gmerlin-1.2.0~dfsg/0000755000175000017500000000000012062133312014062 5ustar alessioalessiogmerlin-1.2.0~dfsg/lib/0000755000175000017500000000000011764363441014650 5ustar alessioalessiogmerlin-1.2.0~dfsg/lib/transcoder.c0000644000175000017500000030022011764363410017151 0ustar alessioalessio/***************************************************************** * gmerlin - a general purpose multimedia framework and applications * * Copyright (c) 2001 - 2011 Members of the Gmerlin project * gmerlin-general@lists.sourceforge.net * http://gmerlin.sourceforge.net * * 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 of the License, 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 this program. If not, see . * *****************************************************************/ #include #include #include #include // mkdir() #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include // #define DUMP_VIDEO_TIMESTAMPS // #define DUMP_AUDIO_TIMESTAMPS #define LOG_DOMAIN "transcoder" #define STREAM_STATE_OFF 0 #define STREAM_STATE_ON 1 #define STREAM_STATE_FINISHED 2 #define STREAM_TYPE_AUDIO 0 #define STREAM_TYPE_VIDEO 1 #define STREAM_TYPE_SUBTITLE_TEXT 2 #define STREAM_TYPE_SUBTITLE_OVERLAY 3 #define STREAM_ACTION_FORGET 0 #define STREAM_ACTION_TRANSCODE 1 #define STREAM_ACTION_COPY 2 /* The followings are for subtitles only */ #define STREAM_ACTION_BLEND 3 /* The following is only for text subtitles and means, that they'll be converted to graphical overlays using the text renderer */ #define STREAM_ACTION_TRANSCODE_OVERLAY 4 #define TRANSCODER_STATE_INIT 0 #define TRANSCODER_STATE_RUNNING 1 #define TRANSCODER_STATE_FINISHED 2 #define TRANSCODER_STATE_ERROR 3 /* Language utilities */ static void copy_language(char * dst, const char * src) { if(src) strncpy(dst, src, 3); else *dst = '\0'; } static void get_language(char * in_lang, char * lang, int force, gavl_metadata_t * m) { char * ret; if(in_lang) ret = force ? lang : in_lang; else ret = lang; gavl_metadata_set(m, GAVL_META_LANGUAGE, ret); } typedef struct subtitle_stream_s subtitle_stream_t; typedef struct { int status; int type; int action; int in_index; int out_index; gavl_time_t time; bg_plugin_handle_t * in_handle; bg_input_plugin_t * in_plugin; int do_encode; /* Whether this stream should be really encoded */ int do_decode; /* Whether this stream should be decoded */ int do_copy; /* Whether this stream should be copied */ gavl_compression_info_t ci; gavl_packet_t packet; gavl_metadata_t m; } stream_t; static int set_stream_parameters_general(stream_t * s, const char * name, const bg_parameter_value_t * val) { if(!strcmp(name, "action")) { if(!strcmp(val->val_str, "transcode")) s->action = STREAM_ACTION_TRANSCODE; else if(!strcmp(val->val_str, "copy")) s->action = STREAM_ACTION_COPY; else if(!strcmp(val->val_str, "transcode_overlay")) s->action = STREAM_ACTION_TRANSCODE_OVERLAY; else if(!strcmp(val->val_str, "blend")) s->action = STREAM_ACTION_BLEND; else s->action = STREAM_ACTION_FORGET; return 1; } return 0; } typedef struct { stream_t com; // int do_convert_in; int do_convert_out; gavl_audio_converter_t * cnv_out; bg_audio_filter_chain_t * fc; gavl_audio_frame_t * out_frame; gavl_audio_frame_t * pipe_frame; gavl_audio_format_t in_format; gavl_audio_format_t pipe_format; gavl_audio_format_t out_format; bg_read_audio_func_t in_func; void * in_data; int in_stream; /* Set by set_parameter */ bg_gavl_audio_options_t options; /* Do normalization */ int normalize; int64_t samples_to_read; /* Samples to read (in OUTPUT samplerate) */ int64_t samples_read; /* Samples read so far (in OUTPUT samplerate) */ int initialized; gavl_peak_detector_t * peak_detector; gavl_volume_control_t * volume_control; char in_language[4]; char out_language[4]; int force_language; } audio_stream_t; static void set_audio_parameter_general(void * data, const char * name, const bg_parameter_value_t * val) { audio_stream_t * stream; stream = (audio_stream_t*)data; if(!name) return; if(!strcmp(name, "normalize")) { stream->normalize = val->val_i; return; } if(!strcmp(name, "in_language")) { copy_language(stream->in_language, val->val_str); return; } if(!strcmp(name, "language")) { copy_language(stream->out_language, val->val_str); return; } if(!strcmp(name, "force_language")) { stream->force_language = val->val_i; return; } if(set_stream_parameters_general(&stream->com, name, val)) return; else if(bg_gavl_audio_set_parameter(&stream->options, name, val)) return; } typedef struct { stream_t com; bg_video_filter_chain_t * fc; gavl_video_frame_t * frame; gavl_video_format_t in_format; gavl_video_format_t out_format; int64_t frames_written; /* Set by set_parameter */ bg_gavl_video_options_t options; /* Data source */ bg_read_video_func_t in_func; void * in_data; int in_stream; /* Other stuff */ int initialized; int64_t start_time_scaled; /* Whether 2-pass transcoding is requested */ int twopass; char * stats_file; /* Subtitle streams for blending */ int num_subtitle_streams; subtitle_stream_t ** subtitle_streams; int b_frames_seen; int flush_b_frames; } video_stream_t; static void set_video_parameter_general(void * data, const char * name, const bg_parameter_value_t * val) { video_stream_t * stream; stream = (video_stream_t*)data; if(!name) return; if(!strcmp(name, "twopass")) stream->twopass = val->val_i; if(set_stream_parameters_general(&stream->com, name, val)) return; else if(bg_gavl_video_set_parameter(&stream->options, name, val)) return; } struct subtitle_stream_s { stream_t com; gavl_video_converter_t * cnv; int do_convert; gavl_overlay_t ovl1, ovl2; gavl_overlay_t * current_ovl; gavl_overlay_t * next_ovl; int has_current; int has_next; gavl_overlay_blend_context_t * blend_context; int video_stream; gavl_video_format_t in_format; gavl_video_format_t out_format; int do_blend; /* Set by check_video_blend() */ int eof; /* Set STREAM finished not before the last subtitle expired */ char in_language[4]; char out_language[4]; int force_language; int64_t time_offset; int64_t time_offset_scaled; }; typedef struct { subtitle_stream_t com; bg_text_renderer_t * textrenderer; char * text; int text_alloc; gavl_time_t subtitle_start; gavl_time_t subtitle_duration; } subtitle_text_stream_t; static void set_subtitle_parameter_general(void * data, const char * name, const bg_parameter_value_t * val) { subtitle_stream_t * stream; stream = (subtitle_stream_t*)data; if(!name) return; if(!strcmp(name, "video_stream")) stream->video_stream = val->val_i-1; else if(!strcmp(name, "in_language")) { copy_language(stream->in_language, val->val_str); return; } else if(!strcmp(name, "language")) { copy_language(stream->out_language, val->val_str); return; } else if(!strcmp(name, "force_language")) { stream->force_language = val->val_i; return; } else if(!strcmp(name, "time_offset")) { stream->time_offset = (int64_t)(val->val_f * GAVL_TIME_SCALE + 0.5); return; } else if(set_stream_parameters_general(&stream->com, name, val)) return; } struct bg_transcoder_s { int num_audio_streams; int num_video_streams; int num_subtitle_text_streams; int num_subtitle_overlay_streams; int num_audio_streams_real; int num_video_streams_real; int num_subtitle_text_streams_real; int num_subtitle_overlay_streams_real; audio_stream_t * audio_streams; video_stream_t * video_streams; subtitle_text_stream_t * subtitle_text_streams; subtitle_stream_t * subtitle_overlay_streams; float percentage_done; gavl_time_t remaining_time; /* Remaining time (Transcoding time, NOT track time!!!) */ double last_seconds; int state; bg_plugin_handle_t * in_handle; bg_input_plugin_t * in_plugin; bg_track_info_t * track_info; bg_plugin_handle_t * out_handle; /* Set by set_parameter */ char * name; char * location; char * plugin; int track; gavl_time_t start_time; gavl_time_t end_time; int set_start_time; int set_end_time; int prefer_edl; gavl_metadata_t metadata; /* General configuration stuff */ char * output_directory; char * output_path; char * subdir; int delete_incomplete; int send_finished; /* Timing stuff */ gavl_timer_t * timer; gavl_time_t time; /* Duration of the section to be transcoded */ gavl_time_t duration; char * output_filename; int is_url; /* Message queues */ bg_msg_queue_list_t * message_queues; /* Multi threading stuff */ pthread_t thread; int do_stop; pthread_mutex_t stop_mutex; /* Multipass */ int total_passes; int pass; bg_plugin_registry_t * plugin_reg; /* Track we are created from */ bg_transcoder_track_t * transcoder_track; /* Encoder frontend */ bg_encoder_t * enc; /* Postprocess only */ int pp_only; bg_encoder_callbacks_t cb; char ** output_files; int num_output_files; }; static void add_output_file(bg_transcoder_t * t, const char * filename) { t->output_files = realloc(t->output_files, (t->num_output_files+2) * sizeof(*t->output_files)); memset(t->output_files + t->num_output_files, 0, 2 * sizeof(*t->output_files)); t->output_files[t->num_output_files] = bg_strdup(NULL, filename); t->num_output_files++; } static void free_output_files(bg_transcoder_t * t) { int i = 0; for(i = 0; i < t->num_output_files; i++) free(t->output_files[i]); if(t->output_files) free(t->output_files); } static void log_transcoding_time(bg_transcoder_t * t) { gavl_time_t transcoding_time; char time_str[GAVL_TIME_STRING_LEN]; transcoding_time = gavl_timer_get(t->timer); gavl_time_prettyprint(transcoding_time, time_str); bg_log(BG_LOG_INFO, LOG_DOMAIN, "Transcoding took %s (%.2f %% of realtime duration)", time_str, 100.0 * gavl_time_to_seconds(transcoding_time) / gavl_time_to_seconds(t->duration)); } static const bg_parameter_info_t parameters[] = { { .name = "output_path", .long_name = TRS("Output Directory"), .type = BG_PARAMETER_DIRECTORY, .val_default = { .val_str = "." }, }, { .name = "delete_incomplete", .long_name = TRS("Delete incomplete output files"), .type = BG_PARAMETER_CHECKBUTTON, .val_default = { .val_i = 1 }, .help_string = TRS("Delete the encoded files if you hit the stop button. \ This option will automatically be disabled, when the track is an URL"), }, { .name = "cleanup_pp", .long_name = TRS("Clean up after postprocessing"), .type = BG_PARAMETER_CHECKBUTTON, .help_string = TRS("Clean up all encoded files, which were postprocessed"), }, { .name = "send_finished", .long_name = TRS("Send finished files to player"), .type = BG_PARAMETER_CHECKBUTTON, .val_default = { .val_i = 1 }, }, { /* End of parameters */ } }; void bg_transcoder_set_parameter(void * data, const char * name, const bg_parameter_value_t * val) { bg_transcoder_t * w = (bg_transcoder_t*)data; if(!name) return; if(!strcmp(name, "output_path")) { w->output_path = bg_strdup(w->output_path, val->val_str); } else if(!strcmp(name, "delete_incomplete")) { w->delete_incomplete = val->val_i; } else if(!strcmp(name, "send_finished")) { w->send_finished = val->val_i; } } const bg_parameter_info_t * bg_transcoder_get_parameters() { return parameters; } /* Message stuff */ typedef struct { int id; int num; } message_num_t; static void set_message_num(bg_msg_t * msg, const void * data) { message_num_t * num = (message_num_t *)data; bg_msg_set_id(msg, num->id); bg_msg_set_arg_int(msg, 0, num->num); } void bg_transcoder_send_msg_num_audio_streams(bg_msg_queue_list_t * l, int num) { message_num_t n; n.id = BG_TRANSCODER_MSG_NUM_AUDIO_STREAMS; n.num = num; bg_msg_queue_list_send(l, set_message_num, &n); } void bg_transcoder_send_msg_num_video_streams(bg_msg_queue_list_t * l, int num) { message_num_t n; n.id = BG_TRANSCODER_MSG_NUM_VIDEO_STREAMS; n.num = num; bg_msg_queue_list_send(l, set_message_num, &n); } typedef struct { int id; int index; gavl_audio_format_t * ifmt; gavl_audio_format_t * ofmt; } message_af_t; static void set_message_audio_format(bg_msg_t * msg, const void * data) { message_af_t * m = (message_af_t *)data; bg_msg_set_id(msg, m->id); bg_msg_set_arg_int(msg, 0, m->index); bg_msg_set_arg_audio_format(msg, 1, m->ifmt); bg_msg_set_arg_audio_format(msg, 2, m->ofmt); } void bg_transcoder_send_msg_audio_format(bg_msg_queue_list_t * l, int index, gavl_audio_format_t * input_format, gavl_audio_format_t * output_format) { message_af_t m; m.id = BG_TRANSCODER_MSG_AUDIO_FORMAT; m.index = index; m.ifmt = input_format; m.ofmt = output_format; bg_msg_queue_list_send(l, set_message_audio_format, &m); } typedef struct { int id; int index; gavl_video_format_t * ifmt; gavl_video_format_t * ofmt; } message_vf_t; static void set_message_video_format(bg_msg_t * msg, const void * data) { message_vf_t * m = (message_vf_t *)data; bg_msg_set_id(msg, m->id); bg_msg_set_arg_int(msg, 0, m->index); bg_msg_set_arg_video_format(msg, 1, m->ifmt); bg_msg_set_arg_video_format(msg, 2, m->ofmt); } void bg_transcoder_send_msg_video_format(bg_msg_queue_list_t * l, int index, gavl_video_format_t * input_format, gavl_video_format_t * output_format) { message_vf_t m; m.id = BG_TRANSCODER_MSG_VIDEO_FORMAT; m.index = index; m.ifmt = input_format; m.ofmt = output_format; bg_msg_queue_list_send(l, set_message_video_format, &m); } typedef struct { const char * name; int pp_only; } message_file_t; static void set_message_file(bg_msg_t * msg, const void * data) { message_file_t * m = (message_file_t *)data; bg_msg_set_id(msg, BG_TRANSCODER_MSG_FILE); bg_msg_set_arg_string(msg, 0, m->name); bg_msg_set_arg_int(msg, 1, m->pp_only); } void bg_transcoder_send_msg_file(bg_msg_queue_list_t * l, const char * filename, int pp_only) { message_file_t m; m.name = filename; m.pp_only = pp_only; bg_msg_queue_list_send(l, set_message_file, &m); } typedef struct { float perc; gavl_time_t rem; } message_progress_t; static void set_message_progress(bg_msg_t * msg, const void * data) { message_progress_t * m = (message_progress_t *)data; bg_msg_set_id(msg, BG_TRANSCODER_MSG_PROGRESS); bg_msg_set_arg_float(msg, 0, m->perc); bg_msg_set_arg_time(msg, 1, m->rem); } void bg_transcoder_send_msg_progress(bg_msg_queue_list_t * l, float percentage_done, gavl_time_t remaining_time) { message_progress_t n; n.perc = percentage_done; n.rem = remaining_time; bg_msg_queue_list_send(l, set_message_progress, &n); } static void set_message_finished(bg_msg_t * msg, const void * data) { bg_msg_set_id(msg, BG_TRANSCODER_MSG_FINISHED); } void bg_transcoder_send_msg_finished(bg_msg_queue_list_t * l) { bg_msg_queue_list_send(l, set_message_finished, NULL); } static void set_message_start(bg_msg_t * msg, const void * data) { bg_msg_set_id(msg, BG_TRANSCODER_MSG_START); bg_msg_set_arg_string(msg, 0, (char*)data); } void bg_transcoder_send_msg_start(bg_msg_queue_list_t * l, char * what) { bg_msg_queue_list_send(l, set_message_start, what); } static void set_message_error(bg_msg_t * msg, const void * data) { bg_msg_set_id(msg, BG_TRANSCODER_MSG_ERROR); } void bg_transcoder_send_msg_error(bg_msg_queue_list_t * l) { bg_msg_queue_list_send(l, set_message_error, NULL); } static void set_message_metadata(bg_msg_t * msg, const void * data) { bg_msg_set_id(msg, BG_TRANSCODER_MSG_METADATA); bg_msg_set_arg_metadata(msg, 0, (const gavl_metadata_t*)data); } void bg_transcoder_send_msg_metadata(bg_msg_queue_list_t * l, gavl_metadata_t * m) { bg_msg_queue_list_send(l, set_message_metadata, m); } /* */ static int decode_video_frame(void * priv, gavl_video_frame_t * f, int stream) { video_stream_t * s; bg_transcoder_t * t; int result; t = (bg_transcoder_t *)priv; s = &t->video_streams[stream]; result = s->com.in_plugin->read_video(s->com.in_handle->priv, f, s->com.in_index); if(!result) return 0; #ifdef DUMP_VIDEO_TIMESTAMPS bg_debug("Input timestamp (video): %"PRId64" Offset: %"PRId64"\n", f->timestamp, s->start_time_scaled); #endif /* Check for end of stream */ if((t->end_time != GAVL_TIME_UNDEFINED) && (gavl_time_unscale(s->in_format.timescale, f->timestamp) >= t->end_time)) return 0; /* Correct timestamps */ if(s->start_time_scaled) { f->timestamp -= s->start_time_scaled; if(f->timestamp < 0) f->timestamp = 0; } return 1; } static void init_audio_stream(audio_stream_t * ret, bg_transcoder_track_audio_t * s, int in_index, bg_plugin_registry_t * plugin_reg) { ret->com.type = STREAM_TYPE_AUDIO; /* Default options */ ret->volume_control = gavl_volume_control_create(); ret->peak_detector = gavl_peak_detector_create(); /* Create converter */ bg_gavl_audio_options_init(&ret->options); ret->cnv_out = gavl_audio_converter_create(); ret->fc = bg_audio_filter_chain_create(&ret->options, plugin_reg); /* Apply parameters */ bg_cfg_section_apply(s->general_section, bg_transcoder_track_audio_get_general_parameters(), set_audio_parameter_general, ret); bg_cfg_section_apply(s->filter_section, s->filter_parameters, bg_audio_filter_chain_set_parameter, ret->fc); ret->com.in_index = in_index; } static void start_audio_stream_i(audio_stream_t * ret, bg_plugin_handle_t * in_handle) { ret->com.in_handle = in_handle; ret->com.in_plugin = (bg_input_plugin_t*)(in_handle->plugin); /* Set stream */ if(ret->com.in_plugin->set_audio_stream) { if(ret->com.do_decode) ret->com.in_plugin->set_audio_stream(ret->com.in_handle->priv, ret->com.in_index, BG_STREAM_ACTION_DECODE); else if(ret->com.do_copy) ret->com.in_plugin->set_audio_stream(ret->com.in_handle->priv, ret->com.in_index, BG_STREAM_ACTION_READRAW); else ret->com.in_plugin->set_audio_stream(ret->com.in_handle->priv, ret->com.in_index, BG_STREAM_ACTION_OFF); } } static void init_video_stream(video_stream_t * ret, bg_transcoder_track_video_t * s, int in_index, bg_plugin_registry_t * plugin_reg) { ret->com.type = STREAM_TYPE_VIDEO; /* Default options */ bg_gavl_video_options_init(&ret->options); /* Create converter */ ret->fc = bg_video_filter_chain_create(&ret->options, plugin_reg); /* Apply parameters */ bg_cfg_section_apply(s->general_section, bg_transcoder_track_video_get_general_parameters(), set_video_parameter_general, ret); bg_cfg_section_apply(s->filter_section, s->filter_parameters, bg_video_filter_chain_set_parameter, ret->fc); ret->com.in_index = in_index; } static void start_video_stream_i(video_stream_t * ret, bg_plugin_handle_t * in_handle) { ret->com.in_handle = in_handle; ret->com.in_plugin = (bg_input_plugin_t*)(in_handle->plugin); /* Set stream */ if(ret->com.in_plugin->set_video_stream) { if(ret->com.do_decode) ret->com.in_plugin->set_video_stream(ret->com.in_handle->priv, ret->com.in_index, BG_STREAM_ACTION_DECODE); else if(ret->com.do_copy) ret->com.in_plugin->set_video_stream(ret->com.in_handle->priv, ret->com.in_index, BG_STREAM_ACTION_READRAW); else ret->com.in_plugin->set_video_stream(ret->com.in_handle->priv, ret->com.in_index, BG_STREAM_ACTION_OFF); } } static void init_subtitle_overlay_stream(subtitle_stream_t * ret, bg_transcoder_track_subtitle_overlay_t * s) { ret->com.type = STREAM_TYPE_SUBTITLE_OVERLAY; /* Apply parameters */ bg_cfg_section_apply(s->general_section, s->general_parameters, set_subtitle_parameter_general, ret); ret->com.in_index = s->in_index; if(ret->com.action == STREAM_ACTION_BLEND) { ret->blend_context = gavl_overlay_blend_context_create(); } ret->cnv = gavl_video_converter_create(); } static void init_subtitle_text_stream(subtitle_text_stream_t * ret, bg_transcoder_track_subtitle_text_t * s) { ret->com.com.type = STREAM_TYPE_SUBTITLE_TEXT; /* Apply parameters */ bg_cfg_section_apply(s->general_section, s->general_parameters, set_subtitle_parameter_general, ret); ret->com.com.in_index = s->in_index; if(ret->com.com.action == STREAM_ACTION_BLEND) { ret->com.blend_context = gavl_overlay_blend_context_create(); ret->textrenderer = bg_text_renderer_create(); bg_cfg_section_apply(s->textrenderer_section, bg_text_renderer_get_parameters(), bg_text_renderer_set_parameter, ret->textrenderer); } else if(ret->com.com.action == STREAM_ACTION_TRANSCODE_OVERLAY) { ret->textrenderer = bg_text_renderer_create(); bg_cfg_section_apply(s->textrenderer_section, bg_text_renderer_get_parameters(), bg_text_renderer_set_parameter, ret->textrenderer); ret->com.cnv = gavl_video_converter_create(); } } static void start_subtitle_stream_i(subtitle_stream_t * ret, bg_plugin_handle_t * in_handle) { ret->com.in_handle = in_handle; ret->com.in_plugin = (bg_input_plugin_t*)(in_handle->plugin); /* Set stream */ if(ret->com.in_plugin->set_subtitle_stream) { if(ret->com.action != STREAM_ACTION_FORGET) ret->com.in_plugin->set_subtitle_stream(ret->com.in_handle->priv, ret->com.in_index, BG_STREAM_ACTION_DECODE); else ret->com.in_plugin->set_subtitle_stream(ret->com.in_handle->priv, ret->com.in_index, BG_STREAM_ACTION_OFF); } } static void set_input_formats(bg_transcoder_t * ret) { int i; for(i = 0; i < ret->num_audio_streams; i++) { if(ret->audio_streams[i].com.do_decode || ret->audio_streams[i].com.do_copy) gavl_audio_format_copy(&ret->audio_streams[i].in_format, &ret->track_info->audio_streams[ret->audio_streams[i].com.in_index].format); } for(i = 0; i < ret->num_video_streams; i++) { if(ret->video_streams[i].com.do_decode || ret->video_streams[i].com.do_copy) gavl_video_format_copy(&ret->video_streams[i].in_format, &ret->track_info->video_streams[ret->video_streams[i].com.in_index].format); } for(i = 0; i < ret->num_subtitle_overlay_streams; i++) { if(ret->subtitle_overlay_streams[i].com.do_decode) gavl_video_format_copy(&ret->subtitle_overlay_streams[i].in_format, &ret->track_info->subtitle_streams[ret->subtitle_overlay_streams[i].com.in_index].format); } for(i = 0; i < ret->num_subtitle_text_streams; i++) { if(ret->subtitle_text_streams[i].com.com.do_decode) gavl_video_format_copy(&ret->subtitle_text_streams[i].com.in_format, &ret->track_info->subtitle_streams[ret->subtitle_text_streams[i].com.com.in_index].format); } } static void add_audio_stream(audio_stream_t * ret, bg_transcoder_t * t) { ret->in_func = ret->com.in_plugin->read_audio; ret->in_data = ret->com.in_handle->priv; ret->in_stream = ret->com.in_index; /* We set the frame size so we have roughly half second long audio chunks */ ret->in_format.samples_per_frame = gavl_time_to_samples(ret->in_format.samplerate, GAVL_TIME_SCALE/2); bg_audio_filter_chain_connect_input(ret->fc, ret->in_func, ret->in_data, ret->in_stream); bg_audio_filter_chain_init(ret->fc, &ret->in_format, &ret->pipe_format); ret->pipe_format.samples_per_frame = gavl_time_to_samples(ret->pipe_format.samplerate, GAVL_TIME_SCALE/2); ret->in_func = bg_audio_filter_chain_read; ret->in_data = ret->fc; ret->in_stream = 0; gavl_audio_format_copy(&ret->out_format, &ret->pipe_format); /* Decide language */ get_language(ret->in_language, ret->out_language, ret->force_language, &ret->com.m); /* Add the audio stream */ ret->com.out_index = bg_encoder_add_audio_stream(t->enc, &ret->com.m, &ret->out_format, ret->com.in_index); } static void add_audio_stream_compressed(audio_stream_t * ret, bg_transcoder_t * t) { /* Decide language */ get_language(ret->in_language, ret->out_language, ret->force_language, &ret->com.m); /* Add the audio stream */ ret->com.out_index = bg_encoder_add_audio_stream_compressed(t->enc, &ret->com.m, &ret->in_format, &ret->com.ci, ret->com.in_index); } static void add_subtitle_text_stream(subtitle_text_stream_t * ret, bg_transcoder_track_subtitle_text_t * s, bg_transcoder_t * t) { if(ret->com.com.action == STREAM_ACTION_TRANSCODE) { /* Decide language */ get_language(ret->com.in_language, ret->com.out_language, ret->com.force_language, &ret->com.com.m); gavl_video_format_copy(&ret->com.out_format, &ret->com.in_format); /* TODO: timescale might get changed by the encoder!!! */ ret->com.com.out_index = bg_encoder_add_subtitle_text_stream(t->enc, &ret->com.com.m, ret->com.out_format.timescale, ret->com.com.in_index); } else if(ret->com.com.action == STREAM_ACTION_TRANSCODE_OVERLAY) { /* Get the video format for overlay encoding. This is a bit nasty, since we have no idea yet, how the format will look like (the video output format isn't known by now). We'll copy the format, which was passed to the video encoder and hope that the overlay encoder will choose a proper pixelformat for us. Then, we pass the same format as *frame* format to the textrenderer */ if(t->video_streams[ret->com.video_stream].com.do_encode) { gavl_video_format_copy(&ret->com.out_format, &t->video_streams[ret->com.video_stream].out_format); } else { /* Video stream won't get encoded: Use video format associatd with the text subtitle stream */ gavl_video_format_copy(&ret->com.out_format, &ret->com.in_format); } /* Decide language */ get_language(ret->com.in_language, ret->com.out_language, ret->com.force_language, &ret->com.com.m); ret->com.com.out_index = bg_encoder_add_subtitle_overlay_stream(t->enc, &ret->com.com.m, &ret->com.out_format, ret->com.com.in_index, BG_STREAM_SUBTITLE_TEXT); } } static void add_subtitle_overlay_stream(subtitle_stream_t * ret, bg_transcoder_track_subtitle_overlay_t * s, bg_transcoder_t * t) { gavl_video_format_copy(&ret->out_format, &ret->in_format); /* Decide language */ get_language(ret->in_language, ret->out_language, ret->force_language, &ret->com.m); ret->com.out_index = bg_encoder_add_subtitle_overlay_stream(t->enc, &ret->com.m, &ret->out_format, ret->com.in_index, BG_STREAM_SUBTITLE_OVERLAY); } static void add_video_stream(video_stream_t * ret, bg_transcoder_t * t) { ret->in_func = decode_video_frame; ret->in_data = t; ret->in_stream = ret->com.in_index; bg_video_filter_chain_connect_input(ret->fc, ret->in_func, ret->in_data, ret->in_stream); bg_video_filter_chain_init(ret->fc, &ret->in_format, &ret->out_format); ret->in_func = bg_video_filter_chain_read; ret->in_data = ret->fc; ret->in_stream = 0; /* Add the video stream */ ret->com.out_index = bg_encoder_add_video_stream(t->enc, &ret->com.m, &ret->out_format, ret->com.in_index); } static void add_video_stream_compressed(video_stream_t * ret, bg_transcoder_t * t) { /* Add the video stream */ ret->com.out_index = bg_encoder_add_video_stream_compressed(t->enc, &ret->com.m, &ret->in_format, &ret->com.ci, ret->com.in_index); } static int set_video_pass(bg_transcoder_t * t, int i) { video_stream_t * s; s = &t->video_streams[i]; if(!s->twopass) return 1; if(!s->stats_file) { s->stats_file = bg_sprintf("%s/%s_video_%02d.stats", t->output_directory, t->name, i+1); bg_log(BG_LOG_INFO, LOG_DOMAIN, "Using statistics file: %s", s->stats_file); } bg_encoder_set_video_pass(t->enc, s->com.out_index, t->pass, t->total_passes, s->stats_file); return 1; } static int audio_iteration(audio_stream_t*s, bg_transcoder_t * t) { int ret = 1; int num_samples; int samples_decoded; gavl_audio_frame_t * frame; /* Get one frame worth of input data */ if(!s->initialized) { if((t->start_time != GAVL_TIME_UNDEFINED) && (t->end_time != GAVL_TIME_UNDEFINED) && (t->end_time > t->start_time)) { s->samples_to_read = gavl_time_to_samples(s->out_format.samplerate, t->end_time - t->start_time); } else if(t->end_time != GAVL_TIME_UNDEFINED) { s->samples_to_read = gavl_time_to_samples(s->out_format.samplerate, t->end_time); } else s->samples_to_read = 0; /* Zero == Infinite */ s->initialized = 1; } if(s->com.do_copy) { if(!s->com.in_plugin->read_audio_packet(s->com.in_handle->priv, s->com.in_index, &s->com.packet)) { /* EOF */ s->com.status = STREAM_STATE_FINISHED; return ret; } ret = bg_encoder_write_audio_packet(t->enc, &s->com.packet, s->com.out_index); s->samples_read += s->com.packet.duration; if(s->samples_to_read && (s->samples_to_read <= s->samples_read)) s->com.status = STREAM_STATE_FINISHED; s->com.time = gavl_samples_to_time(s->in_format.samplerate, s->samples_read); } else { if(s->samples_to_read && (s->samples_read + s->out_format.samples_per_frame > s->samples_to_read)) num_samples = s->samples_to_read - s->samples_read; else num_samples = s->out_format.samples_per_frame; if(s->do_convert_out) frame = s->pipe_frame; else frame = s->out_frame; samples_decoded = s->in_func(s->in_data, frame, s->in_stream, num_samples); /* Nothing more to transcode */ if(!samples_decoded) { s->com.status = STREAM_STATE_FINISHED; return ret; } /* Volume normalization */ if(s->normalize) { if(t->pass == t->total_passes) { gavl_volume_control_apply(s->volume_control, frame); } else if((t->pass > 1) && (t->pass < t->total_passes)) frame = NULL; } /* Output conversion */ if(s->do_convert_out) { gavl_audio_convert(s->cnv_out, s->pipe_frame, s->out_frame); frame = s->out_frame; } /* Update sample counter before the frame is set to NULL after peak-detection */ s->samples_read += frame->valid_samples; /* Peak detection is done for the final frame */ if(s->normalize) { if(t->pass == 1) { gavl_peak_detector_update(s->peak_detector, frame); frame = NULL; } } if(frame) { #ifdef DUMP_AUDIO_TIMESTAMPS bg_debug("Output timestamp (audio): %"PRId64"\n", frame->timestamp); #endif ret = bg_encoder_write_audio_frame(t->enc, frame, s->com.out_index); } s->com.time = gavl_samples_to_time(s->out_format.samplerate, s->samples_read); } /* Last samples */ if(s->samples_to_read && (s->samples_to_read <= s->samples_read)) s->com.status = STREAM_STATE_FINISHED; if(!ret) bg_log(BG_LOG_ERROR, LOG_DOMAIN, "Encoding audio failed"); return ret; } static void correct_subtitle_timestamp(subtitle_stream_t * s, int64_t * start, int64_t * duration, bg_transcoder_t * t) { /* Add offset */ *start += gavl_time_scale(s->in_format.timescale, s->time_offset); /* Correct timestamps */ if(t->start_time != GAVL_TIME_UNDEFINED) { *start -= gavl_time_scale(s->in_format.timescale, t->start_time); if(*start < 0) { *duration += *start; if(*duration < 0) *duration = 0; *start = 0; } } /* Rescale */ *start = gavl_time_rescale(s->in_format.timescale, s->out_format.timescale, *start); *duration = gavl_time_rescale(s->in_format.timescale, s->out_format.timescale, *duration); } static int decode_subtitle_overlay(subtitle_stream_t * s, bg_transcoder_t * t, gavl_overlay_t * ovl) { int result; subtitle_text_stream_t * st; result = s->com.in_plugin->has_subtitle(s->com.in_handle->priv, s->com.in_index); if(!result) return 0; if(s->com.type == STREAM_TYPE_SUBTITLE_TEXT) { st = (subtitle_text_stream_t*)s; result = s->com.in_plugin->read_subtitle_text(s->com.in_handle->priv, &st->text, &st->text_alloc, &st->subtitle_start, &st->subtitle_duration, s->com.in_index); if(!result || ((t->end_time != GAVL_TIME_UNDEFINED) && (gavl_time_unscale(s->in_format.timescale, st->subtitle_start) >= t->end_time))) { s->eof = 1; return 0; } correct_subtitle_timestamp(&st->com, &st->subtitle_start, &st->subtitle_duration, t); ovl->frame->timestamp = st->subtitle_start; ovl->frame->duration = st->subtitle_duration; bg_text_renderer_render(st->textrenderer, st->text, ovl); } else { result = s->com.in_plugin->read_subtitle_overlay(s->com.in_handle->priv, ovl, s->com.in_index); if(!result || ((t->end_time != GAVL_TIME_UNDEFINED) && (gavl_time_unscale(s->in_format.timescale, ovl->frame->timestamp) >= t->end_time))) { s->eof = 1; return 0; } correct_subtitle_timestamp(s, &ovl->frame->timestamp, &ovl->frame->duration, t); } return 1; } static int decode_subtitle_text(subtitle_text_stream_t * s, bg_transcoder_t * t) { int result; result = s->com.com.in_plugin->has_subtitle(s->com.com.in_handle->priv, s->com.com.in_index); if(!result) return 0; result = s->com.com.in_plugin->read_subtitle_text(s->com.com.in_handle->priv, &s->text, &s->text_alloc, &s->subtitle_start, &s->subtitle_duration, s->com.com.in_index); if(!result || ((t->end_time != GAVL_TIME_UNDEFINED) && (gavl_time_unscale(s->com.in_format.timescale, s->subtitle_start) >= t->end_time))) { s->com.eof = 1; return 0; } correct_subtitle_timestamp(&s->com, &s->subtitle_start, &s->subtitle_duration, t); return 1; } static int check_video_blend(video_stream_t * vs, bg_transcoder_t * t, int64_t time) { gavl_overlay_t * tmp_ovl; int i; subtitle_stream_t * ss; int ret = 0; int current_changed = 0; for(i = 0; i < vs->num_subtitle_streams; i++) { ss = vs->subtitle_streams[i]; if(ss->com.status != STREAM_STATE_ON) continue; /* Check if the overlay expired */ if(ss->has_current) { if(bg_overlay_too_old(time, ss->current_ovl->frame->timestamp, ss->current_ovl->frame->duration)) { tmp_ovl = ss->current_ovl; ss->current_ovl = ss->next_ovl; ss->next_ovl = tmp_ovl; ss->has_current = ss->has_next; ss->has_next = 0; if(ss->has_current) current_changed = 1; } } /* Check if the next overlay replaces the current one */ if(ss->has_next) { if(!bg_overlay_too_new(time, ss->next_ovl->frame->timestamp)) { tmp_ovl = ss->current_ovl; ss->current_ovl = ss->next_ovl; ss->next_ovl = tmp_ovl; ss->has_current = 1; ss->has_next = 0; if(bg_overlay_too_old(time, ss->current_ovl->frame->timestamp, ss->current_ovl->frame->duration)) ss->has_current = 0; else current_changed = 1; } } if(!ss->has_current && !ss->eof) { if(decode_subtitle_overlay(ss, t, ss->current_ovl)) { ss->has_current = 1; current_changed = 1; } else continue; } if(!ss->has_next && !ss->eof) { if(decode_subtitle_overlay(ss, t, ss->next_ovl)) ss->has_next = 1; } if(ss->has_current && !bg_overlay_too_new(time, ss->current_ovl->frame->timestamp)) { ss->do_blend = 1; ret = 1; } else ss->do_blend = 0; if(current_changed) gavl_overlay_blend_context_set_overlay(ss->blend_context, ss->current_ovl); if(!ss->has_current && !ss->has_next && ss->eof) ss->com.status = STREAM_STATE_FINISHED; } return ret; } #define SWAP_FRAMES \ tmp_frame=s->in_frame_1;\ s->in_frame_1=s->in_frame_2;\ s->in_frame_2=tmp_frame static int video_iteration(video_stream_t * s, bg_transcoder_t * t) { int ret = 1; int i; int result; if(!s->initialized) { if(t->start_time != GAVL_TIME_UNDEFINED) { s->start_time_scaled = gavl_time_scale(s->in_format.timescale, t->start_time); // bg_video_converter_reset(s->cnv, s->start_time_scaled); } s->initialized = 1; } if(s->com.do_copy) { if(!s->com.in_plugin->read_video_packet(s->com.in_handle->priv, s->com.in_index, &s->com.packet)) { /* EOF */ s->com.status = STREAM_STATE_FINISHED; return ret; } if((s->com.packet.flags & GAVL_PACKET_TYPE_MASK) != GAVL_PACKET_TYPE_B) { if(s->flush_b_frames) { s->com.status = STREAM_STATE_FINISHED; return ret; } s->com.time = gavl_time_unscale(s->in_format.timescale, s->com.packet.pts + s->com.packet.duration); if((t->end_time != GAVL_TIME_UNDEFINED) && (s->com.time >= t->end_time)) { if(s->b_frames_seen) s->flush_b_frames = 1; else { s->com.status = STREAM_STATE_FINISHED; return ret; } } } else { s->b_frames_seen = 1; } bg_encoder_write_video_packet(t->enc, &s->com.packet, s->com.out_index); } else { result = s->in_func(s->in_data, s->frame, s->in_stream); if(!result) { s->com.status = STREAM_STATE_FINISHED; /* Set this also for all attached subtitle streams */ for(i = 0; i < s->num_subtitle_streams; i++) s->subtitle_streams[i]->com.status = STREAM_STATE_FINISHED; return ret; } s->com.time = gavl_time_unscale(s->out_format.timescale, s->frame->timestamp + s->frame->duration); if((t->end_time != GAVL_TIME_UNDEFINED) && (s->com.time >= t->end_time)) s->com.status = STREAM_STATE_FINISHED; // if(check_video_blend(s, t, s->com.time)) if(check_video_blend(s, t, s->frame->timestamp)) { for(i = 0; i < s->num_subtitle_streams; i++) { if(s->subtitle_streams[i]->do_blend) { gavl_overlay_blend(s->subtitle_streams[i]->blend_context, s->frame); } } } #ifdef DUMP_VIDEO_TIMESTAMPS bg_debug("Output timestamp (video): %"PRId64"\n", s->frame->timestamp); #endif ret = bg_encoder_write_video_frame(t->enc, s->frame, s->com.out_index); } if(!ret) bg_log(BG_LOG_ERROR, LOG_DOMAIN, "Encoding video failed"); s->frames_written++; return ret; } /* Time offset of 0.5 seconds means, that we encode subtitles maximum 0.5 seconds before the subtitle should appear. This is only interesting for formats, which don't allow random access to subtitles */ #define SUBTITLE_TIME_OFFSET (GAVL_TIME_SCALE/2) static int subtitle_iteration(bg_transcoder_t * t) { int i, ret = 1; subtitle_text_stream_t * st; subtitle_stream_t * ss; video_stream_t * vs; gavl_video_frame_t * tmp_frame; for(i = 0; i < t->num_subtitle_text_streams; i++) { st = &t->subtitle_text_streams[i]; if(!st->com.com.do_encode) continue; if(st->com.eof) { st->com.com.status = STREAM_STATE_FINISHED; continue; } /* Check for decoding */ if(!st->com.has_current) { if(st->com.com.action == STREAM_ACTION_TRANSCODE) { st->com.has_current = decode_subtitle_text(st, t); } else if(st->com.com.action == STREAM_ACTION_TRANSCODE_OVERLAY) { st->com.has_current = decode_subtitle_overlay((subtitle_stream_t*)st, t, &st->com.ovl1); if(st->com.has_current && st->com.do_convert) { gavl_video_convert(st->com.cnv, st->com.ovl1.frame, st->com.ovl2.frame); tmp_frame = st->com.ovl1.frame; st->com.ovl1.frame = st->com.ovl2.frame; st->com.ovl2.frame = tmp_frame; } } } /* Check for encoding */ if(st->com.has_current) { vs = &t->video_streams[st->com.video_stream]; if(!vs->com.do_encode || (st->subtitle_start - vs->com.time < SUBTITLE_TIME_OFFSET)) { if(st->com.com.action == STREAM_ACTION_TRANSCODE) { ret = bg_encoder_write_subtitle_text(t->enc, st->text, st->subtitle_start, st->subtitle_duration, st->com.com.out_index); st->com.com.time = gavl_time_unscale(st->com.out_format.timescale, st->subtitle_start); if(st->subtitle_start > t->time) t->time = st->subtitle_start; } else if(st->com.com.action == STREAM_ACTION_TRANSCODE_OVERLAY) { ret = bg_encoder_write_subtitle_overlay(t->enc, &st->com.ovl1, st->com.com.out_index); st->com.com.time = gavl_time_unscale(st->com.out_format.timescale, st->com.ovl1.frame->timestamp); if(st->com.com.time > t->time) t->time = st->com.com.time; } st->com.has_current = 0; } } if(!ret) bg_log(BG_LOG_ERROR, LOG_DOMAIN, "Encoding subtitles failed"); } if(!ret) return ret; for(i = 0; i < t->num_subtitle_overlay_streams; i++) { ss = &t->subtitle_overlay_streams[i]; if(!ss->com.do_encode) continue; if(ss->eof) { ss->com.status = STREAM_STATE_FINISHED; continue; } /* Check for decoding */ if(!ss->has_current) { ss->has_current = decode_subtitle_overlay(ss, t, &ss->ovl1); if(ss->has_current && ss->do_convert) { gavl_video_convert(ss->cnv, ss->ovl1.frame, ss->ovl2.frame); tmp_frame = ss->ovl1.frame; ss->ovl1.frame = ss->ovl2.frame; ss->ovl2.frame = tmp_frame; } } /* Check for encoding */ if(ss->has_current) { vs = &t->video_streams[ss->video_stream]; if(!vs->com.do_encode || (ss->ovl1.frame->timestamp - vs->com.time < SUBTITLE_TIME_OFFSET)) { ret = bg_encoder_write_subtitle_overlay(t->enc, &ss->ovl1, ss->com.out_index); ss->com.time = gavl_time_unscale(ss->out_format.timescale, ss->ovl1.frame->timestamp); if(ss->com.time > t->time) t->time = ss->com.time; ss->has_current = 0; } } if(!ret) { bg_log(BG_LOG_ERROR, LOG_DOMAIN, "Encoding subtitles failed"); break; } } return ret; } /* Parameter passing for the Transcoder */ #define SP_STR(s) if(!strcmp(name, # s)) \ { \ t->s = bg_strdup(t->s, val->val_str); \ return; \ } #define SP_INT(s) if(!strcmp(name, # s)) \ { \ t->s = val->val_i; \ return; \ } #define SP_TIME(s) if(!strcmp(name, # s)) \ { \ t->s = val->val_time; \ return; \ } static void set_parameter_general(void * data, const char * name, const bg_parameter_value_t * val) { int i, name_len; bg_transcoder_t * t; t = (bg_transcoder_t *)data; if(!name) { /* Set start and end times */ if(!t->set_start_time) t->start_time = GAVL_TIME_UNDEFINED; if(!t->set_end_time) t->end_time = GAVL_TIME_UNDEFINED; /* Replace all '/' by '-' */ if(t->name) { name_len = strlen(t->name); for(i = 0; i < name_len; i++) { if(t->name[i] == '/') t->name[i] = '-'; } } /* Create the subdirectory if necessary */ if(t->subdir) { t->output_directory = bg_sprintf("%s/%s", t->output_path, t->subdir); if(mkdir(t->output_directory, S_IRUSR|S_IWUSR|S_IXUSR|S_IRGRP|S_IXGRP|S_IROTH|S_IWOTH) == -1) { if(errno != EEXIST) { bg_log(BG_LOG_ERROR, LOG_DOMAIN, "Cannot create directory %s: %s, using default", t->output_directory, strerror(errno)); t->output_directory = bg_strdup(t->output_directory, t->output_path); } } else bg_log(BG_LOG_INFO, LOG_DOMAIN, "Created directory %s", t->output_directory); } else t->output_directory = bg_strdup(t->output_directory, t->output_path); return; } SP_STR(name); SP_STR(location); SP_STR(plugin); SP_STR(subdir); SP_INT(track); SP_INT(prefer_edl); SP_INT(set_start_time); SP_INT(set_end_time); SP_TIME(start_time); SP_TIME(end_time); SP_INT(pp_only); } #undef SP_INT #undef SP_TIME #undef SP_STR void bg_transcoder_add_message_queue(bg_transcoder_t * t, bg_msg_queue_t * message_queue) { bg_msg_queue_list_add(t->message_queues, message_queue); } bg_transcoder_t * bg_transcoder_create() { bg_transcoder_t * ret; ret = calloc(1, sizeof(*ret)); ret->timer = gavl_timer_create(); ret->message_queues = bg_msg_queue_list_create(); pthread_mutex_init(&ret->stop_mutex, NULL); return ret; } static void send_init_messages(bg_transcoder_t * t) { int i; char * tmp_string; if(t->pp_only) { tmp_string = bg_sprintf(TR("Postprocessing %s"), t->location); } else if(t->total_passes > 1) { tmp_string = bg_sprintf(TR("Transcoding %s [Track %d, Pass %d/%d]"), t->location, t->track+1, t->pass, t->total_passes); } else { tmp_string = bg_sprintf(TR("Transcoding %s [Track %d]"), t->location, t->track+1); } bg_transcoder_send_msg_start(t->message_queues, tmp_string); bg_log_notranslate(BG_LOG_INFO, LOG_DOMAIN, "%s", tmp_string); free(tmp_string); bg_transcoder_send_msg_metadata(t->message_queues, &t->metadata); tmp_string = bg_metadata_to_string(&t->metadata, 1); if(tmp_string) { bg_log(BG_LOG_INFO, LOG_DOMAIN, "Metadata:\n%s", tmp_string); free(tmp_string); } if(!t->pp_only) { bg_transcoder_send_msg_num_audio_streams(t->message_queues, t->num_audio_streams); for(i = 0; i < t->num_audio_streams; i++) { if(t->audio_streams[i].com.do_decode) { bg_transcoder_send_msg_audio_format(t->message_queues, i, &t->audio_streams[i].in_format, &t->audio_streams[i].out_format); tmp_string = bg_audio_format_to_string(&t->audio_streams[i].in_format, 1); bg_log(BG_LOG_INFO, LOG_DOMAIN, "Audio stream %d input format:\n%s", i+1, tmp_string); free(tmp_string); tmp_string = bg_audio_format_to_string(&t->audio_streams[i].out_format, 1); bg_log(BG_LOG_INFO, LOG_DOMAIN, "Audio stream %d output format:\n%s", i+1, tmp_string); free(tmp_string); } else if(t->audio_streams[i].com.do_copy) { tmp_string = bg_audio_format_to_string(&t->audio_streams[i].in_format, 0); bg_log(BG_LOG_INFO, LOG_DOMAIN, "Audio stream %d format:\n%s", i+1, tmp_string); free(tmp_string); } } bg_transcoder_send_msg_num_video_streams(t->message_queues, t->num_video_streams); for(i = 0; i < t->num_video_streams; i++) { if(t->video_streams[i].com.do_decode) { bg_transcoder_send_msg_video_format(t->message_queues, i, &t->video_streams[i].in_format, &t->video_streams[i].out_format); tmp_string = bg_video_format_to_string(&t->video_streams[i].in_format, 0); bg_log(BG_LOG_INFO, LOG_DOMAIN, "Video stream %d input format:\n%s", i+1, tmp_string); free(tmp_string); tmp_string = bg_video_format_to_string(&t->video_streams[i].out_format, 0); bg_log(BG_LOG_INFO, LOG_DOMAIN, "Video stream %d output format:\n%s", i+1, tmp_string); free(tmp_string); } else if(t->video_streams[i].com.do_copy) { tmp_string = bg_video_format_to_string(&t->video_streams[i].in_format, 0); bg_log(BG_LOG_INFO, LOG_DOMAIN, "Video stream %d format:\n%s", i+1, tmp_string); free(tmp_string); } } for(i = 0; i < t->num_subtitle_text_streams; i++) { if(t->subtitle_text_streams[i].com.com.do_decode) { switch(t->subtitle_text_streams[i].com.com.action) { case STREAM_ACTION_BLEND: bg_log(BG_LOG_INFO, LOG_DOMAIN, "Text subtitle stream %d: Blending onto video stream %d", i+1, t->subtitle_text_streams[i].com.video_stream); break; case STREAM_ACTION_TRANSCODE: case STREAM_ACTION_TRANSCODE_OVERLAY: bg_log(BG_LOG_INFO, LOG_DOMAIN, "Text subtitle stream %d: Exporting to file", i+1); break; } } } for(i = 0; i < t->num_subtitle_overlay_streams; i++) { if(t->subtitle_overlay_streams[i].com.do_decode) { switch(t->subtitle_overlay_streams[i].com.action) { case STREAM_ACTION_BLEND: bg_log(BG_LOG_INFO, LOG_DOMAIN, "Overlay subtitle stream %d: Blending onto video stream %d", i+1, t->subtitle_overlay_streams[i].video_stream); break; case STREAM_ACTION_TRANSCODE: case STREAM_ACTION_TRANSCODE_OVERLAY: bg_log(BG_LOG_INFO, LOG_DOMAIN, "Overlay subtitle stream %d: Exporting to file", i+1); break; } } } } } static void send_file(const char * name) { char * command; command = bg_sprintf("gmerlin_remote -add \"%s\"\n", name); bg_system(command); free(command); } static void send_file_messages(bg_transcoder_t * t) { int i; for(i = 0; i < t->num_output_files; i++) { bg_transcoder_send_msg_file(t->message_queues, t->output_files[i], t->pp_only); if(t->send_finished) send_file(t->output_files[i]); } } static int open_input(bg_transcoder_t * ret) { bg_cfg_section_t * s; const bg_plugin_info_t * plugin_info; plugin_info = bg_plugin_find_by_name(ret->plugin_reg, ret->plugin); if(!plugin_info) { bg_log(BG_LOG_ERROR, LOG_DOMAIN, "Cannot find plugin %s", ret->plugin); goto fail; } s = bg_plugin_registry_get_section(ret->plugin_reg, plugin_info->name); if(s && ret->transcoder_track->input_section) { bg_cfg_section_transfer(ret->transcoder_track->input_section, s); } // fprintf(stderr, "open input %d\n", ret->prefer_edl); if(!bg_input_plugin_load(ret->plugin_reg, ret->location, plugin_info, &ret->in_handle, NULL, ret->prefer_edl)) goto fail; ret->in_plugin = (bg_input_plugin_t*)ret->in_handle->plugin; if(bg_string_is_url(ret->location)) ret->is_url = 1; /* Select track and get track info */ if(ret->in_plugin->get_num_tracks && (ret->track >= ret->in_plugin->get_num_tracks(ret->in_handle->priv))) { bg_log(BG_LOG_ERROR, LOG_DOMAIN, "Invalid track number %d", ret->track); goto fail; } ret->track_info = ret->in_plugin->get_track_info(ret->in_handle->priv, ret->track); if(ret->in_plugin->set_track) ret->in_plugin->set_track(ret->in_handle->priv, ret->track); return 1; fail: return 0; } static void check_compressed(bg_transcoder_t * ret) { int i, j; for(i = 0; i < ret->num_audio_streams; i++) { if(!(ret->audio_streams[i].com.action == STREAM_ACTION_COPY)) continue; /* Check if we can read compressed data */ if(!ret->in_plugin->get_audio_compression_info || !ret->in_plugin->get_audio_compression_info(ret->in_handle->priv, i, &ret->audio_streams[i].com.ci)) { bg_log(BG_LOG_WARNING, LOG_DOMAIN, "Audio stream %d cannot be read compressed", i+1); ret->audio_streams[i].com.action = STREAM_ACTION_TRANSCODE; continue; } /* Check if we can write compressed data */ if(!bg_encoder_writes_compressed_audio(ret->enc, &ret->track_info->audio_streams[i].format, &ret->audio_streams[i].com.ci)) { bg_log(BG_LOG_WARNING, LOG_DOMAIN, "Audio stream %d cannot be written compressed", i+1); ret->audio_streams[i].com.action = STREAM_ACTION_TRANSCODE; continue; } bg_log(BG_LOG_INFO, LOG_DOMAIN, "Copying compressed audio stream %d", i+1); // bg_dprintf("Copying compressed audio stream %d\n", i+1); // gavl_compression_info_dump(&ret->audio_streams[i].com.ci); } for(i = 0; i < ret->num_video_streams; i++) { if(ret->video_streams[i].com.action != STREAM_ACTION_COPY) continue; /* Check if we can read compressed data */ if(!ret->in_plugin->get_video_compression_info || !ret->in_plugin->get_video_compression_info(ret->in_handle->priv, i, &ret->video_streams[i].com.ci)) { bg_log(BG_LOG_WARNING, LOG_DOMAIN, "Video stream %d cannot be read compressed", i+1); ret->video_streams[i].com.action = STREAM_ACTION_TRANSCODE; continue; } /* Check if we need to blend text subtitles */ for(j = 0; j < ret->num_subtitle_text_streams; j++) { if((ret->subtitle_text_streams[i].com.com.action == STREAM_ACTION_BLEND) && (ret->subtitle_text_streams[i].com.video_stream == i)) { bg_log(BG_LOG_WARNING, LOG_DOMAIN, "Not copying video stream %d: Will blend subtitles", i+1); ret->video_streams[i].com.action = STREAM_ACTION_TRANSCODE; break; } } if(ret->video_streams[i].com.action != STREAM_ACTION_COPY) continue; /* Check if we need to blend overlay subtitles */ for(j = 0; j < ret->num_subtitle_overlay_streams; j++) { if((ret->subtitle_overlay_streams[i].com.action == STREAM_ACTION_BLEND) && (ret->subtitle_overlay_streams[i].video_stream == i)) { bg_log(BG_LOG_WARNING, LOG_DOMAIN, "Not copying video stream %d: Will blend subtitles", i+1); ret->video_streams[i].com.action = STREAM_ACTION_TRANSCODE; } } if(ret->video_streams[i].com.action != STREAM_ACTION_COPY) continue; /* Check if we can write compressed data */ if(!bg_encoder_writes_compressed_video(ret->enc, &ret->track_info->video_streams[i].format, &ret->video_streams[i].com.ci)) { bg_log(BG_LOG_WARNING, LOG_DOMAIN, "Video stream %d cannot be written compressed", i+1); ret->video_streams[i].com.action = STREAM_ACTION_TRANSCODE; continue; } bg_log(BG_LOG_INFO, LOG_DOMAIN, "Copying compressed video stream %d", i+1); // bg_dprintf("Copying compressed video stream %d\n", i+1); // gavl_compression_info_dump(&ret->video_streams[i].com.ci); } } static void create_streams(bg_transcoder_t * ret, bg_transcoder_track_t * track) { int i; /* Allocate streams */ ret->num_audio_streams = track->num_audio_streams; if(ret->num_audio_streams) ret->audio_streams = calloc(ret->num_audio_streams, sizeof(*ret->audio_streams)); ret->num_video_streams = track->num_video_streams; if(ret->num_video_streams) ret->video_streams = calloc(ret->num_video_streams, sizeof(*ret->video_streams)); ret->num_subtitle_text_streams = track->num_subtitle_text_streams; if(ret->num_subtitle_text_streams) ret->subtitle_text_streams = calloc(ret->num_subtitle_text_streams, sizeof(*ret->subtitle_text_streams)); ret->num_subtitle_overlay_streams = track->num_subtitle_overlay_streams; if(ret->num_subtitle_overlay_streams) ret->subtitle_overlay_streams = calloc(ret->num_subtitle_overlay_streams, sizeof(*ret->subtitle_overlay_streams)); /* Prepare streams */ ret->num_audio_streams_real = 0; ret->num_video_streams_real = 0; ret->num_subtitle_text_streams_real = 0; ret->num_subtitle_overlay_streams_real = 0; for(i = 0; i < ret->num_audio_streams; i++) { init_audio_stream(&ret->audio_streams[i], &track->audio_streams[i], i, ret->plugin_reg); if(ret->audio_streams[i].com.action == STREAM_ACTION_TRANSCODE) ret->num_audio_streams_real++; } for(i = 0; i < ret->num_video_streams; i++) { init_video_stream(&ret->video_streams[i], &track->video_streams[i], i, ret->plugin_reg); if(ret->video_streams[i].com.action == STREAM_ACTION_TRANSCODE) ret->num_video_streams_real++; } for(i = 0; i < ret->num_subtitle_text_streams; i++) { init_subtitle_text_stream(&ret->subtitle_text_streams[i], &track->subtitle_text_streams[i]); if(ret->subtitle_text_streams[i].com.com.action == STREAM_ACTION_TRANSCODE) ret->num_subtitle_text_streams_real++; else if(ret->subtitle_text_streams[i].com.com.action == STREAM_ACTION_TRANSCODE_OVERLAY) ret->num_subtitle_overlay_streams_real++; } for(i = 0; i < ret->num_subtitle_overlay_streams; i++) { init_subtitle_overlay_stream(&ret->subtitle_overlay_streams[i], &track->subtitle_overlay_streams[i]); if(ret->subtitle_overlay_streams[i].com.action == STREAM_ACTION_TRANSCODE) ret->num_subtitle_overlay_streams_real++; } } static int start_input(bg_transcoder_t * ret) { int i; for(i = 0; i < ret->num_audio_streams; i++) { if(ret->audio_streams[i].com.do_decode || ret->audio_streams[i].com.do_copy) { start_audio_stream_i(&ret->audio_streams[i], ret->in_handle); } } for(i = 0; i < ret->num_video_streams; i++) { if(ret->video_streams[i].com.do_decode || ret->video_streams[i].com.do_copy) { start_video_stream_i(&ret->video_streams[i], ret->in_handle); } } for(i = 0; i < ret->num_subtitle_text_streams; i++) { if(ret->subtitle_text_streams[i].com.com.do_decode) { start_subtitle_stream_i((subtitle_stream_t*)(&ret->subtitle_text_streams[i]), ret->in_handle); } } for(i = 0; i < ret->num_subtitle_overlay_streams; i++) { if(ret->subtitle_overlay_streams[i].com.do_decode) { start_subtitle_stream_i(&ret->subtitle_overlay_streams[i], ret->in_handle); } } if(ret->in_plugin->start) { if(!ret->in_plugin->start(ret->in_handle->priv)) { bg_log(BG_LOG_ERROR, LOG_DOMAIN, "Starting input plugin failed"); goto fail; } } /* Check if we must seek to the start position */ if(ret->start_time != GAVL_TIME_UNDEFINED) { if(!ret->in_plugin->seek) { bg_log(BG_LOG_ERROR, LOG_DOMAIN, "Cannot seek to start point"); goto fail; } ret->in_plugin->seek(ret->in_handle->priv, &ret->start_time, GAVL_TIME_SCALE); /* This happens, if the decoder reached EOF during the seek */ if(ret->start_time == GAVL_TIME_UNDEFINED) { bg_log(BG_LOG_ERROR, LOG_DOMAIN, "Cannot seek to start point"); goto fail; } } /* Check, if the user entered bullshit */ if((ret->start_time != GAVL_TIME_UNDEFINED) && (ret->end_time != GAVL_TIME_UNDEFINED) && (ret->end_time < ret->start_time)) { bg_log(BG_LOG_ERROR, LOG_DOMAIN, "End time if before start time"); goto fail; } return 1; fail: return 0; } static void check_passes(bg_transcoder_t * ret) { int i; ret->total_passes = 1; for(i = 0; i < ret->num_audio_streams; i++) { if((ret->audio_streams[i].com.action == STREAM_ACTION_TRANSCODE) && ret->audio_streams[i].normalize) { ret->total_passes = 2; return; } } for(i = 0; i < ret->num_video_streams; i++) { if((ret->video_streams[i].com.action == STREAM_ACTION_TRANSCODE) && ret->video_streams[i].twopass) { ret->total_passes = 2; return; } } } static int setup_pass(bg_transcoder_t * ret) { int i; int result = 0; for(i = 0; i < ret->num_audio_streams; i++) { /* Reset the samples already decoded */ ret->audio_streams[i].samples_read = 0; if(ret->audio_streams[i].com.action == STREAM_ACTION_COPY) { if(ret->pass == ret->total_passes) { ret->audio_streams[i].com.do_copy = 1; result = 1; } else ret->audio_streams[i].com.do_copy = 0; } else if(ret->audio_streams[i].com.action != STREAM_ACTION_TRANSCODE) { ret->audio_streams[i].com.do_decode = 0; ret->audio_streams[i].com.do_encode = 0; } else if(ret->pass == ret->total_passes) { ret->audio_streams[i].com.do_decode = 1; ret->audio_streams[i].com.do_encode = 1; result = 1; } else if((ret->pass == 1) && (ret->audio_streams[i].normalize)) { ret->audio_streams[i].com.do_decode = 1; ret->audio_streams[i].com.do_encode = 0; result = 1; } else { ret->audio_streams[i].com.do_decode = 0; ret->audio_streams[i].com.do_encode = 0; } if(ret->audio_streams[i].com.do_decode || ret->audio_streams[i].com.do_copy) ret->audio_streams[i].com.status = STREAM_STATE_ON; else ret->audio_streams[i].com.status = STREAM_STATE_OFF; } for(i = 0; i < ret->num_video_streams; i++) { if(ret->video_streams[i].com.action == STREAM_ACTION_COPY) { if(ret->pass == ret->total_passes) { ret->video_streams[i].com.do_copy = 1; result = 1; } else ret->video_streams[i].com.do_copy = 0; } else if(ret->video_streams[i].com.action != STREAM_ACTION_TRANSCODE) { ret->video_streams[i].com.do_decode = 0; ret->video_streams[i].com.do_encode = 0; } else if((ret->pass == ret->total_passes) || ret->video_streams[i].twopass) { ret->video_streams[i].com.do_decode = 1; ret->video_streams[i].com.do_encode = 1; result = 1; } else { ret->video_streams[i].com.do_decode = 0; ret->video_streams[i].com.do_encode = 0; } if(ret->video_streams[i].com.do_decode || ret->video_streams[i].com.do_copy) ret->video_streams[i].com.status = STREAM_STATE_ON; else ret->video_streams[i].com.status = STREAM_STATE_OFF; } /* Subtitles */ for(i = 0; i < ret->num_subtitle_text_streams; i++) { switch(ret->subtitle_text_streams[i].com.com.action) { case STREAM_ACTION_FORGET: ret->subtitle_text_streams[i].com.com.do_decode = 0; ret->subtitle_text_streams[i].com.com.do_encode = 0; break; case STREAM_ACTION_BLEND: if((ret->video_streams[ret->subtitle_text_streams[i].com.video_stream].twopass) || (ret->pass == ret->total_passes)) { ret->subtitle_text_streams[i].com.com.do_decode = 1; ret->subtitle_text_streams[i].com.com.do_encode = 0; } else { ret->subtitle_text_streams[i].com.com.do_decode = 0; ret->subtitle_text_streams[i].com.com.do_encode = 0; } result = 1; break; case STREAM_ACTION_TRANSCODE: case STREAM_ACTION_TRANSCODE_OVERLAY: if(ret->pass == ret->total_passes) { ret->subtitle_text_streams[i].com.com.do_decode = 1; ret->subtitle_text_streams[i].com.com.do_encode = 1; result = 1; } else { ret->subtitle_text_streams[i].com.com.do_decode = 0; ret->subtitle_text_streams[i].com.com.do_encode = 0; } break; default: bg_log(BG_LOG_WARNING, LOG_DOMAIN, "Subtitle stream cannot be handled"); ret->subtitle_text_streams[i].com.com.do_decode = 0; ret->subtitle_text_streams[i].com.com.do_encode = 0; ret->subtitle_text_streams[i].com.com.action = STREAM_ACTION_FORGET; break; } if(!ret->subtitle_text_streams[i].com.com.do_decode) ret->subtitle_text_streams[i].com.com.status = STREAM_STATE_OFF; else ret->subtitle_text_streams[i].com.com.status = STREAM_STATE_ON; } for(i = 0; i < ret->num_subtitle_overlay_streams; i++) { switch(ret->subtitle_overlay_streams[i].com.action) { case STREAM_ACTION_FORGET: ret->subtitle_overlay_streams[i].com.do_decode = 0; ret->subtitle_overlay_streams[i].com.do_encode = 0; break; case STREAM_ACTION_BLEND: if(ret->video_streams[ret->subtitle_overlay_streams[i].video_stream].com.do_encode) { ret->subtitle_overlay_streams[i].com.do_decode = 1; ret->subtitle_overlay_streams[i].com.do_encode = 1; result = 1; } else { ret->subtitle_overlay_streams[i].com.do_decode = 0; ret->subtitle_overlay_streams[i].com.do_encode = 0; } break; case STREAM_ACTION_TRANSCODE: if(ret->pass == ret->total_passes) { ret->subtitle_overlay_streams[i].com.do_decode = 1; ret->subtitle_overlay_streams[i].com.do_encode = 1; result = 1; } else { ret->subtitle_overlay_streams[i].com.do_decode = 0; ret->subtitle_overlay_streams[i].com.do_encode = 0; } break; default: bg_log(BG_LOG_WARNING, LOG_DOMAIN, "Subtitle stream cannot be handled"); ret->subtitle_overlay_streams[i].com.do_decode = 0; ret->subtitle_overlay_streams[i].com.do_encode = 0; ret->subtitle_overlay_streams[i].com.action = STREAM_ACTION_FORGET; break; } if(!ret->subtitle_overlay_streams[i].com.do_decode) ret->subtitle_overlay_streams[i].com.status = STREAM_STATE_OFF; else ret->subtitle_overlay_streams[i].com.status = STREAM_STATE_ON; } return result; } static int create_output_file_cb(void * priv, const char * filename) { bg_transcoder_t * t = priv; if(!strcmp(filename, t->location)) { bg_log(BG_LOG_ERROR, LOG_DOMAIN, "Input and output are the same file"); return 0; } if(t->pass == t->total_passes) add_output_file(t, filename); return 1; } static void create_encoder(bg_transcoder_t * ret) { ret->enc = bg_encoder_create(ret->plugin_reg, NULL, ret->transcoder_track, BG_STREAM_AUDIO | BG_STREAM_VIDEO | BG_STREAM_SUBTITLE_TEXT | BG_STREAM_SUBTITLE_OVERLAY, BG_PLUGIN_FILE); } static int init_encoder(bg_transcoder_t * ret) { int i; char * tmp_string; ret->cb.create_output_file = create_output_file_cb; ret->cb.data = ret; bg_encoder_set_callbacks(ret->enc, &ret->cb); tmp_string = bg_sprintf("%s/%s", ret->output_directory, ret->name); bg_encoder_open(ret->enc, tmp_string, &ret->metadata, ret->transcoder_track->chapter_list); free(tmp_string); for(i = 0; i < ret->num_audio_streams; i++) { if(ret->audio_streams[i].com.do_decode) /* If we don't encode we still need to open the plugin to get the final output format */ add_audio_stream(&ret->audio_streams[i], ret); else if(ret->audio_streams[i].com.do_copy) add_audio_stream_compressed(&ret->audio_streams[i], ret); } /* Video streams: Must be added before the subtitle streams, because we need to know the output format (at least the output size) of the stream */ for(i = 0; i < ret->num_video_streams; i++) { if(ret->video_streams[i].com.do_decode)/* If we don't encode we still need to open the plugin to get the final output format */ { add_video_stream(&ret->video_streams[i], ret); set_video_pass(ret, i); } else if(ret->video_streams[i].com.do_copy) add_video_stream_compressed(&ret->video_streams[i], ret); } for(i = 0; i < ret->num_subtitle_text_streams; i++) { if(!ret->subtitle_text_streams[i].com.com.do_encode) continue; add_subtitle_text_stream(&ret->subtitle_text_streams[i], &ret->transcoder_track->subtitle_text_streams[i], ret); } for(i = 0; i < ret->num_subtitle_overlay_streams; i++) { if(!ret->subtitle_overlay_streams[i].com.do_encode) continue; add_subtitle_overlay_stream(&ret->subtitle_overlay_streams[i], &ret->transcoder_track->subtitle_overlay_streams[i], ret); } return bg_encoder_start(ret->enc); } static int init_audio_converter(audio_stream_t * ret, bg_transcoder_t * t) { gavl_audio_options_t * opt; bg_encoder_get_audio_format(t->enc, ret->com.out_index, &ret->out_format); gavl_audio_format_copy(&ret->pipe_format, &ret->out_format); if(ret->options.force_format != GAVL_SAMPLE_NONE) ret->pipe_format.sample_format = ret->options.force_format; bg_audio_filter_chain_set_out_format(ret->fc, &ret->pipe_format); /* Initialize output converter */ opt = gavl_audio_converter_get_options(ret->cnv_out); gavl_audio_options_copy(opt, ret->options.opt); ret->do_convert_out = gavl_audio_converter_init(ret->cnv_out, &ret->pipe_format, &ret->out_format); /* Create frames (could be left from the previous pass) */ if(ret->do_convert_out && !ret->pipe_frame) ret->pipe_frame = gavl_audio_frame_create(&ret->pipe_format); if(!ret->out_frame) ret->out_frame = gavl_audio_frame_create(&ret->out_format); return 1; } static int init_video_converter(video_stream_t * ret, bg_transcoder_t * t) { bg_encoder_get_video_format(t->enc, ret->com.out_index, &ret->out_format); /* Initialize converter */ bg_video_filter_chain_set_out_format(ret->fc, &ret->out_format); /* Create frames */ if(!ret->frame) { ret->frame = gavl_video_frame_create(&ret->out_format); // fprintf(stderr, "Created video frame %p %p\n", ret->frame, ret->frame->planes[0]); } gavl_video_frame_clear(ret->frame, &ret->out_format); return 1; } static void subtitle_init_blend(subtitle_stream_t * ss, video_stream_t * vs) { subtitle_text_stream_t * sst; vs->subtitle_streams = realloc(vs->subtitle_streams, sizeof(*(vs->subtitle_streams))*(vs->num_subtitle_streams+1)); vs->subtitle_streams[vs->num_subtitle_streams] = ss; vs->num_subtitle_streams++; /* Check whether to initialize the text renderer */ if(ss->com.type == STREAM_TYPE_SUBTITLE_TEXT) { sst = (subtitle_text_stream_t*)ss; bg_text_renderer_init(sst->textrenderer, &vs->out_format, &ss->in_format); } if(!ss->ovl1.frame) ss->ovl1.frame = gavl_video_frame_create(&ss->in_format); if(!ss->ovl2.frame) ss->ovl2.frame = gavl_video_frame_create(&ss->in_format); ss->current_ovl = &ss->ovl1; ss->next_ovl = &ss->ovl2; gavl_overlay_blend_context_init(ss->blend_context, &vs->out_format, &ss->in_format); gavl_video_format_copy(&ss->out_format, &vs->out_format); } static void subtitle_init_encode_text(subtitle_text_stream_t * ss, bg_transcoder_t * t) { /* Nothing to do here for now */ bg_encoder_get_subtitle_text_timescale(t->enc, ss->com.com.out_index, &ss->com.out_format.timescale); } static void subtitle_init_encode_overlay(subtitle_stream_t * ss, bg_transcoder_t * t) { subtitle_text_stream_t * sst; bg_encoder_get_subtitle_overlay_format(t->enc, ss->com.out_index, &ss->out_format); /* Check whether to initialize the text renderer */ if(ss->com.type == STREAM_TYPE_SUBTITLE_TEXT) { sst = (subtitle_text_stream_t*)ss; bg_text_renderer_init(sst->textrenderer, &ss->out_format, &ss->in_format); // gavl_video_format_dump(&ss->in_format); // gavl_video_format_dump(&ss->out_format); } ss->do_convert = gavl_video_converter_init(ss->cnv, &ss->in_format, &ss->out_format); if(!ss->ovl1.frame) ss->ovl1.frame = gavl_video_frame_create(&ss->in_format); if(ss->do_convert) { if(!ss->ovl2.frame) ss->ovl2.frame = gavl_video_frame_create(&ss->out_format); } } static int init_converters(bg_transcoder_t * ret) { int i; for(i = 0; i < ret->num_audio_streams; i++) { if(ret->audio_streams[i].com.do_copy) { gavl_audio_format_copy(&ret->audio_streams[i].out_format, &ret->audio_streams[i].in_format); continue; } if(!ret->audio_streams[i].com.do_decode) continue; if(!init_audio_converter(&ret->audio_streams[i], ret)) return 0; } for(i = 0; i < ret->num_video_streams; i++) { if(ret->video_streams[i].com.do_copy) { gavl_video_format_copy(&ret->video_streams[i].out_format, &ret->video_streams[i].in_format); continue; } if(!ret->video_streams[i].com.do_decode) continue; if(!init_video_converter(&ret->video_streams[i], ret)) return 0; if(ret->video_streams[i].subtitle_streams) { free(ret->video_streams[i].subtitle_streams); ret->video_streams[i].subtitle_streams = NULL; ret->video_streams[i].num_subtitle_streams = 0; } } for(i = 0; i < ret->num_subtitle_text_streams; i++) { if(!ret->subtitle_text_streams[i].com.com.do_decode) continue; switch(ret->subtitle_text_streams[i].com.com.action) { case STREAM_ACTION_BLEND: subtitle_init_blend((subtitle_stream_t*)(&ret->subtitle_text_streams[i]), &ret->video_streams[ret->subtitle_text_streams[i].com.video_stream]); break; case STREAM_ACTION_TRANSCODE: subtitle_init_encode_text((&ret->subtitle_text_streams[i]), ret); break; case STREAM_ACTION_TRANSCODE_OVERLAY: subtitle_init_encode_overlay((subtitle_stream_t*)&ret->subtitle_text_streams[i], ret); break; } } for(i = 0; i < ret->num_subtitle_overlay_streams; i++) { if(!ret->subtitle_overlay_streams[i].com.do_decode) continue; switch(ret->subtitle_overlay_streams[i].com.action) { case STREAM_ACTION_BLEND: subtitle_init_blend(&ret->subtitle_overlay_streams[i], &ret->video_streams[ret->subtitle_overlay_streams[i].video_stream]); break; case STREAM_ACTION_TRANSCODE: subtitle_init_encode_overlay(&ret->subtitle_overlay_streams[i], ret); break; } } return 1; } static void init_normalize(bg_transcoder_t * ret) { int i; double absolute; double volume_dB = 0.0; for(i = 0; i < ret->num_audio_streams; i++) { if(!ret->audio_streams[i].normalize) continue; if(ret->pass == 1) { gavl_peak_detector_set_format(ret->audio_streams[i].peak_detector, &ret->audio_streams[i].out_format); } else if(ret->pass == ret->total_passes) { gavl_volume_control_set_format(ret->audio_streams[i].volume_control, &ret->audio_streams[i].pipe_format); /* Set the volume */ gavl_peak_detector_get_peak(ret->audio_streams[i].peak_detector, NULL, NULL, &absolute); if(absolute == 0.0) { gavl_volume_control_set_volume(ret->audio_streams[i].volume_control, volume_dB); bg_log(BG_LOG_WARNING, LOG_DOMAIN, "Zero peaks detected (silent file?). Disabling normalization."); } else { volume_dB = - 20.0 * log10(absolute); gavl_volume_control_set_volume(ret->audio_streams[i].volume_control, volume_dB); bg_log(BG_LOG_INFO, LOG_DOMAIN, "Correcting volume by %.2f dB", volume_dB); } } } } int bg_transcoder_init(bg_transcoder_t * ret, bg_plugin_registry_t * plugin_reg, bg_transcoder_track_t * track) { ret->plugin_reg = plugin_reg; ret->transcoder_track = track; /* Initialize encoder info */ /* Set general parameter */ bg_cfg_section_apply(track->general_section, track->general_parameters, set_parameter_general, ret); /* Set Metadata */ bg_cfg_section_apply(track->metadata_section, track->metadata_parameters, bg_metadata_set_parameter, &ret->metadata); /* Postprocess only: Send messages and return */ if(ret->pp_only) { ret->output_filename = bg_strdup(ret->output_filename, ret->location); send_init_messages(ret); ret->state = STREAM_STATE_FINISHED; return 1; } /* Open input plugin */ if(!open_input(ret)) goto fail; create_encoder(ret); create_streams(ret, track); check_compressed(ret); /* Check how many passes we must do */ check_passes(ret); ret->pass = 1; /* Set up this pass */ if(!setup_pass(ret)) { bg_log(BG_LOG_ERROR, LOG_DOMAIN, "No stream to encode"); goto fail; } /* Start input plugin */ if(!start_input(ret)) goto fail; set_input_formats(ret); /* Set up the streams in the encoders */ if(!init_encoder(ret)) goto fail; /* Set formats */ if(!init_converters(ret)) goto fail; /* Init normalizing */ init_normalize(ret); /* Send messages */ send_init_messages(ret); /* Set duration */ if(ret->set_start_time && ret->set_end_time) ret->duration = ret->end_time - ret->start_time; else if(ret->set_start_time) ret->duration = ret->track_info->duration - ret->start_time; else if(ret->set_end_time) ret->duration = ret->end_time; else ret->duration = ret->track_info->duration; /* Start timer */ gavl_timer_start(ret->timer); ret->state = TRANSCODER_STATE_RUNNING; return 1; fail: return 0; } #define FREE_STR(str) if(str)free(str); static void cleanup_stream(stream_t * s) { gavl_compression_info_free(&s->ci); gavl_packet_free(&s->packet); gavl_metadata_free(&s->m); } static void cleanup_audio_stream(audio_stream_t * s) { cleanup_stream(&s->com); /* Free all resources */ if(s->out_frame) gavl_audio_frame_destroy(s->out_frame); if(s->pipe_frame) gavl_audio_frame_destroy(s->pipe_frame); if(s->cnv_out) gavl_audio_converter_destroy(s->cnv_out); if(s->fc) bg_audio_filter_chain_destroy(s->fc); if(s->volume_control) gavl_volume_control_destroy(s->volume_control); if(s->peak_detector) gavl_peak_detector_destroy(s->peak_detector); bg_gavl_audio_options_free(&s->options); } static void cleanup_video_stream(video_stream_t * s) { cleanup_stream(&s->com); /* Free all resources */ if(s->frame) { // fprintf(stderr, "gavl_video_frame_destroy %p %p\n", s->frame, s->frame->planes[0]); gavl_video_frame_destroy(s->frame); } if(s->fc) bg_video_filter_chain_destroy(s->fc); if(s->subtitle_streams) free(s->subtitle_streams); /* Delete stats file */ if(s->stats_file) { remove(s->stats_file); free(s->stats_file); } bg_gavl_video_options_free(&s->options); } static void cleanup_subtitle_stream(subtitle_stream_t * s) { subtitle_text_stream_t * ts; cleanup_stream(&s->com); if(s->ovl1.frame) gavl_video_frame_destroy(s->ovl1.frame); if(s->ovl2.frame) gavl_video_frame_destroy(s->ovl2.frame); if(s->blend_context) gavl_overlay_blend_context_destroy(s->blend_context); if(s->com.type == STREAM_TYPE_SUBTITLE_TEXT) { ts = (subtitle_text_stream_t*)s; if(ts->textrenderer) bg_text_renderer_destroy(ts->textrenderer); } } static void reset_streams(bg_transcoder_t * t) { int i; for(i = 0; i < t->num_audio_streams; i++) { t->audio_streams[i].samples_read = 0; t->audio_streams[i].com.time = 0; } for(i = 0; i < t->num_video_streams; i++) { t->video_streams[i].frames_written = 0; t->video_streams[i].com.time = 0; } } static void close_input(bg_transcoder_t * t) { if(t->pp_only) return; if(t->in_plugin->stop) t->in_plugin->stop(t->in_handle->priv); t->in_plugin->close(t->in_handle->priv); bg_plugin_unref(t->in_handle); t->in_handle = NULL; } /* Switch to next pass */ static void next_pass(bg_transcoder_t * t) { char * tmp_string; bg_encoder_destroy(t->enc, 1); close_input(t); t->pass++; /* Reset stream times */ reset_streams(t); gavl_timer_stop(t->timer); gavl_timer_set(t->timer, 0); t->percentage_done = 0.0; t->time = 0; t->last_seconds = 0.0; open_input(t); create_encoder(t); /* Decide, which stream will be en/decoded*/ setup_pass(t); start_input(t); /* Some streams don't have this already */ set_input_formats(t); /* Initialize encoding plugins */ init_encoder(t); /* Set formats */ init_converters(t); /* Init normalizing */ init_normalize(t); /* Send message */ tmp_string = bg_sprintf(TR("Transcoding %s [Track %d, Pass %d/%d]"), t->location, t->track+1, t->pass, t->total_passes); bg_transcoder_send_msg_start(t->message_queues, tmp_string); bg_log_notranslate(BG_LOG_INFO, LOG_DOMAIN, "%s", tmp_string); free(tmp_string); gavl_timer_start(t->timer); } /* * Do one iteration. * If return value is FALSE, we are done */ int bg_transcoder_iteration(bg_transcoder_t * t) { int i; gavl_time_t time; stream_t * stream = NULL; gavl_time_t real_time; double real_seconds; double remaining_seconds; int done = 1; if(t->pp_only) { t->state = TRANSCODER_STATE_FINISHED; bg_transcoder_send_msg_finished(t->message_queues); log_transcoding_time(t); return 0; } time = GAVL_TIME_MAX; /* Find the stream with the smallest time */ for(i = 0; i < t->num_audio_streams; i++) { /* Check for the most urgent audio/video stream */ if(t->audio_streams[i].com.status != STREAM_STATE_ON) continue; done = 0; if(t->audio_streams[i].com.time < time) { time = t->audio_streams[i].com.time; stream = &t->audio_streams[i].com; } } for(i = 0; i < t->num_video_streams; i++) { if(t->video_streams[i].com.status != STREAM_STATE_ON) continue; done = 0; if(t->video_streams[i].com.time < time) { time = t->video_streams[i].com.time; stream = &t->video_streams[i].com; } } /* Detecting EOF for subtitles doesn't work when we transcode until a specified time */ if(t->end_time == GAVL_TIME_UNDEFINED) { for(i = 0; i < t->num_subtitle_text_streams; i++) { if(t->subtitle_text_streams[i].com.com.status != STREAM_STATE_ON) continue; done = 0; } for(i = 0; i < t->num_subtitle_overlay_streams; i++) { if(t->subtitle_overlay_streams[i].com.status != STREAM_STATE_ON) continue; done = 0; } } if(done) { if(t->pass < t->total_passes) { log_transcoding_time(t); next_pass(t); return 1; } else { t->state = TRANSCODER_STATE_FINISHED; bg_transcoder_send_msg_finished(t->message_queues); log_transcoding_time(t); return 0; } } /* Do the actual transcoding */ /* Subtitle iteration must always be done */ if(!subtitle_iteration(t)) { t->state = TRANSCODER_STATE_ERROR; bg_transcoder_send_msg_error(t->message_queues); return 0; } if(stream) { if(stream->type == STREAM_TYPE_AUDIO) { if(!audio_iteration((audio_stream_t*)stream, t)) { t->state = TRANSCODER_STATE_ERROR; bg_transcoder_send_msg_error(t->message_queues); return 0; } } else if(stream->type == STREAM_TYPE_VIDEO) { if(!video_iteration((video_stream_t*)stream, t)) { t->state = TRANSCODER_STATE_ERROR; bg_transcoder_send_msg_error(t->message_queues); return 0; } } if(stream->time > t->time) t->time = stream->time; } /* Update status */ real_time = gavl_timer_get(t->timer); real_seconds = gavl_time_to_seconds(real_time); t->percentage_done = gavl_time_to_seconds(t->time) / gavl_time_to_seconds(t->duration); if(t->percentage_done < 0.0) t->percentage_done = 0.0; if(t->percentage_done > 1.0) t->percentage_done = 1.0; if(t->percentage_done == 0.0) remaining_seconds = 0.0; else { remaining_seconds = real_seconds * (1.0 / t->percentage_done - 1.0); } t->remaining_time = gavl_seconds_to_time(remaining_seconds); if(real_seconds - t->last_seconds > 1.0) { bg_transcoder_send_msg_progress(t->message_queues, t->percentage_done, t->remaining_time); t->last_seconds = real_seconds; } return 1; } void bg_transcoder_destroy(bg_transcoder_t * t) { int i; int do_delete = 0; char tmp_string[128]; if((t->state == TRANSCODER_STATE_RUNNING) && t->delete_incomplete && !t->is_url) do_delete = 1; else if(t->state == TRANSCODER_STATE_INIT) do_delete = 1; else if(t->state == TRANSCODER_STATE_ERROR) do_delete = 1; /* Close all encoders so the files are finished */ if(t->enc) bg_encoder_destroy(t->enc, do_delete); /* Send created files to gmerlin */ if((t->state != TRANSCODER_STATE_RUNNING) && !do_delete) { send_file_messages(t); } free_output_files(t); /* Cleanup streams */ for(i = 0; i < t->num_video_streams; i++) { if((t->video_streams[i].com.action != STREAM_ACTION_FORGET) && !do_delete) { sprintf(tmp_string, "%" PRId64, t->video_streams[i].frames_written); bg_log(BG_LOG_INFO, LOG_DOMAIN, "Video stream %d: Transcoded %s frames", i+1, tmp_string); } cleanup_video_stream(&t->video_streams[i]); } for(i = 0; i < t->num_audio_streams; i++) { if((t->audio_streams[i].com.action != STREAM_ACTION_FORGET) && !do_delete) { sprintf(tmp_string, "%" PRId64, t->audio_streams[i].samples_read); bg_log(BG_LOG_INFO, LOG_DOMAIN, "Audio stream %d: Transcoded %s samples", i+1, tmp_string); } cleanup_audio_stream(&t->audio_streams[i]); } for(i = 0; i < t->num_subtitle_text_streams; i++) { cleanup_subtitle_stream((subtitle_stream_t*)(&t->subtitle_text_streams[i])); } for(i = 0; i < t->num_subtitle_overlay_streams; i++) { cleanup_subtitle_stream(&t->subtitle_overlay_streams[i]); } if(t->audio_streams) free(t->audio_streams); if(t->video_streams) free(t->video_streams); if(t->subtitle_text_streams) free(t->subtitle_text_streams); if(t->subtitle_overlay_streams) free(t->subtitle_overlay_streams); /* Free metadata */ gavl_metadata_free(&t->metadata); /* Close and destroy the input plugin */ close_input(t); /* Free rest */ FREE_STR(t->name); FREE_STR(t->location); FREE_STR(t->plugin); FREE_STR(t->output_directory); FREE_STR(t->output_path); FREE_STR(t->subdir); FREE_STR(t->output_filename); gavl_timer_destroy(t->timer); bg_msg_queue_list_destroy(t->message_queues); pthread_mutex_destroy(&t->stop_mutex); free(t); } static void * thread_func(void * data) { int do_stop; bg_transcoder_t * t = (bg_transcoder_t*)data; while(bg_transcoder_iteration(t)) { pthread_mutex_lock(&t->stop_mutex); do_stop = t->do_stop; pthread_mutex_unlock(&t->stop_mutex); if(do_stop) break; } return NULL; } void bg_transcoder_run(bg_transcoder_t * t) { pthread_create(&t->thread, NULL, thread_func, t); } void bg_transcoder_stop(bg_transcoder_t * t) { pthread_mutex_lock(&t->stop_mutex); t->do_stop = 1; pthread_mutex_unlock(&t->stop_mutex); } void bg_transcoder_finish(bg_transcoder_t * t) { pthread_join(t->thread, NULL); } gmerlin-1.2.0~dfsg/lib/thumbnail.c0000644000175000017500000001625511764363410017004 0ustar alessioalessio/***************************************************************** * gmerlin - a general purpose multimedia framework and applications * * Copyright (c) 2001 - 2011 Members of the Gmerlin project * gmerlin-general@lists.sourceforge.net * http://gmerlin.sourceforge.net * * 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 of the License, 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 this program. If not, see . * *****************************************************************/ #include #include /* stat() */ #include /* stat() */ #include /* stat() */ #include #include #include #include #include #include #include #define LOG_DOMAIN "thumbnails" static int thumbnail_up_to_date(const char * thumbnail_file, bg_plugin_registry_t * plugin_reg, gavl_video_frame_t ** frame, gavl_video_format_t * format, int64_t mtime) { int i; gavl_metadata_t metadata; int64_t test_mtime; int ret = 0; const char * val; memset(&metadata, 0, sizeof(metadata)); memset(format, 0, sizeof(*format)); *frame = bg_plugin_registry_load_image(plugin_reg, thumbnail_file, format, &metadata); i = 0; val = gavl_metadata_get(&metadata, "Thumb::MTime"); if(val) { test_mtime = strtoll(val, NULL, 10); if(mtime == test_mtime) ret = 1; } gavl_metadata_free(&metadata); return ret; } static void make_fail_thumbnail(const char * gml, const char * thumb_filename, bg_plugin_registry_t * plugin_reg, int64_t mtime) { gavl_video_format_t format; gavl_video_frame_t * frame; gavl_metadata_t metadata; char * tmp_string; memset(&format, 0, sizeof(format)); gavl_metadata_init(&metadata); format.image_width = 1; format.image_height = 1; format.frame_width = 1; format.frame_height = 1; format.pixel_width = 1; format.pixel_height = 1; format.pixelformat = GAVL_RGBA_32; frame = gavl_video_frame_create(&format); gavl_video_frame_clear(frame, &format); tmp_string = bg_string_to_uri(gml, -1); gavl_metadata_set_nocpy(&metadata, "Thumb::URI", tmp_string); tmp_string = bg_sprintf("%"PRId64, mtime); gavl_metadata_set_nocpy(&metadata, "Thumb::MTime", tmp_string); bg_plugin_registry_save_image(plugin_reg, thumb_filename, frame, &format, &metadata); gavl_metadata_free(&metadata); gavl_video_frame_destroy(frame); } int bg_get_thumbnail(const char * gml, bg_plugin_registry_t * plugin_reg, char ** thumbnail_filename_ret, gavl_video_frame_t ** frame_ret, gavl_video_format_t * format_ret) { bg_subprocess_t * sp; char hash[33]; char * home_dir; char * thumb_filename_normal = NULL; char * thumb_filename_fail = NULL; char * thumbs_dir_normal = NULL; char * thumbs_dir_fail = NULL; char * command; int ret = 0; gavl_video_frame_t * frame = NULL; gavl_video_format_t format; struct stat st; if(stat(gml, &st)) { bg_log(BG_LOG_ERROR, LOG_DOMAIN, "Cannot stat %s: %s", gml, strerror(errno)); return 0; } /* Get and create directories */ home_dir = getenv("HOME"); if(!home_dir) { bg_log(BG_LOG_ERROR, LOG_DOMAIN, "Cannot get home directory"); return 0; } thumbs_dir_normal = bg_sprintf("%s/.thumbnails/normal", home_dir); thumbs_dir_fail = bg_sprintf("%s/.thumbnails/fail/gmerlin", home_dir); if(!bg_ensure_directory(thumbs_dir_normal) || !bg_ensure_directory(thumbs_dir_fail)) goto done; bg_get_filename_hash(gml, hash); thumb_filename_normal = bg_sprintf("%s/%s.png", thumbs_dir_normal, hash); thumb_filename_fail = bg_sprintf("%s/%s.png", thumbs_dir_fail, hash); if(access(thumb_filename_normal, R_OK)) /* Thumbnail file not present */ { /* Check if there is a failed thumbnail */ if(!access(thumb_filename_fail, R_OK)) { if(thumbnail_up_to_date(thumb_filename_fail, plugin_reg, &frame, &format, st.st_mtime)) { gavl_video_frame_destroy(frame); frame = NULL; goto done; } else /* Failed thumbnail is *not* up to date, remove it */ { remove(thumb_filename_fail); gavl_video_frame_destroy(frame); frame = NULL; } } /* else: Regenerate */ } else /* Thumbnail file present */ { /* Check if the thumbnail is recent */ if(thumbnail_up_to_date(thumb_filename_normal, plugin_reg, &frame, &format, st.st_mtime)) { if(thumbnail_filename_ret) { *thumbnail_filename_ret = thumb_filename_normal; thumb_filename_normal = NULL; } if(frame_ret) { *frame_ret = frame; frame = NULL; } if(format_ret) gavl_video_format_copy(format_ret, &format); ret = 1; goto done; } else { remove(thumb_filename_normal); gavl_video_frame_destroy(frame); frame = NULL; } /* else: Regenerate */ } /* Regenerate */ command = bg_sprintf("gmerlin-video-thumbnailer \"%s\" %s", gml, thumb_filename_normal); sp = bg_subprocess_create(command, 0, 0, 0); bg_subprocess_close(sp); free(command); if(!access(thumb_filename_normal, R_OK)) /* Thumbnail generation succeeded */ { if(frame_ret && format_ret) { *frame_ret = bg_plugin_registry_load_image(plugin_reg, thumb_filename_normal, format_ret, NULL); } if(thumbnail_filename_ret) { *thumbnail_filename_ret = thumb_filename_normal; thumb_filename_normal = NULL; } ret = 1; goto done; } else /* Thumbnail generation failed */ { make_fail_thumbnail(gml, thumb_filename_fail, plugin_reg, st.st_mtime); } done: free(thumbs_dir_normal); free(thumbs_dir_fail); if(thumb_filename_normal) free(thumb_filename_normal); if(thumb_filename_fail) free(thumb_filename_fail); if(frame) gavl_video_frame_destroy(frame); return ret; } gmerlin-1.2.0~dfsg/lib/socket.c0000644000175000017500000003055411764363410016307 0ustar alessioalessio/***************************************************************** * gmerlin - a general purpose multimedia framework and applications * * Copyright (c) 2001 - 2011 Members of the Gmerlin project * gmerlin-general@lists.sourceforge.net * http://gmerlin.sourceforge.net * * 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 of the License, 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 this program. If not, see . * *****************************************************************/ #include #include #include #include #include #include #ifdef HAVE_SYS_SELECT_H #include #else #include #include #endif #include #include /* gethostbyname */ #include //#include #include #include #include #include #include #include #include #define LOG_DOMAIN "tcpsocket" #if !HAVE_DECL_MSG_NOSIGNAL #define MSG_NOSIGNAL 0 #endif /* Opaque address structure so we can support IPv6 in the future */ struct bg_host_address_s { struct addrinfo * addr; }; bg_host_address_t * bg_host_address_create() { bg_host_address_t * ret; ret = calloc(1, sizeof(*ret)); return ret; } void bg_host_address_destroy(bg_host_address_t * a) { freeaddrinfo(a->addr); free(a); } static int create_socket(int domain, int type, int protocol) { int ret; #if HAVE_DECL_SO_NOSIGPIPE // OSX int value = 1; #endif ret = socket(domain, type, protocol); #if HAVE_DECL_SO_NOSIGPIPE // OSX if(ret < 0) return ret; if(setsockopt(ret, SOL_SOCKET, SO_NOSIGPIPE, &value, sizeof(int)) == -1) return -1; #endif return ret; } /* */ static void address_set_port(struct addrinfo * info, int port) { while(info) { switch(info->ai_family) { case AF_INET: { struct sockaddr_in * addr; addr = (struct sockaddr_in*)info->ai_addr; addr->sin_port = htons(port); } break; case AF_INET6: { struct sockaddr_in6 * addr; addr = (struct sockaddr_in6*)info->ai_addr; addr->sin6_port = htons(port); } break; default: break; } info = info->ai_next; } } static struct addrinfo * hostbyname(const char * hostname, int port, int socktype) { int err; struct in_addr ipv4_addr; struct addrinfo hints; struct addrinfo * ret; memset(&hints, 0, sizeof(hints)); hints.ai_family = PF_UNSPEC; hints.ai_socktype = socktype; // SOCK_STREAM, SOCK_DGRAM hints.ai_protocol = 0; // 0 hints.ai_flags = 0; /* prevent DNS lookup for numeric IP addresses */ if(inet_aton(hostname, &ipv4_addr)) hints.ai_flags |= AI_NUMERICHOST; if((err = getaddrinfo(hostname, NULL /* service */, &hints, &ret))) { bg_log(BG_LOG_ERROR, LOG_DOMAIN, "Cannot resolve address of %s: %s", hostname, gai_strerror(err)); return NULL; } #if 0 if(ret[0].ai_addr->sa_family == AF_INET) fprintf(stderr, "Got IPV4 address\n"); else if(ret[0].ai_addr->sa_family == AF_INET6) fprintf(stderr, "Got IPV6 address\n"); #endif address_set_port(ret, port); return ret; } int bg_host_address_set(bg_host_address_t * a, const char * hostname, int port, int socktype) { a->addr = hostbyname(hostname, port, socktype); // if(!hostbyname(a, hostname)) // return 0; // a->port = port; if(!a->addr) return 0; return 1; } /* Client connection (stream oriented) */ int bg_socket_connect_inet(bg_host_address_t * a, int milliseconds) { int ret = -1; int err; socklen_t err_len; struct timeval timeout; fd_set write_fds; /* Create the socket */ if((ret = create_socket(a->addr->ai_family, SOCK_STREAM, 0)) < 0) { bg_log(BG_LOG_ERROR, LOG_DOMAIN, "Cannot create socket"); return -1; } /* Set nonblocking mode */ if(fcntl(ret, F_SETFL, O_NONBLOCK) < 0) { bg_log(BG_LOG_ERROR, LOG_DOMAIN, "Cannot set nonblocking mode"); return -1; } /* Connect the thing */ if(connect(ret, a->addr->ai_addr, a->addr->ai_addrlen)<0) { if(errno == EINPROGRESS) { timeout.tv_sec = milliseconds / 1000; timeout.tv_usec = 1000 * (milliseconds % 1000); FD_ZERO (&write_fds); FD_SET (ret, &write_fds); err = select(ret+1, NULL, &write_fds, NULL,&timeout); if(!err) { bg_log(BG_LOG_ERROR, LOG_DOMAIN, "Connection timed out"); return -1; } else if(err < 0) { bg_log(BG_LOG_ERROR, LOG_DOMAIN, "select() failed on connect"); return -1; } } else { bg_log(BG_LOG_ERROR, LOG_DOMAIN, "Connecting failed: %s", strerror(errno)); return -1; } } /* Check for error */ err_len = sizeof(err); getsockopt(ret, SOL_SOCKET, SO_ERROR, &err, &err_len); if(err) { bg_log(BG_LOG_ERROR, LOG_DOMAIN, "Connecting failed: %s", strerror(err)); return -1; } /* Set back to blocking mode */ if(fcntl(ret, F_SETFL, 0) < 0) { bg_log(BG_LOG_ERROR, LOG_DOMAIN, "Cannot set blocking mode"); return -1; } return ret; } int bg_socket_connect_unix(const char * name) { struct sockaddr_un addr; int addr_len; int ret; ret = create_socket(PF_LOCAL, SOCK_STREAM, 0); if(ret < 0) { bg_log(BG_LOG_ERROR, LOG_DOMAIN, "Cannot create unix socket"); return -1; } addr.sun_family = AF_LOCAL; strncpy (addr.sun_path, name, sizeof(addr.sun_path)); addr.sun_path[sizeof (addr.sun_path) - 1] = '\0'; addr_len = SUN_LEN(&addr); if(connect(ret,(struct sockaddr*)(&addr),addr_len)<0) { bg_log(BG_LOG_ERROR, LOG_DOMAIN, "Connecting unix socket failed"); return -1; } return ret; } void bg_socket_disconnect(int sock) { close(sock); } /* Older systems assign an ipv4 address to localhost, newer systems (e.g. Ubuntu Karmic) assign an ipv6 address to localhost. To test this, we make a name lookup for "localhost" and test if it returns an IPV4 or an IPV6 address */ static int have_ipv6() { struct addrinfo hints; struct addrinfo * ret; int err, has_ipv6; memset(&hints, 0, sizeof(hints)); hints.ai_family = PF_UNSPEC; hints.ai_socktype = SOCK_STREAM; // SOCK_DGRAM hints.ai_protocol = 0; // 0 hints.ai_flags = 0; if((err = getaddrinfo("localhost", NULL /* service */, &hints, &ret))) { bg_log(BG_LOG_ERROR, LOG_DOMAIN, "Cannot resolve address of localhost: %s", gai_strerror(err)); return 0; } if(ret[0].ai_addr->sa_family == AF_INET6) has_ipv6 = 1; else has_ipv6 = 0; freeaddrinfo(ret); return has_ipv6; } /* Server socket (stream oriented) */ int bg_listen_socket_create_inet(int port, int queue_size, int flags) { int ret, err, use_ipv6; struct sockaddr_in name_ipv4; struct sockaddr_in6 name_ipv6; if(flags & BG_SOCKET_LOOPBACK) use_ipv6 = have_ipv6(); else use_ipv6 = 0; memset(&name_ipv4, 0, sizeof(name_ipv4)); memset(&name_ipv6, 0, sizeof(name_ipv6)); if(use_ipv6) ret = create_socket(PF_INET6, SOCK_STREAM, 0); else ret = create_socket(PF_INET, SOCK_STREAM, 0); /* Create the socket. */ if (ret < 0) { bg_log(BG_LOG_ERROR, LOG_DOMAIN, "Cannot create inet server socket"); return -1; } /* Give the socket a name. */ if(use_ipv6) { name_ipv6.sin6_family = AF_INET6; name_ipv6.sin6_port = htons(port); if(flags & BG_SOCKET_LOOPBACK) name_ipv6.sin6_addr = in6addr_loopback; else name_ipv6.sin6_addr = in6addr_any; err = bind(ret, (struct sockaddr *)&name_ipv6, sizeof(name_ipv6)); } else { name_ipv4.sin_family = AF_INET; name_ipv4.sin_port = htons(port); if(flags & BG_SOCKET_LOOPBACK) name_ipv4.sin_addr.s_addr = htonl(INADDR_LOOPBACK); else name_ipv4.sin_addr.s_addr = htonl(INADDR_ANY); err = bind(ret, (struct sockaddr *)&name_ipv4, sizeof(name_ipv4)); } if(err < 0) { bg_log(BG_LOG_ERROR, LOG_DOMAIN, "Cannot bind inet socket: %s", strerror(errno)); return -1; } if(fcntl(ret, F_SETFL, O_NONBLOCK) < 0) { bg_log(BG_LOG_ERROR, LOG_DOMAIN, "Cannot set nonblocking mode"); return -1; } if(listen(ret, queue_size)) { bg_log(BG_LOG_ERROR, LOG_DOMAIN, "Cannot put socket into listening mode"); return -1; } return ret; } int bg_listen_socket_create_unix(const char * name, int queue_size) { int ret; struct sockaddr_un addr; int addr_len; ret = create_socket(PF_LOCAL, SOCK_STREAM, 0); if(ret < 0) { bg_log(BG_LOG_ERROR, LOG_DOMAIN, "Cannot create unix server socket"); return -1; } addr.sun_family = AF_LOCAL; strncpy (addr.sun_path, name, sizeof(addr.sun_path)); addr.sun_path[sizeof (addr.sun_path) - 1] = '\0'; addr_len = SUN_LEN(&addr); if(bind(ret,(struct sockaddr*)(&addr),addr_len)<0) { bg_log(BG_LOG_ERROR, LOG_DOMAIN, "Could not bind socket"); return -1; } if(fcntl(ret, F_SETFL, O_NONBLOCK) < 0) { bg_log(BG_LOG_ERROR, LOG_DOMAIN, "Cannot set nonblocking mode"); return -1; } if(listen(ret, queue_size)) { bg_log(BG_LOG_ERROR, LOG_DOMAIN, "Cannot put socket into listening mode"); return -1; } return ret; } /* Accept a new client connection, return -1 if there is none */ int bg_listen_socket_accept(int sock) { int ret; ret = accept(sock, NULL, NULL); if(ret < 0) return -1; return ret; } void bg_listen_socket_destroy(int sock) { close(sock); } int bg_socket_read_data(int fd, uint8_t * data, int len, int milliseconds) { int result; fd_set rset; struct timeval timeout; if(milliseconds >= 0) { FD_ZERO (&rset); FD_SET (fd, &rset); timeout.tv_sec = milliseconds / 1000; timeout.tv_usec = (milliseconds % 1000) * 1000; if(select (fd+1, &rset, NULL, NULL, &timeout) <= 0) { // bg_log(BG_LOG_ERROR, LOG_DOMAIN, "Got read timeout"); return 0; } } result = recv(fd, data, len, MSG_WAITALL); if(result <= 0) { return 0; } return result; } int bg_socket_write_data(int fd, const uint8_t * data, int len) { int result; result = send(fd, data, len, MSG_NOSIGNAL); if(result != len) { bg_log(BG_LOG_ERROR, LOG_DOMAIN, "Sending data failed: %s", strerror(errno)); return 0; } return result; } /* * Read a single line from a filedescriptor * * ret will be reallocated if neccesary and ret_alloc will * be updated then * * The string will be 0 terminated, a trailing \r or \n will * be removed */ #define BYTES_TO_ALLOC 1024 int bg_socket_read_line(int fd, char ** ret, int * ret_alloc, int milliseconds) { char * pos; char c; int bytes_read; bytes_read = 0; /* Allocate Memory for the case we have none */ if(!(*ret_alloc)) { *ret_alloc = BYTES_TO_ALLOC; *ret = realloc(*ret, *ret_alloc); } pos = *ret; while(1) { if(!bg_socket_read_data(fd, (uint8_t*)(&c), 1, milliseconds)) { if(!bytes_read) return 0; break; } /* * Line break sequence * is starting, remove the rest from the stream */ if(c == '\n') { break; } /* Reallocate buffer */ else if(c != '\r') { if(bytes_read+2 >= *ret_alloc) { *ret_alloc += BYTES_TO_ALLOC; *ret = realloc(*ret, *ret_alloc); pos = &((*ret)[bytes_read]); } /* Put the byte and advance pointer */ *pos = c; pos++; bytes_read++; } } *pos = '\0'; return 1; } gmerlin-1.2.0~dfsg/lib/chapterlist.c0000644000175000017500000001125411764363410017335 0ustar alessioalessio/***************************************************************** * gmerlin - a general purpose multimedia framework and applications * * Copyright (c) 2001 - 2011 Members of the Gmerlin project * gmerlin-general@lists.sourceforge.net * http://gmerlin.sourceforge.net * * 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 of the License, 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 this program. If not, see . * *****************************************************************/ #include #include #include #include #include #include bg_chapter_list_t * bg_chapter_list_create(int num_chapters) { bg_chapter_list_t * ret; ret = calloc(1, sizeof(*ret)); if(num_chapters) { ret->chapters = calloc(num_chapters, sizeof(*(ret->chapters))); ret->num_chapters = num_chapters; } return ret; } bg_chapter_list_t * bg_chapter_list_copy(const bg_chapter_list_t * list) { int i; bg_chapter_list_t * ret; if(!list || !list->num_chapters) return NULL; ret = bg_chapter_list_create(list->num_chapters); for(i = 0; i < ret->num_chapters; i++) { ret->chapters[i].time = list->chapters[i].time; ret->chapters[i].name = bg_strdup(ret->chapters[i].name, list->chapters[i].name); } ret->timescale = list->timescale; return ret; } void bg_chapter_list_destroy(bg_chapter_list_t * list) { int i; for(i = 0; i < list->num_chapters; i++) { if(list->chapters[i].name) free(list->chapters[i].name); } free(list->chapters); free(list); } void bg_chapter_list_insert(bg_chapter_list_t * list, int index, int64_t time, const char * name) { int chapters_to_add; /* Add a chapter behind the last one */ if(index >= list->num_chapters) { chapters_to_add = index + 1 - list->num_chapters; list->chapters = realloc(list->chapters, (chapters_to_add + list->num_chapters)*sizeof(*list->chapters)); memset(list->chapters + list->num_chapters, 0, sizeof(*list->chapters) * chapters_to_add); list->chapters[index].name = bg_strdup(list->chapters[index].name, name); list->chapters[index].time = time; list->num_chapters = index + 1; } else { list->chapters = realloc(list->chapters, (list->num_chapters + 1)* sizeof(*list->chapters)); memmove(list->chapters + index + 1, list->chapters + index, (list->num_chapters - index) * sizeof(*list->chapters)); list->chapters[index].name = bg_strdup(NULL, name); list->chapters[index].time = time; list->num_chapters++; } } void bg_chapter_list_delete(bg_chapter_list_t * list, int index) { if((index < 0) || (index >= list->num_chapters)) return; if(list->chapters[index].name) free(list->chapters[index].name); if(index < list->num_chapters-1) { memmove(list->chapters + index, list->chapters + index + 1, sizeof(*list->chapters) * (list->num_chapters - index)); } if(!index) list->chapters[index].time = 0; list->num_chapters--; } void bg_chapter_list_set_default_names(bg_chapter_list_t * list) { int i; for(i = 0; i < list->num_chapters; i++) { if(!list->chapters[i].name) list->chapters[i].name = bg_sprintf(TR("Chapter %d"), i+1); } } int bg_chapter_list_get_current(bg_chapter_list_t * list, gavl_time_t time) { int i; int64_t time_scaled = gavl_time_scale(list->timescale, time); for(i = 0; i < list->num_chapters-1; i++) { if(time_scaled < list->chapters[i+1].time) return i; } return list->num_chapters-1; } int bg_chapter_list_changed(bg_chapter_list_t * list, gavl_time_t time, int * current_chapter) { int ret = 0; int64_t time_scaled = gavl_time_scale(list->timescale, time); while(*current_chapter < list->num_chapters-1) { if(time_scaled >= list->chapters[(*current_chapter)+1].time) { (*current_chapter)++; ret = 1; } else break; } return ret; } gmerlin-1.2.0~dfsg/lib/player.c0000644000175000017500000002354211764363410016312 0ustar alessioalessio/***************************************************************** * Gmerlin - a general purpose multimedia framework and applications * * Copyright (c) 2001 - 2011 Members of the Gmerlin project * gmerlin-general@lists.sourceforge.net * http://gmerlin.sourceforge.net * * 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 of the License, 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 this program. If not, see . * *****************************************************************/ #include #include #include #include #include #include #define LOG_DOMAIN "player" #include /* Input callbacks */ static void duration_changed(void * data, gavl_time_t duration) { bg_player_t * p = data; bg_player_set_duration(p, duration, p->can_seek); } static void name_changed(void * data, const char * name) { bg_player_t * p = data; bg_player_set_track_name(p, name); } static void metadata_changed(void * data, const gavl_metadata_t * m) { bg_player_t * p = data; bg_player_set_metadata(p, m); } static void buffer_notify(void * data, float percentage) { bg_player_t * p = data; bg_player_set_state(p, BG_PLAYER_STATE_BUFFERING, &percentage, NULL); } static void aspect_changed(void * data, int stream, int pixel_width, int pixel_height) { bg_player_t * p = data; bg_log(BG_LOG_INFO, LOG_DOMAIN, "Aspect ratio changed"); bg_player_ov_update_aspect(&p->video_stream, pixel_width, pixel_height); } bg_player_t * bg_player_create(bg_plugin_registry_t * plugin_reg) { bg_player_t * ret; ret = calloc(1, sizeof(*ret)); /* Callbacks */ ret->input_callbacks.data = ret; ret->input_callbacks.name_changed = name_changed; ret->input_callbacks.duration_changed = duration_changed; ret->input_callbacks.metadata_changed = metadata_changed; ret->input_callbacks.buffer_notify = buffer_notify; ret->input_callbacks.aspect_changed = aspect_changed; /* Create message queues */ ret->command_queue = bg_msg_queue_create(); ret->message_queues = bg_msg_queue_list_create(); ret->visualizer = bg_visualizer_create(plugin_reg); ret->thread_common = bg_player_thread_common_create(); /* Create contexts */ bg_player_audio_create(ret, plugin_reg); bg_player_video_create(ret, plugin_reg); bg_player_subtitle_create(ret); bg_player_input_create(ret); bg_player_ov_create(ret); ret->threads[0] = ret->audio_stream.th; ret->threads[1] = ret->video_stream.th; pthread_mutex_init(&ret->state_mutex, NULL); pthread_mutex_init(&ret->config_mutex, NULL); /* Subtitles are off by default */ ret->current_subtitle_stream = -1; // ret->current_subtitle_stream = 5; ret->state = BG_PLAYER_STATE_INIT; ret->wait_time = 10000; return ret; } void bg_player_destroy(bg_player_t * player) { bg_player_input_destroy(player); bg_player_ov_destroy(player); bg_player_audio_destroy(player); bg_player_video_destroy(player); bg_player_subtitle_destroy(player); bg_visualizer_destroy(player->visualizer); bg_msg_queue_destroy(player->command_queue); bg_msg_queue_list_destroy(player->message_queues); pthread_mutex_destroy(&player->state_mutex); pthread_mutex_destroy(&player->config_mutex); bg_player_thread_common_destroy(player->thread_common); free(player); } void bg_player_add_message_queue(bg_player_t * player, bg_msg_queue_t * message_queue) { bg_msg_queue_list_add(player->message_queues, message_queue); } void bg_player_delete_message_queue(bg_player_t * player, bg_msg_queue_t * message_queue) { bg_msg_queue_list_remove(player->message_queues, message_queue); } int bg_player_get_state(bg_player_t * player) { int ret; pthread_mutex_lock(&player->state_mutex); ret = player->state; pthread_mutex_unlock(&player->state_mutex); return ret; } struct state_struct { int state; float percentage; int want_new; int can_pause; }; static void msg_state(bg_msg_t * msg, const void * data) { struct state_struct * s; s = (struct state_struct *)data; bg_msg_set_id(msg, BG_PLAYER_MSG_STATE_CHANGED); bg_msg_set_arg_int(msg, 0, s->state); if(s->state == BG_PLAYER_STATE_BUFFERING) { bg_msg_set_arg_float(msg, 1, s->percentage); } else if(s->state == BG_PLAYER_STATE_CHANGING) { bg_msg_set_arg_int(msg, 1, s->want_new); } else if(s->state == BG_PLAYER_STATE_PLAYING) { bg_msg_set_arg_int(msg, 1, s->can_pause); } } void bg_player_set_state(bg_player_t * player, int state, const void * arg1, const void * arg2) { struct state_struct s; pthread_mutex_lock(&player->state_mutex); player->state = state; pthread_mutex_unlock(&player->state_mutex); /* Broadcast this message */ // memset(&state, 0, sizeof(state)); s.state = state; if(state == BG_PLAYER_STATE_BUFFERING) s.percentage = *((const float*)arg1); else if(state == BG_PLAYER_STATE_CHANGING) s.want_new = *((const int*)arg1); else if(state == BG_PLAYER_STATE_PLAYING) s.can_pause = *((const int*)arg1); bg_msg_queue_list_send(player->message_queues, msg_state, &s); } const bg_parameter_info_t * bg_player_get_visualization_parameters(bg_player_t * player) { return bg_visualizer_get_parameters(player->visualizer); } void bg_player_set_visualization_parameter(void*data, const char * name, const bg_parameter_value_t*val) { bg_player_t * p; int do_init; p = (bg_player_t*)data; do_init = (bg_player_get_state(p) == BG_PLAYER_STATE_INIT); bg_visualizer_set_parameter(p->visualizer, name, val); if(!do_init) { if(bg_visualizer_need_restart(p->visualizer)) { bg_player_interrupt(p); bg_player_interrupt_resume(p); } } } void bg_player_set_visualization_plugin_parameter(void*data, const char * name, const bg_parameter_value_t*val) { bg_player_t * p; p = (bg_player_t*)data; bg_visualizer_set_vis_parameter(p->visualizer, name, val); } void bg_player_set_visualization(bg_player_t * p, int enable) { int was_enabled; int do_init; do_init = (bg_player_get_state(p) == BG_PLAYER_STATE_INIT); pthread_mutex_lock(&p->config_mutex); was_enabled = p->visualizer_enabled; p->visualizer_enabled = enable; pthread_mutex_unlock(&p->config_mutex); if((was_enabled != enable) && !do_init) { bg_player_interrupt(p); bg_player_interrupt_resume(p); } } void bg_player_set_visualization_plugin(bg_player_t * p, const bg_plugin_info_t * plugin_info) { int do_init; do_init = (bg_player_get_state(p) == BG_PLAYER_STATE_INIT); bg_visualizer_set_vis_plugin(p->visualizer, plugin_info); if(!do_init) { if(bg_visualizer_need_restart(p->visualizer)) { bg_player_interrupt(p); bg_player_interrupt_resume(p); } } } static const bg_parameter_info_t parameters[] = { { .name = "message_interval", .long_name = TRS("Control loop interval"), .type = BG_PARAMETER_INT, .val_default = { .val_i = 10 }, }, { .name = "time_update", .long_name = TRS("Time update interval"), .type = BG_PARAMETER_STRINGLIST, .multi_names = (char const *[]){ "seconds", "frames", NULL }, .multi_labels = (char const *[]){ TRS("Seconds"), TRS("frames"), NULL }, .val_default = { .val_str = "seconds" }, }, { .name = "report_peak", .long_name = TRS("Report peak values for audio"), .type = BG_PARAMETER_CHECKBUTTON, }, { .name = "finish_mode", .long_name = TRS("Finish mode"), .type = BG_PARAMETER_STRINGLIST, .multi_names = (char const *[]){ "change", "pause", NULL }, .multi_labels = (char const *[]){ TRS("Change"), TRS("Pause"), NULL }, .val_default = { .val_str = "change" }, }, { /* End of parameters */ } }; const bg_parameter_info_t * bg_player_get_parameters(bg_player_t * player) { return parameters; } void bg_player_set_parameter(void * player, const char * name, const bg_parameter_value_t * val) { bg_player_t * p = player; if(!name) return; else if(!strcmp(name, "message_interval")) { p->wait_time = val->val_i; p->wait_time *= 1000; } else if(!strcmp(name, "time_update")) { if(!strcmp(val->val_str, "second")) { p->time_update_mode = TIME_UPDATE_SECOND; } else if(!strcmp(val->val_str, "frame")) { p->time_update_mode = TIME_UPDATE_FRAME; } } else if(!strcmp(name, "finish_mode")) { if(!strcmp(val->val_str, "change")) { p->finish_mode = BG_PLAYER_FINISH_CHANGE; } else if(!strcmp(val->val_str, "pause")) { p->finish_mode = BG_PLAYER_FINISH_PAUSE; } } else if(!strcmp(name, "report_peak")) { if(val->val_i) p->flags |= PLAYER_DO_REPORT_PEAK; else p->flags &= ~PLAYER_DO_REPORT_PEAK; } } gmerlin-1.2.0~dfsg/lib/Makefile.am0000644000175000017500000000432711764363410016706 0ustar alessioalessioplugindir=$(pkglibdir)/plugins INCLUDES = -I$(top_srcdir)/include if HAVE_X11 x11_subdirs = x11 x11_libadd = x11/libx11.la else x11_subdirs = x11_libadd = endif if HAVE_GTK gtk_subdirs = gtk else gtk_subdirs = endif if HAVE_LV lv_sources = bglv.c lv_cflags = @LV_CFLAGS@ lv_libs = @LV_LIBS@ else lv_sources = lv_cflags = lv_libs = endif if HAVE_POSIX_SEMAPHORES sem_sources = else sem_sources = uthread_sem.c endif SUBDIRS = $(x11_subdirs) . $(gtk_subdirs) AM_CFLAGS = \ @FONTCONFIG_CFLAGS@ \ @FREETYPE_CFLAGS@ \ -DLOCALE_DIR=\"$(localedir)\" \ -DPLUGIN_DIR=\"$(plugindir)\" \ -DDOC_DIR=\"$(docdir)\" \ -DDATA_DIR=\"$(pkgdatadir)\" \ $(lv_cflags) libgmerlin_la_LDFLAGS = -version-info @LTVERSION_CURRENT@:@LTVERSION_REVISION@:@LTVERSION_AGE@ -export-symbols-regex ^bg_ libgmerlin_la_LIBADD = $(x11_libadd) @FONTCONFIG_LIBS@ @FREETYPE_LIBS@ @XML2_LIBS@ @ICONV_LIBS@ @LIBINTL@ $(lv_libs) -ldl -lpthread bin_PROGRAMS = gmerlin_visualizer_slave gmerlin_visualizer_slave_SOURCES = visualize_slave.c gmerlin_visualizer_slave_LDADD = libgmerlin.la lib_LTLIBRARIES = libgmerlin.la libgmerlin_la_SOURCES = \ $(lv_sources) \ $(sem_sources) \ accelerator.c \ album.c \ album_xml.c \ bggavl.c \ bgladspa.c \ bgfrei0r.c \ bgxml.c \ cfg_item.c \ cfg_registry.c \ cfg_section.c \ cfg_xml.c \ chapterlist.c \ chapterlist_xml.c \ charset.c \ cmdline.c \ converters.c \ device.c \ edl.c \ edldec.c \ edl_xml.c \ encoder.c \ fileformat.c \ filters.c \ formats.c \ hexdump.c \ language_table.c \ lcdproc.c \ log.c \ md5.c \ mediafiledevice.c \ metadata.c \ metadata_xml.c \ msgqueue.c \ ocr.c \ osd.c \ ov.c \ ovl2text.c \ parameter.c \ parameter_xml.c \ player.c \ player_input.c \ player_oa.c \ player_ov.c \ player_audio.c \ player_loop.c \ player_subtitle.c \ player_thread.c \ player_time.c \ player_video.c \ playercmd.c \ pluginfuncs.c \ pluginregistry.c \ pluginreg_xml.c \ preset.c \ preset_xml.c \ recorder.c \ recorder_audio.c \ recorder_video.c \ remote.c \ searchpath.c \ serialize.c \ singlepic.c \ socket.c \ streaminfo.c \ stringutils.c \ subprocess.c \ textrenderer.c \ threadpool.c \ thumbnail.c \ transcoder.c \ transcoder_pp.c \ transcoder_track.c \ transcoder_track_xml.c \ translation.c \ tree.c \ tree_xml.c \ urilist.c \ utf8.c \ visualize.c gmerlin-1.2.0~dfsg/lib/msgqueue.c0000644000175000017500000010270111764363410016644 0ustar alessioalessio/***************************************************************** * gmerlin - a general purpose multimedia framework and applications * * Copyright (c) 2001 - 2011 Members of the Gmerlin project * gmerlin-general@lists.sourceforge.net * http://gmerlin.sourceforge.net * * 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 of the License, 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 this program. If not, see . * *****************************************************************/ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #define TYPE_INT 0 #define TYPE_FLOAT 1 #define TYPE_POINTER 2 #define TYPE_POINTER_NOCOPY 3 #define TYPE_TIME 4 #define TYPE_COLOR_RGB 5 #define TYPE_COLOR_RGBA 6 #define TYPE_POSITION 7 struct bg_msg_s { uint32_t id; struct { union { int val_i; double val_f; void * val_ptr; gavl_time_t val_time; float val_color[4]; double val_pos[2]; } value; uint8_t type; uint32_t size; } args[BG_MSG_MAX_ARGS]; int num_args; sem_t produced; bg_msg_t * prev; bg_msg_t * next; }; void bg_msg_set_id(bg_msg_t * msg, int id) { msg->id = id; msg->num_args = 0; /* Zero everything */ memset(&msg->args, 0, sizeof(msg->args)); } static int check_arg(int arg) { if(arg < 0) return 0; assert(arg < BG_MSG_MAX_ARGS); return 1; } /* Set argument to a basic type */ void bg_msg_set_arg_int(bg_msg_t * msg, int arg, int value) { if(!check_arg(arg)) return; msg->args[arg].value.val_i = value; msg->args[arg].type = TYPE_INT; if(arg+1 > msg->num_args) msg->num_args = arg + 1; } void bg_msg_set_arg_time(bg_msg_t * msg, int arg, gavl_time_t value) { if(!check_arg(arg)) return; msg->args[arg].value.val_time = value; msg->args[arg].type = TYPE_TIME; if(arg+1 > msg->num_args) msg->num_args = arg + 1; } void * bg_msg_set_arg_ptr(bg_msg_t * msg, int arg, int len) { if(!check_arg(arg)) return NULL; msg->args[arg].value.val_ptr = calloc(1, len); msg->args[arg].size = len; msg->args[arg].type = TYPE_POINTER; if(arg+1 > msg->num_args) msg->num_args = arg + 1; return msg->args[arg].value.val_ptr; } void bg_msg_set_arg_ptr_nocopy(bg_msg_t * msg, int arg, void * value) { if(!check_arg(arg)) return; msg->args[arg].value.val_ptr = value; msg->args[arg].type = TYPE_POINTER_NOCOPY; if(arg+1 > msg->num_args) msg->num_args = arg + 1; } void bg_msg_set_arg_string(bg_msg_t * msg, int arg, const char * value) { int length; void * dst; if(!value) return; length = strlen(value)+1; dst = bg_msg_set_arg_ptr(msg, arg, length); memcpy(dst, value, length); if(arg+1 > msg->num_args) msg->num_args = arg + 1; } void bg_msg_set_arg_float(bg_msg_t * msg, int arg, double value) { if(!check_arg(arg)) return; msg->args[arg].value.val_f = value; msg->args[arg].type = TYPE_FLOAT; if(arg+1 > msg->num_args) msg->num_args = arg + 1; } void bg_msg_set_arg_color_rgb(bg_msg_t * msg, int arg, const float * value) { if(!check_arg(arg)) return; msg->args[arg].value.val_color[0] = value[0]; msg->args[arg].value.val_color[1] = value[1]; msg->args[arg].value.val_color[2] = value[2]; msg->args[arg].type = TYPE_COLOR_RGB; if(arg+1 > msg->num_args) msg->num_args = arg + 1; } void bg_msg_set_arg_color_rgba(bg_msg_t * msg, int arg, const float * value) { if(!check_arg(arg)) return; msg->args[arg].value.val_color[0] = value[0]; msg->args[arg].value.val_color[1] = value[1]; msg->args[arg].value.val_color[2] = value[2]; msg->args[arg].value.val_color[3] = value[3]; msg->args[arg].type = TYPE_COLOR_RGBA; if(arg+1 > msg->num_args) msg->num_args = arg + 1; } void bg_msg_set_arg_position(bg_msg_t * msg, int arg, const double * value) { if(!check_arg(arg)) return; msg->args[arg].value.val_pos[0] = value[0]; msg->args[arg].value.val_pos[1] = value[1]; msg->args[arg].type = TYPE_POSITION; if(arg+1 > msg->num_args) msg->num_args = arg + 1; } /* Get basic types */ int bg_msg_get_id(bg_msg_t * msg) { return msg->id; } int bg_msg_get_arg_int(bg_msg_t * msg, int arg) { if(!check_arg(arg)) return 0; return msg->args[arg].value.val_i; } gavl_time_t bg_msg_get_arg_time(bg_msg_t * msg, int arg) { if(!check_arg(arg)) return 0; return msg->args[arg].value.val_time; } double bg_msg_get_arg_float(bg_msg_t * msg, int arg) { if(!check_arg(arg)) return 0.0; return msg->args[arg].value.val_f; } void bg_msg_get_arg_color_rgb(bg_msg_t * msg, int arg, float * val) { if(!check_arg(arg)) return; val[0] = msg->args[arg].value.val_color[0]; val[1] = msg->args[arg].value.val_color[1]; val[2] = msg->args[arg].value.val_color[2]; } void bg_msg_get_arg_color_rgba(bg_msg_t * msg, int arg, float * val) { if(!check_arg(arg)) return; val[0] = msg->args[arg].value.val_color[0]; val[1] = msg->args[arg].value.val_color[1]; val[2] = msg->args[arg].value.val_color[2]; val[3] = msg->args[arg].value.val_color[3]; } void bg_msg_get_arg_position(bg_msg_t * msg, int arg, double * val) { if(!check_arg(arg)) return; val[0] = msg->args[arg].value.val_pos[0]; val[1] = msg->args[arg].value.val_pos[1]; } void * bg_msg_get_arg_ptr(bg_msg_t * msg, int arg, int * length) { void * ret; if(!check_arg(arg)) return NULL; ret = msg->args[arg].value.val_ptr; msg->args[arg].value.val_ptr = NULL; if(length) *length = msg->args[arg].size; return ret; } void * bg_msg_get_arg_ptr_nocopy(bg_msg_t * msg, int arg) { if(!check_arg(arg)) return NULL; return msg->args[arg].value.val_ptr; } char * bg_msg_get_arg_string(bg_msg_t * msg, int arg) { char * ret; if(!check_arg(arg)) return NULL; ret = msg->args[arg].value.val_ptr; msg->args[arg].value.val_ptr = NULL; return ret; } /* Get/Set routines for structures */ static inline uint8_t * get_8(uint8_t * data, uint32_t * val) { *val = *data; data++; return data; } static inline uint8_t * get_16(uint8_t * data, uint32_t * val) { *val = ((data[0] << 8) | data[1]); data+=2; return data; } static inline uint8_t * get_32(uint8_t * data, uint32_t * val) { *val = ((data[0] << 24) | (data[1] << 16) | (data[2] << 8) | data[3]); data+=4; return data; } static inline uint8_t * get_str(uint8_t * data, char ** val) { uint32_t len; uint8_t * ret; ret = get_32(data, &len); if(len) { *val = malloc(len+1); memcpy(*val, ret, len); (*val)[len] = '\0'; } return ret + len; } static inline uint8_t * set_8(uint8_t * data, uint8_t val) { *data = val; data++; return data; } static inline uint8_t * set_16(uint8_t * data, uint16_t val) { data[0] = (val & 0xff00) >> 8; data[1] = (val & 0xff); data+=2; return data; } static inline uint8_t * set_32(uint8_t * data, uint32_t val) { data[0] = (val & 0xff000000) >> 24; data[1] = (val & 0xff0000) >> 16; data[2] = (val & 0xff00) >> 8; data[3] = (val & 0xff); data+=4; return data; } static int str_len(const char * str) { int ret = 4; if(str) ret += strlen(str); return ret; } static inline uint8_t * set_str(uint8_t * data, const char * val) { uint32_t len; if(val) len = strlen(val); else len = 0; data = set_32(data, len); if(len) memcpy(data, val, len); return data + len; } /* int samples_per_frame; int samplerate; int num_channels; gavl_sample_format_t sample_format; gavl_interleave_mode_t interleave_mode; gavl_channel_setup_t channel_setup; int lfe; */ void bg_msg_set_arg_audio_format(bg_msg_t * msg, int arg, const gavl_audio_format_t * format) { uint8_t * ptr; int len; len = bg_serialize_audio_format(format, NULL, 0); ptr = bg_msg_set_arg_ptr(msg, arg, len); bg_serialize_audio_format(format, ptr, len); } void bg_msg_get_arg_audio_format(bg_msg_t * msg, int arg, gavl_audio_format_t * format, int * big_endian) { uint8_t * ptr; int len, be; ptr = bg_msg_get_arg_ptr(msg, arg, &len); bg_deserialize_audio_format(format, ptr, len, &be); if(big_endian) *big_endian = be; free(ptr); } /* Video format */ /* int frame_width; int frame_height; int image_width; int image_height; int pixel_width; int pixel_height; gavl_pixelformat_t pixelformat; int framerate_num; int frame_duration; int free_framerate; */ void bg_msg_set_arg_video_format(bg_msg_t * msg, int arg, const gavl_video_format_t * format) { uint8_t * ptr; int len; len = bg_serialize_video_format(format, NULL, 0); ptr = bg_msg_set_arg_ptr(msg, arg, len); bg_serialize_video_format(format, ptr, len); } void bg_msg_get_arg_video_format(bg_msg_t * msg, int arg, gavl_video_format_t * format, int * big_endian) { uint8_t * ptr; int len, be; ptr = bg_msg_get_arg_ptr(msg, arg, &len); bg_deserialize_video_format(format, ptr, len, &be); if(big_endian) *big_endian = be; free(ptr); } /* char * artist; char * title; char * album; int track; char * date; char * genre; char * comment; char * author; char * copyright; */ void bg_msg_set_arg_metadata(bg_msg_t * msg, int arg, const gavl_metadata_t * m) { int i; uint8_t * ptr; uint8_t * pos; int len = 4; for(i = 0; i < m->num_tags; i++) { len += str_len(m->tags[i].key); len += str_len(m->tags[i].val); } ptr = bg_msg_set_arg_ptr(msg, arg, len); pos = ptr; pos = set_32(pos, m->num_tags); for(i = 0; i < m->num_tags; i++) { pos = set_str(pos, m->tags[i].key); pos = set_str(pos, m->tags[i].val); } } void bg_msg_get_arg_metadata(bg_msg_t * msg, int arg, gavl_metadata_t * m) { int i; uint32_t num; uint8_t * ptr; uint8_t * pos; char * key; char * val; ptr = bg_msg_get_arg_ptr(msg, arg, NULL); pos = ptr; pos = get_32(pos, &num); for(i = 0; i < num; i++) { pos = get_str(pos, &key); pos = get_str(pos, &val); gavl_metadata_set_nocpy(m, key, val); free(key); } free(ptr); } bg_msg_t * bg_msg_create() { bg_msg_t * ret; ret = calloc(1, sizeof(*ret)); sem_init(&ret->produced, 0, 0); return ret; } void bg_msg_free(bg_msg_t * m) { int i; for(i = 0; i < m->num_args; i++) { if((m->args[i].type == TYPE_POINTER) && (m->args[i].value.val_ptr)) { free(m->args[i].value.val_ptr); m->args[i].value.val_ptr = NULL; } } } void bg_msg_destroy(bg_msg_t * m) { bg_msg_free(m); sem_destroy(&m->produced); free(m); } /* Audio frame: .arg_0 = valid samples .arg_1 = timestamp .arg_2 = big endian */ int bg_msg_write_audio_frame(bg_msg_t * msg, const gavl_audio_format_t * format, const gavl_audio_frame_t * frame, bg_msg_write_callback_t cb, void * cb_data) { uint8_t * ptr; int len; len = bg_serialize_audio_frame_header(format, frame, NULL, 0); ptr = bg_msg_set_arg_ptr(msg, 0, len); bg_serialize_audio_frame_header(format, frame, ptr, len); if(!bg_msg_write(msg, cb, cb_data)) return 0; return bg_serialize_audio_frame(format, frame, cb, cb_data); } /** \brief Read an audio frame from a socket * \param msg Message containing the frame header * \param format Audio format * \param frame An audio frame * \param fd A socket * \returns 1 on success, 0 on error * * Before you can use this function, msg must contain * a valid audio frame header */ int bg_msg_read_audio_frame(gavl_dsp_context_t * ctx, bg_msg_t * msg, const gavl_audio_format_t * format, gavl_audio_frame_t * frame, bg_msg_read_callback_t cb, void * cb_data, int big_endian) { uint8_t * ptr; int len; ptr = bg_msg_get_arg_ptr(msg, 0, &len); bg_deserialize_audio_frame_header(format, frame, ptr, len); free(ptr); return bg_deserialize_audio_frame(ctx, format, frame, cb, cb_data, big_endian); } /* .parameters = .arg_0 = name .arg_1 = type (int) .arg_2 = value */ void bg_msg_set_parameter(bg_msg_t * msg, const char * name, bg_parameter_type_t type, const bg_parameter_value_t * val) { if(!name) return; bg_msg_set_arg_string(msg, 0, name); bg_msg_set_arg_int(msg, 1, type); switch(type) { case BG_PARAMETER_SECTION: //!< Dummy type. It contains no data but acts as a separator in notebook style configuration windows case BG_PARAMETER_BUTTON: /* Button (just tell we are called) */ break; case BG_PARAMETER_CHECKBUTTON: //!< Bool case BG_PARAMETER_INT: //!< Integer spinbutton case BG_PARAMETER_SLIDER_INT: //!< Integer slider bg_msg_set_arg_int(msg, 2, val->val_i); break; case BG_PARAMETER_FLOAT: // spinbutton case BG_PARAMETER_SLIDER_FLOAT: //!< Float slider bg_msg_set_arg_float(msg, 2, val->val_f); break; case BG_PARAMETER_STRING: //!< String (one line only) case BG_PARAMETER_STRING_HIDDEN: //!< Encrypted string (displays as ***) case BG_PARAMETER_STRINGLIST: //!< Popdown menu with string values case BG_PARAMETER_FONT: //!< Font (contains fontconfig compatible fontname) case BG_PARAMETER_DEVICE: //!< Device case BG_PARAMETER_FILE: //!< File case BG_PARAMETER_DIRECTORY: //!< Directory case BG_PARAMETER_MULTI_MENU: //!< Menu with config- and infobutton case BG_PARAMETER_MULTI_LIST: //!< List with config- and infobutton case BG_PARAMETER_MULTI_CHAIN: //!< Several subitems (including suboptions) can be arranged in a chain bg_msg_set_arg_string(msg, 2, val->val_str); break; case BG_PARAMETER_COLOR_RGB: //!< RGB Color bg_msg_set_arg_color_rgb(msg, 2, val->val_color); break; case BG_PARAMETER_COLOR_RGBA: //!< RGBA Color bg_msg_set_arg_color_rgba(msg, 2, val->val_color); break; case BG_PARAMETER_POSITION: //!< RGBA Color bg_msg_set_arg_position(msg, 2, val->val_pos); break; case BG_PARAMETER_TIME: //!< Time bg_msg_set_arg_time(msg, 2, val->val_time); break; } } void bg_msg_get_parameter(bg_msg_t * msg, char ** name, bg_parameter_type_t * type, bg_parameter_value_t * val) { *name = bg_msg_get_arg_string(msg, 0); if(!*name) return; *type = bg_msg_get_arg_int(msg, 1); switch(*type) { case BG_PARAMETER_SECTION: //!< Dummy type. It contains no data but acts as a separator in notebook style configuration windows case BG_PARAMETER_BUTTON: break; case BG_PARAMETER_CHECKBUTTON: //!< Bool case BG_PARAMETER_INT: //!< Integer spinbutton case BG_PARAMETER_SLIDER_INT: //!< Integer slider val->val_i = bg_msg_get_arg_int(msg, 2); break; case BG_PARAMETER_FLOAT: // spinbutton case BG_PARAMETER_SLIDER_FLOAT: //!< Float slider val->val_f = bg_msg_get_arg_float(msg, 2); break; case BG_PARAMETER_STRING: //!< String (one line only) case BG_PARAMETER_STRING_HIDDEN: //!< Encrypted string (displays as ***) case BG_PARAMETER_STRINGLIST: //!< Popdown menu with string values case BG_PARAMETER_FONT: //!< Font (contains fontconfig compatible fontname) case BG_PARAMETER_DEVICE: //!< Device case BG_PARAMETER_FILE: //!< File case BG_PARAMETER_DIRECTORY: //!< Directory case BG_PARAMETER_MULTI_MENU: //!< Menu with config- and infobutton case BG_PARAMETER_MULTI_LIST: //!< List with config- and infobutton case BG_PARAMETER_MULTI_CHAIN: //!< Several subitems (including suboptions) can be arranged in a chain val->val_str = bg_msg_get_arg_string(msg, 2); break; case BG_PARAMETER_COLOR_RGB: //!< RGB Color bg_msg_get_arg_color_rgb(msg, 2, val->val_color); break; case BG_PARAMETER_COLOR_RGBA: //!< RGBA Color bg_msg_get_arg_color_rgba(msg, 2, val->val_color); break; case BG_PARAMETER_POSITION: //!< RGBA Color bg_msg_get_arg_position(msg, 2, val->val_pos); break; case BG_PARAMETER_TIME: //!< Time bg_msg_set_arg_time(msg, 2, val->val_time); break; } } struct bg_msg_queue_s { bg_msg_t * msg_input; bg_msg_t * msg_output; bg_msg_t * msg_last; pthread_mutex_t chain_mutex; pthread_mutex_t write_mutex; int num_messages; /* Number of total messages */ }; bg_msg_queue_t * bg_msg_queue_create() { bg_msg_queue_t * ret; ret = calloc(1, sizeof(*ret)); /* Allocate at least 2 messages */ ret->msg_output = bg_msg_create(); ret->msg_output->next = bg_msg_create(); /* Set in- and output messages */ ret->msg_input = ret->msg_output; ret->msg_last = ret->msg_output->next; /* Initialize chain mutex */ pthread_mutex_init(&ret->chain_mutex, NULL); pthread_mutex_init(&ret->write_mutex, NULL); return ret; } void bg_msg_queue_destroy(bg_msg_queue_t * m) { bg_msg_t * tmp_message; while(m->msg_output) { tmp_message = m->msg_output->next; bg_msg_destroy(m->msg_output); m->msg_output = tmp_message; } free(m); } /* Lock message queue for reading, block until something arrives */ bg_msg_t * bg_msg_queue_lock_read(bg_msg_queue_t * m) { while(sem_wait(&m->msg_output->produced) == -1) { if(errno != EINTR) return NULL; } return m->msg_output; // sem_ret->msg_output } bg_msg_t * bg_msg_queue_try_lock_read(bg_msg_queue_t * m) { if(!sem_trywait(&m->msg_output->produced)) return m->msg_output; else return NULL; } int bg_msg_queue_peek(bg_msg_queue_t * m, uint32_t * id) { int sem_val; sem_getvalue(&m->msg_output->produced, &sem_val); if(sem_val) { if(id) *id = m->msg_output->id; return 1; } else return 0; } void bg_msg_queue_unlock_read(bg_msg_queue_t * m) { bg_msg_t * old_out_message; pthread_mutex_lock(&m->chain_mutex); old_out_message = m->msg_output; bg_msg_free(old_out_message); m->msg_output = m->msg_output->next; m->msg_last->next = old_out_message; m->msg_last = m->msg_last->next; m->msg_last->next = NULL; pthread_mutex_unlock(&m->chain_mutex); } /* * Lock queue for writing */ bg_msg_t * bg_msg_queue_lock_write(bg_msg_queue_t * m) { pthread_mutex_lock(&m->write_mutex); return m->msg_input; } void bg_msg_queue_unlock_write(bg_msg_queue_t * m) { bg_msg_t * message = m->msg_input; pthread_mutex_lock(&m->chain_mutex); if(!m->msg_input->next) { m->msg_input->next = bg_msg_create(); m->msg_last = m->msg_input->next; } m->msg_input = m->msg_input->next; sem_post(&message->produced); pthread_mutex_unlock(&m->chain_mutex); pthread_mutex_unlock(&m->write_mutex); } typedef struct list_entry_s { bg_msg_queue_t * q; struct list_entry_s * next; } list_entry_t; struct bg_msg_queue_list_s { list_entry_t * entries; pthread_mutex_t mutex; }; bg_msg_queue_list_t * bg_msg_queue_list_create() { bg_msg_queue_list_t * ret = calloc(1, sizeof(*ret)); pthread_mutex_init(&ret->mutex, NULL); return ret; } void bg_msg_queue_list_destroy(bg_msg_queue_list_t * l) { list_entry_t * tmp_entry; while(l->entries) { tmp_entry = l->entries->next; free(l->entries); l->entries = tmp_entry; } free(l); } void bg_msg_queue_list_send(bg_msg_queue_list_t * l, void (*set_message)(bg_msg_t * message, const void * data), const void * data) { bg_msg_t * msg; list_entry_t * entry; pthread_mutex_lock(&l->mutex); entry = l->entries; while(entry) { msg = bg_msg_queue_lock_write(entry->q); set_message(msg, data); bg_msg_queue_unlock_write(entry->q); entry = entry->next; } pthread_mutex_unlock(&l->mutex); } void bg_msg_queue_list_add(bg_msg_queue_list_t * list, bg_msg_queue_t * queue) { list_entry_t * new_entry; new_entry = calloc(1, sizeof(*new_entry)); pthread_mutex_lock(&list->mutex); new_entry->next = list->entries; new_entry->q = queue; list->entries = new_entry; pthread_mutex_unlock(&list->mutex); } void bg_msg_queue_list_remove(bg_msg_queue_list_t * list, bg_msg_queue_t * queue) { list_entry_t * tmp_entry; list_entry_t * entry_before; pthread_mutex_lock(&list->mutex); if(list->entries->q == queue) { tmp_entry = list->entries->next; free(list->entries); list->entries = tmp_entry; } else { entry_before = list->entries; while(entry_before->next->q != queue) entry_before = entry_before->next; tmp_entry = entry_before->next; entry_before->next = tmp_entry->next; free(tmp_entry); } pthread_mutex_unlock(&list->mutex); } /* * This on will be used for remote controls, * return FALSE on error */ /* This is how a message is passed through pipes and sockets: * * content [ id |nargs|.... * bytes |0|1|2|3| 4 |5.... * * An int argument is encoded as: * content | type | value | * bytes | 0 |1|2|3|4| * * Type is TYPE_INT, byte order is big endian (network byte order) * * Floating point arguments are coded with type TYPE_FLOAT and the * value as an integer * * String arguments are coded as: * content |length |string including final '\0'| * bytes |0|1|2|3|4 .. 4 + len | * * Pointer messages cannot be transmited! */ static int read_uint32(uint32_t * ret, bg_msg_read_callback_t cb, void * cb_data) { uint8_t buf[4]; if(cb(cb_data, buf, 4) < 4) return 0; // bg_hexdump(buf, 4); *ret = (buf[0]<<24) | (buf[1]<<16) | (buf[2]<<8) | buf[3]; return 1; } static int read_uint64(uint64_t * ret, bg_msg_read_callback_t cb, void * cb_data) { uint8_t buf[8]; if(cb(cb_data, buf, 8) < 8) return 0; *ret = ((gavl_time_t)(buf[0])<<56) | ((gavl_time_t)(buf[1])<<48) | ((gavl_time_t)(buf[2])<<40) | ((gavl_time_t)(buf[3])<<32) | ((gavl_time_t)(buf[4])<<24) | ((gavl_time_t)(buf[5])<<16) | ((gavl_time_t)(buf[6])<<8) | ((gavl_time_t)(buf[7])); return 1; } static float float32_be_read (unsigned char *cptr) { int exponent, mantissa, negative ; float fvalue ; negative = cptr [0] & 0x80 ; exponent = ((cptr [0] & 0x7F) << 1) | ((cptr [1] & 0x80) ? 1 : 0) ; mantissa = ((cptr [1] & 0x7F) << 16) | (cptr [2] << 8) | (cptr [3]) ; if (! (exponent || mantissa)) return 0.0 ; mantissa |= 0x800000 ; exponent = exponent ? exponent - 127 : 0 ; fvalue = mantissa ? ((float) mantissa) / ((float) 0x800000) : 0.0 ; if (negative) fvalue *= -1 ; if (exponent > 0) fvalue *= (1 << exponent) ; else if (exponent < 0) fvalue /= (1 << abs (exponent)) ; return fvalue ; } /* float32_be_read */ static int read_float(float * ret, bg_msg_read_callback_t cb, void * cb_data) { uint8_t buf[4]; if(cb(cb_data, buf, 4) < 4) return 0; *ret = float32_be_read(buf); return 1; } static double double64_be_read (unsigned char *cptr) { int exponent, negative ; double dvalue ; negative = (cptr [0] & 0x80) ? 1 : 0 ; exponent = ((cptr [0] & 0x7F) << 4) | ((cptr [1] >> 4) & 0xF) ; /* Might not have a 64 bit long, so load the mantissa into a double. */ dvalue = (((cptr [1] & 0xF) << 24) | (cptr [2] << 16) | (cptr [3] << 8) | cptr [4]) ; dvalue += ((cptr [5] << 16) | (cptr [6] << 8) | cptr [7]) / ((double) 0x1000000) ; if (exponent == 0 && dvalue == 0.0) return 0.0 ; dvalue += 0x10000000 ; exponent = exponent - 0x3FF ; dvalue = dvalue / ((double) 0x10000000) ; if (negative) dvalue *= -1 ; if (exponent > 0) dvalue *= (1 << exponent) ; else if (exponent < 0) dvalue /= (1 << abs (exponent)) ; return dvalue ; } /* double64_be_read */ static int read_double(double * ret, bg_msg_read_callback_t cb, void * cb_data) { uint8_t buf[8]; if(cb(cb_data, buf, 8) < 8) return 0; *ret = double64_be_read(buf); return 1; } static int read_time(gavl_time_t * ret, bg_msg_read_callback_t cb, void * cb_data) { return read_uint64((uint64_t*)ret, cb, cb_data); } static int write_uint32(uint32_t * val, bg_msg_write_callback_t cb, void * cb_data) { uint8_t buf[4]; buf[0] = (*val & 0xff000000) >> 24; buf[1] = (*val & 0x00ff0000) >> 16; buf[2] = (*val & 0x0000ff00) >> 8; buf[3] = (*val & 0x000000ff); // bg_hexdump(buf, 4); if(cb(cb_data, buf, 4) < 4) return 0; return 1; } static int write_uint64(uint64_t val, bg_msg_write_callback_t cb, void * cb_data) { uint8_t buf[8]; buf[0] = (val & 0xff00000000000000LL) >> 56; buf[1] = (val & 0x00ff000000000000LL) >> 48; buf[2] = (val & 0x0000ff0000000000LL) >> 40; buf[3] = (val & 0x000000ff00000000LL) >> 32; buf[4] = (val & 0x00000000ff000000LL) >> 24; buf[5] = (val & 0x0000000000ff0000LL) >> 16; buf[6] = (val & 0x000000000000ff00LL) >> 8; buf[7] = (val & 0x00000000000000ffLL); if(cb(cb_data, buf, 8) < 8) return 0; return 1; } static void float32_be_write (float in, unsigned char *out) { int exponent, mantissa, negative = 0 ; memset (out, 0, sizeof (int)) ; if (in == 0.0) return ; if (in < 0.0) { in *= -1.0 ; negative = 1 ; } ; in = frexp (in, &exponent) ; exponent += 126 ; in *= (float) 0x1000000 ; mantissa = (((int) in) & 0x7FFFFF) ; if (negative) out [0] |= 0x80 ; if (exponent & 0x01) out [1] |= 0x80 ; out [3] = mantissa & 0xFF ; out [2] = (mantissa >> 8) & 0xFF ; out [1] |= (mantissa >> 16) & 0x7F ; out [0] |= (exponent >> 1) & 0x7F ; return ; } /* float32_be_write */ static int write_float(float val, bg_msg_write_callback_t cb, void * cb_data) { uint8_t buf[4]; float32_be_write(val, buf); if(cb(cb_data, buf, 4) < 4) return 0; return 1; } static void double64_be_write (double in, unsigned char *out) { int exponent, mantissa ; memset (out, 0, sizeof (double)) ; if (in == 0.0) return ; if (in < 0.0) { in *= -1.0 ; out [0] |= 0x80 ; } ; in = frexp (in, &exponent) ; exponent += 1022 ; out [0] |= (exponent >> 4) & 0x7F ; out [1] |= (exponent << 4) & 0xF0 ; in *= 0x20000000 ; mantissa = lrint (floor (in)) ; out [1] |= (mantissa >> 24) & 0xF ; out [2] = (mantissa >> 16) & 0xFF ; out [3] = (mantissa >> 8) & 0xFF ; out [4] = mantissa & 0xFF ; in = fmod (in, 1.0) ; in *= 0x1000000 ; mantissa = lrint (floor (in)) ; out [5] = (mantissa >> 16) & 0xFF ; out [6] = (mantissa >> 8) & 0xFF ; out [7] = mantissa & 0xFF ; return ; } /* double64_be_write */ static int write_double(double val, bg_msg_write_callback_t cb, void * cb_data) { uint8_t buf[8]; double64_be_write(val, buf); if(cb(cb_data, buf, 8) < 8) return 0; return 1; } static int write_time(gavl_time_t val, bg_msg_write_callback_t cb, void * cb_data) { return write_uint64((uint64_t)val, cb, cb_data); } int bg_msg_read(bg_msg_t * ret, bg_msg_read_callback_t cb, void * cb_data) { int i; void * ptr; int32_t val_i; gavl_time_t val_time; uint8_t val_u8; memset(ret, 0, sizeof(*ret)); /* Message ID */ if(!read_uint32((uint32_t*)(&val_i), cb, cb_data)) return 0; ret->id = val_i; /* Number of arguments */ if(!cb(cb_data, &val_u8, 1)) return 0; ret->num_args = val_u8; for(i = 0; i < ret->num_args; i++) { if(!cb(cb_data, &val_u8, 1)) return 0; ret->args[i].type = val_u8; switch(ret->args[i].type) { case TYPE_INT: if(!read_uint32((uint32_t*)(&val_i), cb, cb_data)) return 0; ret->args[i].value.val_i = val_i; break; case TYPE_FLOAT: if(!read_double(&ret->args[i].value.val_f, cb, cb_data)) return 0; break; case TYPE_POINTER: if(!read_uint32((uint32_t*)(&val_i), cb, cb_data)) /* Length */ return 0; ptr = bg_msg_set_arg_ptr(ret, i, val_i); if(cb(cb_data, ret->args[i].value.val_ptr, val_i) < val_i) return 0; break; case TYPE_TIME: if(!read_time(&val_time, cb, cb_data)) return 0; ret->args[i].value.val_time = val_time; break; case TYPE_POINTER_NOCOPY: break; case TYPE_COLOR_RGB: if(!read_float(&ret->args[i].value.val_color[0], cb, cb_data) || !read_float(&ret->args[i].value.val_color[1], cb, cb_data) || !read_float(&ret->args[i].value.val_color[2], cb, cb_data)) return 0; break; case TYPE_COLOR_RGBA: if(!read_float(&ret->args[i].value.val_color[0], cb, cb_data) || !read_float(&ret->args[i].value.val_color[1], cb, cb_data) || !read_float(&ret->args[i].value.val_color[2], cb, cb_data) || !read_float(&ret->args[i].value.val_color[3], cb, cb_data)) return 0; break; } } return 1; } int bg_msg_write(bg_msg_t * msg, bg_msg_write_callback_t cb, void * cb_data) { int i; uint8_t val_u8; /* Message id */ if(!write_uint32(&msg->id, cb, cb_data)) return 0; /* Number of arguments */ val_u8 = msg->num_args; if(!cb(cb_data, &val_u8, 1)) return 0; /* Arguments */ for(i = 0; i < msg->num_args; i++) { cb(cb_data, &msg->args[i].type, 1); switch(msg->args[i].type) { case TYPE_INT: if(!write_uint32((uint32_t*)(&msg->args[i].value.val_i), cb, cb_data)) return 0; break; case TYPE_TIME: if(!write_time(msg->args[i].value.val_time, cb, cb_data)) return 0; break; case TYPE_FLOAT: if(!write_double(msg->args[i].value.val_f, cb, cb_data)) return 0; break; case TYPE_POINTER: if(!write_uint32(&msg->args[i].size, cb, cb_data)) return 0; if(cb(cb_data, msg->args[i].value.val_ptr, msg->args[i].size) < msg->args[i].size) return 0; break; case TYPE_POINTER_NOCOPY: break; case TYPE_COLOR_RGB: if(!write_float(msg->args[i].value.val_color[0], cb, cb_data) || !write_float(msg->args[i].value.val_color[1], cb, cb_data) || !write_float(msg->args[i].value.val_color[2], cb, cb_data)) return 0; break; case TYPE_COLOR_RGBA: if(!write_float(msg->args[i].value.val_color[0], cb, cb_data) || !write_float(msg->args[i].value.val_color[1], cb, cb_data) || !write_float(msg->args[i].value.val_color[2], cb, cb_data) || !write_float(msg->args[i].value.val_color[3], cb, cb_data)) return 0; break; } } return 1; } typedef struct { int timeout; int fd; } socket_data; static int socket_read_cb(void * data, uint8_t * ptr, int len) { int result; socket_data * cb_data = (socket_data *)data; result = bg_socket_read_data(cb_data->fd, ptr, len, cb_data->timeout); /* After a successful read, timeout must be disabled */ if(result && cb_data->timeout >= 0) cb_data->timeout = -1; return result; } static int socket_write_cb(void * data, const uint8_t * ptr, int len) { socket_data * cb_data = (socket_data *)data; return bg_socket_write_data(cb_data->fd, ptr, len); } int bg_msg_read_socket(bg_msg_t * ret, int fd, int milliseconds) { socket_data cb_data; cb_data.fd = fd; cb_data.timeout = milliseconds; return bg_msg_read(ret, socket_read_cb, &cb_data); } int bg_msg_write_socket(bg_msg_t * msg, int fd) { socket_data cb_data; cb_data.fd = fd; cb_data.timeout = 0; return bg_msg_write(msg, socket_write_cb, &cb_data); } gmerlin-1.2.0~dfsg/lib/streaminfo.c0000644000175000017500000000705411764363410017165 0ustar alessioalessio/***************************************************************** * gmerlin - a general purpose multimedia framework and applications * * Copyright (c) 2001 - 2011 Members of the Gmerlin project * gmerlin-general@lists.sourceforge.net * http://gmerlin.sourceforge.net * * 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 of the License, 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 this program. If not, see . * *****************************************************************/ #include #include #include #include #include #include #include #include #define MY_FREE(ptr) \ if(ptr) \ { \ free(ptr); \ ptr = NULL; \ } static void bg_audio_info_free(bg_audio_info_t * info) { gavl_metadata_free(&info->m); } static void bg_video_info_free(bg_video_info_t * info) { gavl_metadata_free(&info->m); } static void bg_subtitle_info_free(bg_subtitle_info_t * info) { gavl_metadata_free(&info->m); } void bg_track_info_free(bg_track_info_t * info) { int i; if(info->audio_streams) { for(i = 0; i < info->num_audio_streams; i++) bg_audio_info_free(&info->audio_streams[i]); MY_FREE(info->audio_streams); } if(info->video_streams) { for(i = 0; i < info->num_video_streams; i++) bg_video_info_free(&info->video_streams[i]); MY_FREE(info->video_streams); } if(info->subtitle_streams) { for(i = 0; i < info->num_subtitle_streams; i++) bg_subtitle_info_free(&info->subtitle_streams[i]); MY_FREE(info->subtitle_streams); } gavl_metadata_free(&info->metadata); if(info->chapter_list) bg_chapter_list_destroy(info->chapter_list); MY_FREE(info->name); MY_FREE(info->url); memset(info, 0, sizeof(*info)); } void bg_set_track_name_default(bg_track_info_t * info, const char * location) { const char * start_pos; const char * end_pos; if(bg_string_is_url(location)) { info->name = bg_strdup(info->name, location); return; } start_pos = strrchr(location, '/'); if(start_pos) start_pos++; else start_pos = location; end_pos = strrchr(start_pos, '.'); if(!end_pos) end_pos = &start_pos[strlen(start_pos)]; info->name = bg_strndup(info->name, start_pos, end_pos); } char * bg_get_track_name_default(const char * location, int track, int num_tracks) { const char * start_pos; const char * end_pos; char * tmp_string, *ret; if(bg_string_is_url(location)) { tmp_string = bg_strdup(NULL, location); } else { start_pos = strrchr(location, '/'); if(start_pos) start_pos++; else start_pos = location; end_pos = strrchr(start_pos, '.'); if(!end_pos) end_pos = &start_pos[strlen(start_pos)]; tmp_string = bg_system_to_utf8(start_pos, end_pos - start_pos); } if(num_tracks < 2) return tmp_string; else { ret = bg_sprintf("%s [%d]", tmp_string, track + 1); free(tmp_string); return ret; } } gmerlin-1.2.0~dfsg/lib/pluginreg_xml.c0000644000175000017500000005153411764363410017674 0ustar alessioalessio/***************************************************************** * gmerlin - a general purpose multimedia framework and applications * * Copyright (c) 2001 - 2011 Members of the Gmerlin project * gmerlin-general@lists.sourceforge.net * http://gmerlin.sourceforge.net * * 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 of the License, 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 this program. If not, see . * *****************************************************************/ #include #include #include #include #include #include static const struct { char * name; bg_plugin_type_t type; } type_names[] = { { "Input", BG_PLUGIN_INPUT }, { "OutputAudio", BG_PLUGIN_OUTPUT_AUDIO }, { "OutputVideo", BG_PLUGIN_OUTPUT_VIDEO }, { "AudioRecorder", BG_PLUGIN_RECORDER_AUDIO }, { "VideoRecorder", BG_PLUGIN_RECORDER_VIDEO }, { "EncoderAudio", BG_PLUGIN_ENCODER_AUDIO }, { "EncoderVideo", BG_PLUGIN_ENCODER_VIDEO }, { "EncoderSubtitleText", BG_PLUGIN_ENCODER_SUBTITLE_TEXT }, { "EncoderSubtitleOverlay", BG_PLUGIN_ENCODER_SUBTITLE_OVERLAY }, { "Encoder", BG_PLUGIN_ENCODER }, { "EncoderPP", BG_PLUGIN_ENCODER_PP }, { "ImageReader", BG_PLUGIN_IMAGE_READER }, { "ImageWriter", BG_PLUGIN_IMAGE_WRITER }, { "AudioFilter", BG_PLUGIN_FILTER_AUDIO }, { "VideoFilter", BG_PLUGIN_FILTER_VIDEO }, { "Visualization", BG_PLUGIN_VISUALIZATION }, { NULL, BG_PLUGIN_NONE } }; static const struct { char * name; int api; } api_names[] = { { "gmerlin", BG_PLUGIN_API_GMERLIN }, { "ladspa", BG_PLUGIN_API_LADSPA }, { "lv", BG_PLUGIN_API_LV }, { "frei0r", BG_PLUGIN_API_FREI0R }, { NULL, BG_PLUGIN_NONE } }; static const struct { char * name; int flag; } flag_names[] = { { "Removable", BG_PLUGIN_REMOVABLE }, /* Removable media (CD, DVD etc.) */ { "Recorder", BG_PLUGIN_RECORDER }, /* Plugin can record */ { "File", BG_PLUGIN_FILE }, /* Plugin reads/writes files */ { "URL", BG_PLUGIN_URL }, /* Plugin reads URLs or streams */ { "Playback", BG_PLUGIN_PLAYBACK }, /* Output plugins for playback */ { "Stdin", BG_PLUGIN_STDIN }, /* Plugin reads from stdin */ { "Tuner", BG_PLUGIN_TUNER }, /* Plugin has tuner */ { "Filter1", BG_PLUGIN_FILTER_1 }, /* Filter with one input port */ { "EmbedWindow", BG_PLUGIN_EMBED_WINDOW }, { "VisualizeFrame", BG_PLUGIN_VISUALIZE_FRAME }, { "VisualizeGL", BG_PLUGIN_VISUALIZE_GL }, { "PP", BG_PLUGIN_PP }, { "Callbacks", BG_PLUGIN_CALLBACKS }, { "Broadcast", BG_PLUGIN_BROADCAST }, { "Devparam", BG_PLUGIN_DEVPARAM }, { "Unsupported", BG_PLUGIN_UNSUPPORTED }, { NULL, 0 }, }; static const char * const plugin_key = "PLUGIN"; static const char * const plugin_registry_key = "PLUGIN_REGISTRY"; static const char * const name_key = "NAME"; static const char * const long_name_key = "LONG_NAME"; static const char * const description_key = "DESCRIPTION"; static const char * const mimetypes_key = "MIMETYPES"; static const char * const extensions_key = "EXTENSIONS"; static const char * const protocols_key = "PROTOCOLS"; static const char * const module_filename_key = "MODULE_FILENAME"; static const char * const module_time_key = "MODULE_TIME"; static const char * const type_key = "TYPE"; static const char * const flags_key = "FLAGS"; static const char * const priority_key = "PRIORITY"; static const char * const device_info_key = "DEVICE_INFO"; static const char * const device_key = "DEVICE"; static const char * const max_audio_streams_key = "MAX_AUDIO_STREAMS"; static const char * const max_video_streams_key = "MAX_VIDEO_STREAMS"; static const char * const max_subtitle_text_streams_key = "MAX_SUBTITLE_TEXT_STREAMS"; static const char * const max_subtitle_overlay_streams_key = "MAX_SUBTITLE_OVERLAY_STREAMS"; static const char * const parameters_key = "PARAMETERS"; static const char * const audio_parameters_key = "AUDIO_PARAMETERS"; static const char * const video_parameters_key = "VIDEO_PARAMETERS"; static const char * const subtitle_text_parameters_key = "SUBTITLE_TEXT_PARAMETERS"; static const char * const subtitle_overlay_parameters_key = "SUBTITLE_OVERLAY_PARAMETERS"; static const char * const gettext_domain_key = "GETTEXT_DOMAIN"; static const char * const gettext_directory_key = "GETTEXT_DIRECTORY"; static const char * const api_key = "API"; static const char * const index_key = "INDEX"; static bg_device_info_t * load_device(bg_device_info_t * arr, xmlDocPtr doc, xmlNodePtr node) { char * tmp_string; xmlNodePtr cur; char * device = NULL; char * name = NULL; cur = node->children; while(cur) { if(!cur->name) { cur = cur->next; continue; } tmp_string = (char*)xmlNodeListGetString(doc, cur->children, 1); if(!BG_XML_STRCMP(cur->name, name_key)) { name = tmp_string; tmp_string = NULL; } else if(!BG_XML_STRCMP(cur->name, device_key)) { device = tmp_string; tmp_string = NULL; } if(tmp_string) free(tmp_string); cur = cur->next; } if(device) { arr = bg_device_info_append(arr, device, name); xmlFree(device); } if(name) { xmlFree(name); } return arr; } static bg_plugin_info_t * load_plugin(xmlDocPtr doc, xmlNodePtr node) { char * tmp_string; xmlNodePtr cur; int index; char * start_ptr; char * end_ptr; bg_plugin_info_t * ret; ret = calloc(1, sizeof(*ret)); cur = node->children; while(cur) { if(!cur->name) { cur = cur->next; continue; } if(!BG_XML_STRCMP(cur->name, parameters_key)) { ret->parameters = bg_xml_2_parameters(doc, cur); cur = cur->next; continue; } else if(!BG_XML_STRCMP(cur->name, audio_parameters_key)) { ret->audio_parameters = bg_xml_2_parameters(doc, cur); cur = cur->next; continue; } else if(!BG_XML_STRCMP(cur->name, video_parameters_key)) { ret->video_parameters = bg_xml_2_parameters(doc, cur); cur = cur->next; continue; } else if(!BG_XML_STRCMP(cur->name, subtitle_text_parameters_key)) { ret->subtitle_text_parameters = bg_xml_2_parameters(doc, cur); cur = cur->next; continue; } else if(!BG_XML_STRCMP(cur->name, subtitle_overlay_parameters_key)) { ret->subtitle_overlay_parameters = bg_xml_2_parameters(doc, cur); cur = cur->next; continue; } tmp_string = (char*)xmlNodeListGetString(doc, cur->children, 1); if(!BG_XML_STRCMP(cur->name, name_key)) { ret->name = bg_strdup(ret->name, tmp_string); } else if(!BG_XML_STRCMP(cur->name, long_name_key)) { ret->long_name = bg_strdup(ret->long_name, tmp_string); } else if(!BG_XML_STRCMP(cur->name, description_key)) { ret->description = bg_strdup(ret->description, tmp_string); } else if(!BG_XML_STRCMP(cur->name, mimetypes_key)) { ret->mimetypes = bg_strdup(ret->mimetypes, tmp_string); } else if(!BG_XML_STRCMP(cur->name, extensions_key)) { ret->extensions = bg_strdup(ret->extensions, tmp_string); } else if(!BG_XML_STRCMP(cur->name, protocols_key)) { ret->protocols = bg_strdup(ret->protocols, tmp_string); } else if(!BG_XML_STRCMP(cur->name, module_filename_key)) { ret->module_filename = bg_strdup(ret->module_filename, tmp_string); } else if(!BG_XML_STRCMP(cur->name, gettext_domain_key)) { ret->gettext_domain = bg_strdup(ret->gettext_domain, tmp_string); } else if(!BG_XML_STRCMP(cur->name, gettext_directory_key)) { ret->gettext_directory = bg_strdup(ret->gettext_directory, tmp_string); } else if(!BG_XML_STRCMP(cur->name, module_time_key)) { sscanf(tmp_string, "%ld", &ret->module_time); } else if(!BG_XML_STRCMP(cur->name, priority_key)) { sscanf(tmp_string, "%d", &ret->priority); } else if(!BG_XML_STRCMP(cur->name, index_key)) { sscanf(tmp_string, "%d", &ret->index); } else if(!BG_XML_STRCMP(cur->name, type_key)) { index = 0; while(type_names[index].name) { if(!strcmp(tmp_string, type_names[index].name)) { ret->type = type_names[index].type; break; } index++; } } else if(!BG_XML_STRCMP(cur->name, api_key)) { index = 0; while(api_names[index].name) { if(!strcmp(tmp_string, api_names[index].name)) { ret->api = api_names[index].api; break; } index++; } } else if(!BG_XML_STRCMP(cur->name, flags_key)) { start_ptr = tmp_string; while(1) { if(!start_ptr) break; end_ptr = strchr(start_ptr, '|'); if(!end_ptr) end_ptr = &start_ptr[strlen(start_ptr)]; index = 0; while(flag_names[index].name) { if(!strncmp(flag_names[index].name, start_ptr, end_ptr - start_ptr)) ret->flags |= flag_names[index].flag; index++; } if(*end_ptr == '\0') break; start_ptr = end_ptr; start_ptr++; } } else if(!BG_XML_STRCMP(cur->name, device_info_key)) { ret->devices = load_device(ret->devices, doc, cur); } else if(!BG_XML_STRCMP(cur->name, max_audio_streams_key)) { ret->max_audio_streams = atoi(tmp_string); } else if(!BG_XML_STRCMP(cur->name, max_video_streams_key)) { ret->max_video_streams = atoi(tmp_string); } else if(!BG_XML_STRCMP(cur->name, max_subtitle_text_streams_key)) { ret->max_subtitle_text_streams = atoi(tmp_string); } else if(!BG_XML_STRCMP(cur->name, max_subtitle_overlay_streams_key)) { ret->max_subtitle_overlay_streams = atoi(tmp_string); } xmlFree(tmp_string); cur = cur->next; } return ret; } static const char * get_flag_name(uint32_t flag) { int index = 0; while(flag_names[index].name) { if(flag_names[index].flag == flag) break; else index++; } return flag_names[index].name; } static void save_devices(xmlNodePtr parent, const bg_device_info_t * info) { int i; xmlNodePtr xml_device, xml_item; i = 0; while(info[i].device) { xmlAddChild(parent, BG_XML_NEW_TEXT("\n")); xml_device = xmlNewTextChild(parent, NULL, (xmlChar*)device_info_key, NULL); xmlAddChild(xml_device, BG_XML_NEW_TEXT("\n")); xml_item = xmlNewTextChild(xml_device, NULL, (xmlChar*)device_key, NULL); xmlAddChild(xml_item, BG_XML_NEW_TEXT(info[i].device)); xmlAddChild(xml_device, BG_XML_NEW_TEXT("\n")); if(info[i].name) { xml_item = xmlNewTextChild(xml_device, NULL, (xmlChar*)name_key, NULL); xmlAddChild(xml_item, BG_XML_NEW_TEXT(info[i].name)); xmlAddChild(xml_device, BG_XML_NEW_TEXT("\n")); } i++; } } static void save_plugin(xmlNodePtr parent, const bg_plugin_info_t * info) { char buffer[1024]; int index; int i; int num_flags; const char * flag_name; uint32_t flag; xmlNodePtr xml_plugin; xmlNodePtr xml_item; // fprintf(stderr, "Save plugin: %s\n", info->name); xmlAddChild(parent, BG_XML_NEW_TEXT("\n")); xml_plugin = xmlNewTextChild(parent, NULL, (xmlChar*)plugin_key, NULL); xmlAddChild(xml_plugin, BG_XML_NEW_TEXT("\n")); xml_item = xmlNewTextChild(xml_plugin, NULL, (xmlChar*)name_key, NULL); xmlAddChild(xml_item, BG_XML_NEW_TEXT(info->name)); xmlAddChild(xml_plugin, BG_XML_NEW_TEXT("\n")); xml_item = xmlNewTextChild(xml_plugin, NULL, (xmlChar*)long_name_key, NULL); xmlAddChild(xml_item, BG_XML_NEW_TEXT(info->long_name)); xmlAddChild(xml_plugin, BG_XML_NEW_TEXT("\n")); xml_item = xmlNewTextChild(xml_plugin, NULL, (xmlChar*)description_key, NULL); xmlAddChild(xml_item, BG_XML_NEW_TEXT(info->description)); xmlAddChild(xml_plugin, BG_XML_NEW_TEXT("\n")); xml_item = xmlNewTextChild(xml_plugin, NULL, (xmlChar*)module_filename_key, NULL); xmlAddChild(xml_item, BG_XML_NEW_TEXT(info->module_filename)); xmlAddChild(xml_plugin, BG_XML_NEW_TEXT("\n")); if(info->extensions) { xml_item = xmlNewTextChild(xml_plugin, NULL, (xmlChar*)extensions_key, NULL); xmlAddChild(xml_item, BG_XML_NEW_TEXT(info->extensions)); xmlAddChild(xml_plugin, BG_XML_NEW_TEXT("\n")); } if(info->protocols) { xml_item = xmlNewTextChild(xml_plugin, NULL, (xmlChar*)protocols_key, NULL); xmlAddChild(xml_item, BG_XML_NEW_TEXT(info->protocols)); xmlAddChild(xml_plugin, BG_XML_NEW_TEXT("\n")); } if(info->mimetypes) { xml_item = xmlNewTextChild(xml_plugin, NULL, (xmlChar*)mimetypes_key, NULL); xmlAddChild(xml_item, BG_XML_NEW_TEXT(info->mimetypes)); xmlAddChild(xml_plugin, BG_XML_NEW_TEXT("\n")); } if(info->gettext_domain) { xml_item = xmlNewTextChild(xml_plugin, NULL, (xmlChar*)gettext_domain_key, NULL); xmlAddChild(xml_item, BG_XML_NEW_TEXT(info->gettext_domain)); xmlAddChild(xml_plugin, BG_XML_NEW_TEXT("\n")); } if(info->gettext_directory) { xml_item = xmlNewTextChild(xml_plugin, NULL, (xmlChar*)gettext_directory_key, NULL); xmlAddChild(xml_item, BG_XML_NEW_TEXT(info->gettext_directory)); xmlAddChild(xml_plugin, BG_XML_NEW_TEXT("\n")); } xml_item = xmlNewTextChild(xml_plugin, NULL, (xmlChar*)module_time_key, NULL); sprintf(buffer, "%ld", info->module_time); xmlAddChild(xml_item, BG_XML_NEW_TEXT(buffer)); xmlAddChild(xml_plugin, BG_XML_NEW_TEXT("\n")); xml_item = xmlNewTextChild(xml_plugin, NULL, (xmlChar*)priority_key, NULL); sprintf(buffer, "%d", info->priority); xmlAddChild(xml_item, BG_XML_NEW_TEXT(buffer)); xmlAddChild(xml_plugin, BG_XML_NEW_TEXT("\n")); if(info->parameters) { xml_item = xmlNewTextChild(xml_plugin, NULL, (xmlChar*)parameters_key, NULL); bg_parameters_2_xml(info->parameters, xml_item); xmlAddChild(xml_plugin, BG_XML_NEW_TEXT("\n")); } if(info->audio_parameters) { xml_item = xmlNewTextChild(xml_plugin, NULL, (xmlChar*)audio_parameters_key, NULL); bg_parameters_2_xml(info->audio_parameters, xml_item); xmlAddChild(xml_plugin, BG_XML_NEW_TEXT("\n")); } if(info->video_parameters) { xml_item = xmlNewTextChild(xml_plugin, NULL, (xmlChar*)video_parameters_key, NULL); bg_parameters_2_xml(info->video_parameters, xml_item); xmlAddChild(xml_plugin, BG_XML_NEW_TEXT("\n")); } if(info->subtitle_text_parameters) { xml_item = xmlNewTextChild(xml_plugin, NULL, (xmlChar*)subtitle_text_parameters_key, NULL); bg_parameters_2_xml(info->subtitle_text_parameters, xml_item); xmlAddChild(xml_plugin, BG_XML_NEW_TEXT("\n")); } if(info->subtitle_overlay_parameters) { xml_item = xmlNewTextChild(xml_plugin, NULL, (xmlChar*)subtitle_overlay_parameters_key, NULL); bg_parameters_2_xml(info->subtitle_overlay_parameters, xml_item); xmlAddChild(xml_plugin, BG_XML_NEW_TEXT("\n")); } if(info->type & (BG_PLUGIN_ENCODER_AUDIO| BG_PLUGIN_ENCODER_VIDEO| BG_PLUGIN_ENCODER | BG_PLUGIN_ENCODER_SUBTITLE_TEXT | BG_PLUGIN_ENCODER_SUBTITLE_OVERLAY)) { xml_item = xmlNewTextChild(xml_plugin, NULL, (xmlChar*)max_audio_streams_key, NULL); sprintf(buffer, "%d", info->max_audio_streams); xmlAddChild(xml_item, BG_XML_NEW_TEXT(buffer)); xmlAddChild(xml_plugin, BG_XML_NEW_TEXT("\n")); xml_item = xmlNewTextChild(xml_plugin, NULL, (xmlChar*)max_video_streams_key, NULL); sprintf(buffer, "%d", info->max_video_streams); xmlAddChild(xml_item, BG_XML_NEW_TEXT(buffer)); xmlAddChild(xml_plugin, BG_XML_NEW_TEXT("\n")); xml_item = xmlNewTextChild(xml_plugin, NULL, (xmlChar*)max_subtitle_text_streams_key, NULL); sprintf(buffer, "%d", info->max_subtitle_text_streams); xmlAddChild(xml_item, BG_XML_NEW_TEXT(buffer)); xmlAddChild(xml_plugin, BG_XML_NEW_TEXT("\n")); xml_item = xmlNewTextChild(xml_plugin, NULL, (xmlChar*)max_subtitle_overlay_streams_key, NULL); sprintf(buffer, "%d", info->max_subtitle_overlay_streams); xmlAddChild(xml_item, BG_XML_NEW_TEXT(buffer)); xmlAddChild(xml_plugin, BG_XML_NEW_TEXT("\n")); } index = 0; while(type_names[index].name) { if(info->type == type_names[index].type) { xml_item = xmlNewTextChild(xml_plugin, NULL, (xmlChar*)type_key, NULL); xmlAddChild(xml_item, BG_XML_NEW_TEXT(type_names[index].name)); xmlAddChild(xml_plugin, BG_XML_NEW_TEXT("\n")); break; } index++; } if(info->api) { index = 0; while(api_names[index].name) { if(info->api == api_names[index].api) { xml_item = xmlNewTextChild(xml_plugin, NULL, (xmlChar*)api_key, NULL); xmlAddChild(xml_item, BG_XML_NEW_TEXT(api_names[index].name)); xmlAddChild(xml_plugin, BG_XML_NEW_TEXT("\n")); break; } index++; } xml_item = xmlNewTextChild(xml_plugin, NULL, (xmlChar*)index_key, NULL); sprintf(buffer, "%d", info->index); xmlAddChild(xml_item, BG_XML_NEW_TEXT(buffer)); xmlAddChild(xml_plugin, BG_XML_NEW_TEXT("\n")); } /* Write flags */ if(info->flags) { num_flags = 0; for(i = 0; i < 32; i++) { flag = (1<flags & flag) num_flags++; } buffer[0] = '\0'; index = 0; for(i = 0; i < 32; i++) { flag = (1<flags & flag)) continue; flag_name = get_flag_name(flag); strcat(buffer, flag_name); if(index < num_flags-1) strcat(buffer, "|"); index++; } xml_item = xmlNewTextChild(xml_plugin, NULL, (xmlChar*)flags_key, NULL); xmlAddChild(xml_item, BG_XML_NEW_TEXT(buffer)); xmlAddChild(xml_plugin, BG_XML_NEW_TEXT("\n")); } if(info->devices && info->devices->device) save_devices(xml_plugin, info->devices); } bg_plugin_info_t * bg_plugin_registry_load(const char * filename) { bg_plugin_info_t * ret; bg_plugin_info_t * end; bg_plugin_info_t * new; xmlDocPtr xml_doc; xmlNodePtr node; ret = NULL; end = NULL; xml_doc = bg_xml_parse_file(filename); if(!xml_doc) return NULL; node = xml_doc->children; if(BG_XML_STRCMP(node->name, plugin_registry_key)) { xmlFreeDoc(xml_doc); return NULL; } node = node->children; while(node) { if(node->name && !BG_XML_STRCMP(node->name, plugin_key)) { new = load_plugin(xml_doc, node); if(!new->module_filename) bg_plugin_info_destroy(new); else if(!ret) { ret = new; end = ret; } else { end->next = new; end = end->next; } } node = node->next; } xmlFreeDoc(xml_doc); return ret; } void bg_plugin_registry_save(bg_plugin_info_t * info) { xmlDocPtr xml_doc; xmlNodePtr xml_registry; char * filename; filename = bg_search_file_write("", "plugins.xml"); if(!filename) { return; } xml_doc = xmlNewDoc((xmlChar*)"1.0"); xml_registry = xmlNewDocRawNode(xml_doc, NULL, (xmlChar*)plugin_registry_key, NULL); xmlDocSetRootElement(xml_doc, xml_registry); while(info) { if(info->module_filename) /* We save only external plugins */ save_plugin(xml_registry, info); info = info->next; } xmlAddChild(xml_registry, BG_XML_NEW_TEXT("\n")); xmlSaveFile(filename, xml_doc); xmlFreeDoc(xml_doc); free(filename); } gmerlin-1.2.0~dfsg/lib/recorder_audio.c0000644000175000017500000002327011764363410020002 0ustar alessioalessio/***************************************************************** * gmerlin - a general purpose multimedia framework and applications * * Copyright (c) 2001 - 2011 Members of the Gmerlin project * gmerlin-general@lists.sourceforge.net * http://gmerlin.sourceforge.net * * 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 of the License, 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 this program. If not, see . * *****************************************************************/ #include #include #include #include #include #include #include #define LOG_DOMAIN "recorder.audio" #include void bg_recorder_create_audio(bg_recorder_t * rec) { bg_recorder_audio_stream_t * as = &rec->as; as->output_cnv = gavl_audio_converter_create(); as->enc_cnv = gavl_audio_converter_create(); bg_gavl_audio_options_init(&as->opt); as->fc = bg_audio_filter_chain_create(&as->opt, rec->plugin_reg); as->th = bg_player_thread_create(rec->tc); as->pd = gavl_peak_detector_create(); pthread_mutex_init(&as->eof_mutex, NULL); } void bg_recorder_audio_set_eof(bg_recorder_audio_stream_t * s, int eof) { pthread_mutex_lock(&s->eof_mutex); s->eof = eof; pthread_mutex_unlock(&s->eof_mutex); } int bg_recorder_audio_get_eof(bg_recorder_audio_stream_t * s) { int ret; pthread_mutex_lock(&s->eof_mutex); ret = s->eof; pthread_mutex_unlock(&s->eof_mutex); return ret; } void bg_recorder_destroy_audio(bg_recorder_t * rec) { bg_recorder_audio_stream_t * as = &rec->as; gavl_audio_converter_destroy(as->output_cnv); gavl_audio_converter_destroy(as->enc_cnv); bg_audio_filter_chain_destroy(as->fc); bg_player_thread_destroy(as->th); gavl_peak_detector_destroy(as->pd); pthread_mutex_destroy(&as->eof_mutex); gavl_metadata_free(&as->m); } static const bg_parameter_info_t parameters[] = { { .name = "do_audio", .long_name = TRS("Record audio"), .type = BG_PARAMETER_CHECKBUTTON, .val_default = { .val_i = 1 }, }, { .name = "plugin", .long_name = TRS("Plugin"), .type = BG_PARAMETER_MULTI_MENU, .flags = BG_PARAMETER_PLUGIN, }, { .name = "language", .long_name = TRS("Language"), .type = BG_PARAMETER_STRINGLIST, .val_default = { .val_str = "eng" }, .multi_names = bg_language_codes, .multi_labels = bg_language_labels, }, { }, }; const bg_parameter_info_t * bg_recorder_get_audio_parameters(bg_recorder_t * rec) { bg_recorder_audio_stream_t * as = &rec->as; if(!as->parameters) { as->parameters = bg_parameter_info_copy_array(parameters); bg_plugin_registry_set_parameter_info(rec->plugin_reg, BG_PLUGIN_RECORDER_AUDIO, BG_PLUGIN_RECORDER, &as->parameters[1]); } return as->parameters; } void bg_recorder_set_audio_parameter(void * data, const char * name, const bg_parameter_value_t * val) { bg_recorder_t * rec = data; bg_recorder_audio_stream_t * as = &rec->as; if(!name) return; // if(name) // fprintf(stderr, "bg_recorder_set_audio_parameter %s\n", name); if(!strcmp(name, "do_audio")) { if(!!(as->flags & STREAM_ACTIVE) != val->val_i) bg_recorder_interrupt(rec); if(val->val_i) as->flags |= STREAM_ACTIVE; else as->flags &= ~STREAM_ACTIVE; } else if(!strcmp(name, "language")) gavl_metadata_set(&as->m, GAVL_META_LANGUAGE, val->val_str); else if(!strcmp(name, "plugin")) { const bg_plugin_info_t * info; if(as->input_handle && !strcmp(as->input_handle->info->name, val->val_str)) return; if(rec->flags & FLAG_RUNNING) bg_recorder_interrupt(rec); if(as->input_handle) bg_plugin_unref(as->input_handle); info = bg_plugin_find_by_name(rec->plugin_reg, val->val_str); as->input_handle = bg_plugin_load(rec->plugin_reg, info); as->input_plugin = (bg_recorder_plugin_t*)(as->input_handle->plugin); if(as->input_plugin->set_callbacks) as->input_plugin->set_callbacks(as->input_handle->priv, &rec->recorder_cb); } else if(as->input_handle && as->input_plugin->common.set_parameter) { as->input_plugin->common.set_parameter(as->input_handle->priv, name, val); } } const bg_parameter_info_t * bg_recorder_get_audio_filter_parameters(bg_recorder_t * rec) { bg_recorder_audio_stream_t * as = &rec->as; return bg_audio_filter_chain_get_parameters(as->fc); } void bg_recorder_set_audio_filter_parameter(void * data, const char * name, const bg_parameter_value_t * val) { int need_restart; bg_recorder_t * rec = data; bg_recorder_audio_stream_t * as = &rec->as; if(!name) { if(!(rec->flags & FLAG_RUNNING)) bg_recorder_resume(rec); return; } bg_recorder_interrupt(rec); bg_audio_filter_chain_lock(as->fc); bg_audio_filter_chain_set_parameter(as->fc, name, val); if(bg_audio_filter_chain_need_restart(as->fc)) need_restart = 1; else need_restart = 0; bg_audio_filter_chain_unlock(as->fc); } void * bg_recorder_audio_thread(void * data) { double peaks[2]; /* Doesn't work for > 2 channels!! */ gavl_time_t idle_time = GAVL_TIME_SCALE / 100; // 10 ms bg_recorder_t * rec = data; bg_recorder_audio_stream_t * as = &rec->as; bg_player_thread_wait_for_start(as->th); while(1) { if(!bg_player_thread_check(as->th)) break; if(bg_recorder_audio_get_eof(as)) { gavl_time_delay(&idle_time); continue; } if(!as->in_func(as->in_data, as->pipe_frame, as->in_stream, as->pipe_format.samples_per_frame)) { bg_log(BG_LOG_ERROR, LOG_DOMAIN, "Read failed (device unplugged?)"); bg_recorder_audio_set_eof(as, 1); continue; // Need to go to bg_player_thread_check to stop the thread cleanly } /* Peak detection */ gavl_peak_detector_update(as->pd, as->pipe_frame); gavl_peak_detector_get_peaks(as->pd, NULL, NULL, peaks); if(as->pipe_format.num_channels == 1) peaks[1] = peaks[0]; bg_recorder_msg_audiolevel(rec, peaks, as->pipe_frame->valid_samples); gavl_peak_detector_reset(as->pd); /* Encoding */ if(as->flags & STREAM_ENCODE_OPEN) { bg_recorder_update_time(rec, gavl_time_unscale(as->pipe_format.samplerate, as->pipe_frame->timestamp + as->pipe_frame->valid_samples)); if(as->do_convert_enc) { gavl_audio_convert(as->enc_cnv, as->pipe_frame, as->enc_frame); bg_encoder_write_audio_frame(rec->enc, as->enc_frame, as->enc_index); } else bg_encoder_write_audio_frame(rec->enc, as->pipe_frame, as->enc_index); } } return NULL; } int bg_recorder_audio_init(bg_recorder_t * rec) { bg_recorder_audio_stream_t * as = &rec->as; /* Open input */ if(!as->input_plugin->open(as->input_handle->priv, &as->input_format, NULL)) { return 0; } as->flags |= STREAM_INPUT_OPEN; as->in_func = as->input_plugin->read_audio; as->in_stream = 0; as->in_data = as->input_handle->priv; /* Set up filter chain */ bg_audio_filter_chain_connect_input(as->fc, as->in_func, as->in_data, as->in_stream); as->in_func = bg_audio_filter_chain_read; as->in_data = as->fc; as->in_stream = 0; bg_audio_filter_chain_init(as->fc, &as->input_format, &as->pipe_format); /* Set up peak detection */ gavl_peak_detector_set_format(as->pd, &as->pipe_format); /* Create frame(s) */ as->pipe_frame = gavl_audio_frame_create(&as->pipe_format); /* Set up output */ if(as->flags & STREAM_ENCODE) { as->enc_index = bg_encoder_add_audio_stream(rec->enc, &as->m, &as->pipe_format, 0); } return 1; } void bg_recorder_audio_cleanup(bg_recorder_t * rec) { bg_recorder_audio_stream_t * as = &rec->as; if(as->flags & STREAM_INPUT_OPEN) as->input_plugin->close(as->input_handle->priv); if(as->pipe_frame) { gavl_audio_frame_destroy(as->pipe_frame); as->pipe_frame = NULL; } if(as->enc_frame) { gavl_audio_frame_destroy(as->enc_frame); as->enc_frame = NULL; } as->flags &= ~(STREAM_INPUT_OPEN | STREAM_ENCODE_OPEN); } void bg_recorder_audio_finalize_encode(bg_recorder_t * rec) { bg_recorder_audio_stream_t * as = &rec->as; bg_encoder_get_audio_format(rec->enc, as->enc_index, &as->enc_format); as->do_convert_enc = gavl_audio_converter_init(as->enc_cnv, &as->pipe_format, &as->enc_format); if(as->do_convert_enc) as->enc_frame = gavl_audio_frame_create(&as->enc_format); as->flags |= STREAM_ENCODE_OPEN; } gmerlin-1.2.0~dfsg/lib/transcoder_track.c0000644000175000017500000017767611764363410020370 0ustar alessioalessio/***************************************************************** * gmerlin - a general purpose multimedia framework and applications * * Copyright (c) 2001 - 2011 Members of the Gmerlin project * gmerlin-general@lists.sourceforge.net * http://gmerlin.sourceforge.net * * 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 of the License, 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 this program. If not, see . * *****************************************************************/ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #define LOG_DOMAIN "transcoder_track" #include static void create_sections(bg_transcoder_track_t * t, bg_cfg_section_t * track_defaults_section, bg_cfg_section_t * input_section, bg_cfg_section_t * encoder_section, bg_track_info_t * track_info) { int i, in_index; const char * tag; bg_cfg_section_t * general_section; bg_cfg_section_t * filter_section; bg_cfg_section_t * textrenderer_section; t->input_section = bg_cfg_section_copy(input_section); general_section = bg_cfg_section_find_subsection(track_defaults_section, "general"); t->general_section = bg_cfg_section_copy(general_section); /* The parameters which were initially hidden are not present in the general section. Therefore, we will create the missing items now */ i = 0; while(t->general_parameters[i].name) { bg_cfg_section_set_parameter(t->general_section, &t->general_parameters[i], &t->general_parameters[i].val_default); i++; } /* Stop here for redirectors */ if(t->url) return; t->metadata_section = bg_cfg_section_create_from_parameters("Metadata", t->metadata_parameters); if(t->num_audio_streams) { general_section = bg_cfg_section_find_subsection(track_defaults_section, "audio"); filter_section = bg_cfg_section_find_subsection(track_defaults_section, "audiofilters"); for(i = 0; i < t->num_audio_streams; i++) { t->audio_streams[i].general_section = bg_cfg_section_copy(general_section); t->audio_streams[i].filter_section = bg_cfg_section_copy(filter_section); tag = gavl_metadata_get(&track_info->audio_streams[i].m, GAVL_META_LANGUAGE); if(tag) bg_cfg_section_set_parameter_string(t->audio_streams[i].general_section, "in_language", tag); } } if(t->num_video_streams) { general_section = bg_cfg_section_find_subsection(track_defaults_section, "video"); filter_section = bg_cfg_section_find_subsection(track_defaults_section, "videofilters"); for(i = 0; i < t->num_video_streams; i++) { t->video_streams[i].general_section = bg_cfg_section_copy(general_section); t->video_streams[i].filter_section = bg_cfg_section_copy(filter_section); } } if(t->num_subtitle_text_streams) { general_section = bg_cfg_section_find_subsection(track_defaults_section, "subtitle_text"); textrenderer_section = bg_cfg_section_find_subsection(track_defaults_section, "textrenderer"); for(i = 0; i < t->num_subtitle_text_streams; i++) { t->subtitle_text_streams[i].general_section = bg_cfg_section_copy(general_section); t->subtitle_text_streams[i].textrenderer_section = bg_cfg_section_copy(textrenderer_section); in_index = t->subtitle_text_streams[i].in_index; tag = gavl_metadata_get(&track_info->subtitle_streams[i].m, GAVL_META_LANGUAGE); if(tag) bg_cfg_section_set_parameter_string(t->subtitle_text_streams[i].general_section, "in_language", tag); } } if(t->num_subtitle_overlay_streams) { general_section = bg_cfg_section_find_subsection(track_defaults_section, "subtitle_overlay"); for(i = 0; i < t->num_subtitle_overlay_streams; i++) { t->subtitle_overlay_streams[i].general_section = bg_cfg_section_copy(general_section); in_index = t->subtitle_overlay_streams[i].in_index; tag = gavl_metadata_get(&track_info->subtitle_streams[in_index].m, GAVL_META_LANGUAGE); if(tag) bg_cfg_section_set_parameter_string(t->subtitle_overlay_streams[i].general_section, "in_language", tag); } } } static const bg_parameter_info_t parameters_general[] = { { .name = "name", .long_name = TRS("Name"), .type = BG_PARAMETER_STRING, .flags = BG_PARAMETER_HIDE_DIALOG, }, { .name = "location", .long_name = TRS("Location"), .type = BG_PARAMETER_STRING, .flags = BG_PARAMETER_HIDE_DIALOG, }, { .name = "plugin", .long_name = TRS("Plugin"), .type = BG_PARAMETER_STRING, .flags = BG_PARAMETER_HIDE_DIALOG, }, { .name = "prefer_edl", .long_name = TRS("Prefer EDL"), .type = BG_PARAMETER_CHECKBUTTON, .flags = BG_PARAMETER_HIDE_DIALOG, }, { .name = "track", .long_name = TRS("Track"), .type = BG_PARAMETER_INT, .flags = BG_PARAMETER_HIDE_DIALOG, }, { .name = "subdir", .long_name = TRS("Subdirectory"), .type = BG_PARAMETER_STRING, .help_string = TRS("Subdirectory, where this track will be written to"), }, { .name = "duration", .long_name = "Duration", .type = BG_PARAMETER_TIME, .flags = BG_PARAMETER_HIDE_DIALOG, }, { .name = "flags", .long_name = "Flags", .type = BG_PARAMETER_INT, .flags = BG_PARAMETER_HIDE_DIALOG, }, { .name = "audio_encoder", .long_name = "Audio encoder", .type = BG_PARAMETER_STRING, .flags = BG_PARAMETER_HIDE_DIALOG, }, { .name = "video_encoder", .long_name = "Video encoder", .type = BG_PARAMETER_STRING, .flags = BG_PARAMETER_HIDE_DIALOG, }, { .name = "subtitle_text_encoder", .long_name = "Subtitle text encoder", .type = BG_PARAMETER_STRING, .flags = BG_PARAMETER_HIDE_DIALOG, }, { .name = "subtitle_overlay_encoder", .long_name = "Subtitle overlay encoder", .type = BG_PARAMETER_STRING, .flags = BG_PARAMETER_HIDE_DIALOG, }, { .name = "pp_only", .long_name = TRS("Postprocess only"), .type = BG_PARAMETER_CHECKBUTTON, .help_string = TRS("Skip transcoding of this track and send the file directly to the postprocessor."), }, { .name = "set_start_time", .long_name = TRS("Set start time"), .type = BG_PARAMETER_CHECKBUTTON, .flags = BG_PARAMETER_HIDE_DIALOG, .val_default = { .val_i = 0 }, .help_string = TRS("Specify a start time below. This time will be slightly wrong if the input \ format doesn't support sample accurate seeking.") }, { .name = "start_time", .long_name = TRS("Start time"), .type = BG_PARAMETER_TIME, .flags = BG_PARAMETER_HIDE_DIALOG, .val_default = { .val_time = 0 } }, { .name = "set_end_time", .long_name = TRS("Set end time"), .type = BG_PARAMETER_CHECKBUTTON, .flags = BG_PARAMETER_HIDE_DIALOG, .val_default = { .val_i = 0 }, .help_string = TRS("Specify an end time below.") }, { .name = "end_time", .long_name = TRS("End time"), .type = BG_PARAMETER_TIME, .flags = BG_PARAMETER_HIDE_DIALOG, .val_default = { .val_time = 0 } }, { /* End of parameters */ } }; /* Subtitle text parameters */ static const bg_parameter_info_t general_parameters_subtitle_text[] = { { .name = "action", .long_name = TRS("Action"), .type = BG_PARAMETER_STRINGLIST, .val_default = { .val_str = "forget" }, .multi_names = (char const *[]){ "forget", "transcode", "transcode_overlay", "blend", NULL }, .multi_labels = (char const *[]){ TRS("Forget"), TRS("Transcode as text"), TRS("Transcode as overlay"), TRS("Blend onto video"), NULL }, .help_string = TRS("Select action for this subtitle stream.") }, { .name = "in_language", .long_name = TRS("Input Language"), .type = BG_PARAMETER_STRING, .flags = BG_PARAMETER_HIDE_DIALOG, }, { .name = "language", .long_name = TRS("Language"), .type = BG_PARAMETER_STRINGLIST, .val_default = { .val_str = "eng" }, .multi_names = bg_language_codes, .multi_labels = bg_language_labels, }, { .name = "force_language", .long_name = TRS("Force language"), .type = BG_PARAMETER_CHECKBUTTON, .val_default = { .val_i = 1 }, .help_string = TRS("Force the given language even if the input has the language set differently.") }, { .name = "time_offset", .long_name = TRS("Time offset"), .flags = BG_PARAMETER_SYNC, .type = BG_PARAMETER_FLOAT, .val_min = { .val_f = -600.0 }, .val_max = { .val_f = 600.0 }, .num_digits = 3, }, { .name = "video_stream", .long_name = TRS("Video stream"), .type = BG_PARAMETER_INT, .flags = BG_PARAMETER_HIDE_DIALOG, .val_default = { .val_i = 1 }, .val_min = { .val_i = 1 }, .help_string = TRS("Attach subtitle stream to this video stream. For blending, this video stream will\ get the subtitles. For encoding, take frame dimensions and framerate from this video stream as they are\ sometimes needed by subtitle encoders.") }, { /* End of parameters */ } }; /* Subtitle overlay parameters */ static const bg_parameter_info_t general_parameters_subtitle_overlay[] = { { .name = "action", .long_name = TRS("Action"), .type = BG_PARAMETER_STRINGLIST, .multi_names = (char const *[]){ "forget", "transcode", "blend", NULL }, .multi_labels = (char const *[]){ TRS("Forget"), TRS("Transcode"), TRS("Blend onto video"), NULL }, .val_default = { .val_str = "forget" }, }, { .name = "in_language", .long_name = TRS("Input Language"), .type = BG_PARAMETER_STRING, .flags = BG_PARAMETER_HIDE_DIALOG, }, { .name = "language", .long_name = TRS("Language"), .type = BG_PARAMETER_STRINGLIST, .val_default = { .val_str = "eng" }, .multi_names = bg_language_codes, .multi_labels = bg_language_labels, }, { .name = "force_language", .long_name = TRS("Force language"), .type = BG_PARAMETER_CHECKBUTTON, .val_default = { .val_i = 1 }, .help_string = TRS("Force the given language even if the input has the language set differently.") }, { .name = "blend_stream", .long_name = TRS("Video stream to blend onto"), .type = BG_PARAMETER_INT, .flags = BG_PARAMETER_HIDE_DIALOG, .val_default = { .val_i = 1 }, .val_min = { .val_i = 1 }, }, { /* End of parameters */ } }; /* Create subtitle parameters */ static void create_subtitle_parameters(bg_transcoder_track_t * track) { int i; bg_parameter_info_t * info; /* Create subtitle parameters. These depend on the number of video streams */ for(i = 0; i < track->num_subtitle_text_streams; i++) { /* Forget, Dump, Blend #1, Blend #2 ... */ track->subtitle_text_streams[i].general_parameters = bg_parameter_info_copy_array(general_parameters_subtitle_text); info = track->subtitle_text_streams[i].general_parameters; if(track->num_video_streams > 1) { info[1].val_max.val_i = track->num_video_streams; info[1].flags &= ~BG_PARAMETER_HIDE_DIALOG; } } for(i = 0; i < track->num_subtitle_overlay_streams; i++) { /* Forget, Blend #1, Blend #2 ... */ track->subtitle_overlay_streams[i].general_parameters = bg_parameter_info_copy_array(general_parameters_subtitle_overlay); info = track->subtitle_overlay_streams[i].general_parameters; if(track->num_video_streams > 1) { info[1].val_max.val_i = track->num_video_streams; info[1].flags &= ~BG_PARAMETER_HIDE_DIALOG; } } } static void create_filter_parameters(bg_transcoder_track_t * track, bg_plugin_registry_t * plugin_reg) { int i; bg_audio_filter_chain_t * afc; bg_video_filter_chain_t * vfc; bg_gavl_audio_options_t ao; bg_gavl_video_options_t vo; memset(&ao, 0, sizeof(ao)); memset(&vo, 0, sizeof(vo)); bg_gavl_audio_options_init(&ao); bg_gavl_video_options_init(&vo); if(track->num_audio_streams > 0) { afc = bg_audio_filter_chain_create(&ao, plugin_reg); for(i = 0; i < track->num_audio_streams; i++) { track->audio_streams[i].filter_parameters = bg_parameter_info_copy_array(bg_audio_filter_chain_get_parameters(afc)); } bg_audio_filter_chain_destroy(afc); } if(track->num_video_streams > 0) { vfc = bg_video_filter_chain_create(&vo, plugin_reg); for(i = 0; i < track->num_video_streams; i++) { track->video_streams[i].filter_parameters = bg_parameter_info_copy_array(bg_video_filter_chain_get_parameters(vfc)); } bg_video_filter_chain_destroy(vfc); } bg_gavl_audio_options_free(&ao); bg_gavl_video_options_free(&vo); } /* Create parameters if the config sections are already there */ void bg_transcoder_track_create_parameters(bg_transcoder_track_t * track, bg_plugin_registry_t * plugin_reg) { gavl_time_t duration = GAVL_TIME_UNDEFINED; int i; int flags = 0; if(!track->general_parameters) { track->general_parameters = bg_parameter_info_copy_array(parameters_general); bg_cfg_section_get_parameter_time(track->general_section, "duration", &duration); bg_cfg_section_get_parameter_int(track->general_section, "flags", &flags); if(duration != GAVL_TIME_UNDEFINED) { i = 0; while(track->general_parameters[i].name) { if(!strcmp(track->general_parameters[i].name, "start_time") || !strcmp(track->general_parameters[i].name, "end_time")) track->general_parameters[i].val_max.val_time = duration; i++; } if(flags & BG_TRACK_SEEKABLE) { i = 0; while(track->general_parameters[i].name) { if(!strcmp(track->general_parameters[i].name, "start_time") || !strcmp(track->general_parameters[i].name, "set_start_time")) track->general_parameters[i].flags &= ~BG_PARAMETER_HIDE_DIALOG; i++; } } } i = 0; while(track->general_parameters[i].name) { if(!strcmp(track->general_parameters[i].name, "name") || !strcmp(track->general_parameters[i].name, "set_end_time") || !strcmp(track->general_parameters[i].name, "end_time")) track->general_parameters[i].flags &= ~BG_PARAMETER_HIDE_DIALOG; i++; } } if(!track->metadata_parameters) track->metadata_parameters = bg_metadata_get_parameters(NULL); create_subtitle_parameters(track); create_filter_parameters(track, plugin_reg); } static char * create_stream_label(const gavl_metadata_t * m) { const char * info; const char * language; info = gavl_metadata_get(m, GAVL_META_LABEL); language = gavl_metadata_get(m, GAVL_META_LANGUAGE); if(language && info) return bg_sprintf("%s [%s]", info, bg_get_language_name(language)); else if(language) return bg_strdup(NULL, bg_get_language_name(language)); else if(info) return bg_strdup(NULL, info); else return NULL; } static void set_track(bg_transcoder_track_t * track, bg_track_info_t * track_info, bg_plugin_handle_t * input_plugin, const bg_plugin_info_t * input_info, const char * location, int track_index, int total_tracks, bg_plugin_registry_t * plugin_reg) { int i; int subtitle_text_index, subtitle_overlay_index; const bg_input_plugin_t * input; input = (bg_input_plugin_t *)input_plugin->plugin; /* General parameters */ track->general_parameters = bg_parameter_info_copy_array(parameters_general); i = 0; while(track->general_parameters[i].name) { if(!strcmp(track->general_parameters[i].name, "name")) { if(track_info->name) track->general_parameters[i].val_default.val_str = bg_strdup(NULL, track_info->name); else track->general_parameters[i].val_default.val_str = bg_get_track_name_default(location, track_index, total_tracks); track->general_parameters[i].flags &= ~BG_PARAMETER_HIDE_DIALOG; } else if(!strcmp(track->general_parameters[i].name, "duration")) track->general_parameters[i].val_default.val_time = track_info->duration; else if(!strcmp(track->general_parameters[i].name, "subdir")) { if(input->get_disc_name) track->general_parameters[i].val_default.val_str = bg_strdup(track->general_parameters[i].val_default.val_str, input->get_disc_name(input_plugin->priv)); } else if(!strcmp(track->general_parameters[i].name, "flags")) track->general_parameters[i].val_default.val_i = track_info->flags; else if(!strcmp(track->general_parameters[i].name, "location")) track->general_parameters[i].val_default.val_str = bg_strdup(NULL, location); else if(!strcmp(track->general_parameters[i].name, "plugin")) track->general_parameters[i].val_default.val_str = bg_strdup(NULL, input_info->name); else if(!strcmp(track->general_parameters[i].name, "prefer_edl")) { if(input_plugin->edl) track->general_parameters[i].val_default.val_i = 1; else track->general_parameters[i].val_default.val_i = 0; } else if(!strcmp(track->general_parameters[i].name, "track")) track->general_parameters[i].val_default.val_i = track_index; else if(!strcmp(track->general_parameters[i].name, "set_start_time")) { if(track_info->flags & BG_TRACK_SEEKABLE) track->general_parameters[i].flags &= ~BG_PARAMETER_HIDE_DIALOG; } else if(!strcmp(track->general_parameters[i].name, "start_time")) { if(track_info->flags & BG_TRACK_SEEKABLE) { track->general_parameters[i].flags &= ~BG_PARAMETER_HIDE_DIALOG; track->general_parameters[i].val_max.val_time = track_info->duration; } } else if(!strcmp(track->general_parameters[i].name, "end_time")) { if(track_info->duration != GAVL_TIME_UNDEFINED) { track->general_parameters[i].val_max.val_time = track_info->duration; track->general_parameters[i].val_default.val_time = track_info->duration; } track->general_parameters[i].flags &= ~BG_PARAMETER_HIDE_DIALOG; } else if(!strcmp(track->general_parameters[i].name, "set_end_time")) { track->general_parameters[i].flags &= ~BG_PARAMETER_HIDE_DIALOG; } i++; } /* Stop here for redirectors */ if(track->url) return; /* Metadata */ track->metadata_parameters = bg_metadata_get_parameters(&track_info->metadata); /* Chapter list */ if(track_info->chapter_list) track->chapter_list = bg_chapter_list_copy(track_info->chapter_list); /* Audio streams */ if(track_info->num_audio_streams) { track->num_audio_streams = track_info->num_audio_streams; track->audio_streams = calloc(track_info->num_audio_streams, sizeof(*(track->audio_streams))); for(i = 0; i < track_info->num_audio_streams; i++) { track->audio_streams[i].label = create_stream_label(&track_info->audio_streams[i].m); } } /* Video streams */ if(track_info->num_video_streams) { track->num_video_streams = track_info->num_video_streams; track->video_streams = calloc(track_info->num_video_streams, sizeof(*(track->video_streams))); for(i = 0; i < track_info->num_video_streams; i++) { track->video_streams[i].label = create_stream_label(&track_info->video_streams[i].m); } } /* Subtitle streams */ if(track_info->num_subtitle_streams) { for(i = 0; i < track_info->num_subtitle_streams; i++) { if(track_info->subtitle_streams[i].is_text) track->num_subtitle_text_streams++; else track->num_subtitle_overlay_streams++; } if(track->num_subtitle_text_streams) track->subtitle_text_streams = calloc(track->num_subtitle_text_streams, sizeof(*(track->subtitle_text_streams))); if(track->num_subtitle_overlay_streams) track->subtitle_overlay_streams = calloc(track->num_subtitle_overlay_streams, sizeof(*(track->subtitle_overlay_streams))); subtitle_text_index = 0; subtitle_overlay_index = 0; for(i = 0; i < track_info->num_subtitle_streams; i++) { if(track_info->subtitle_streams[i].is_text) { track->subtitle_text_streams[subtitle_text_index].label = create_stream_label(&track_info->subtitle_streams[i].m); track->subtitle_text_streams[subtitle_text_index].in_index = i; subtitle_text_index++; } else { track->subtitle_overlay_streams[subtitle_overlay_index].label = create_stream_label(&track_info->subtitle_streams[i].m); track->subtitle_overlay_streams[subtitle_overlay_index].in_index = i; subtitle_overlay_index++; } } } create_subtitle_parameters(track); create_filter_parameters(track, plugin_reg); } static void enable_streams(bg_input_plugin_t * plugin, void * priv, int track, int num_audio_streams, int num_video_streams, int num_subtitle_streams) { int i; if(plugin->set_track) plugin->set_track(priv, track); if(plugin->set_audio_stream) { for(i = 0; i < num_audio_streams; i++) { plugin->set_audio_stream(priv, i, BG_STREAM_ACTION_DECODE); } } if(plugin->set_video_stream) { for(i = 0; i < num_video_streams; i++) { plugin->set_video_stream(priv, i, BG_STREAM_ACTION_DECODE); } } if(plugin->set_subtitle_stream) { for(i = 0; i < num_subtitle_streams; i++) { plugin->set_subtitle_stream(priv, i, BG_STREAM_ACTION_DECODE); } } if(plugin->start) plugin->start(priv); } static void disable_streams(bg_input_plugin_t * plugin, void * priv) { if(plugin->stop) plugin->stop(priv); } bg_transcoder_track_t * bg_transcoder_track_create(const char * url, const bg_plugin_info_t * input_info, int prefer_edl, int track, bg_plugin_registry_t * plugin_reg, bg_cfg_section_t * track_defaults_section, bg_cfg_section_t * encoder_section, char * name) { int i; bg_transcoder_track_t * ret = NULL; bg_transcoder_track_t * new_track = NULL; bg_transcoder_track_t * end_track = NULL; bg_input_plugin_t * input; bg_track_info_t * track_info; bg_plugin_handle_t * plugin_handle = NULL; int num_tracks; int streams_enabled = 0; bg_cfg_section_t * input_section; /* Load the plugin */ if(!input_info) { if(!bg_input_plugin_load(plugin_reg, url, input_info, &plugin_handle, NULL, 0)) { bg_log(BG_LOG_ERROR, LOG_DOMAIN, "Loading %s failed", url); return NULL; } input_info = bg_plugin_find_by_name(plugin_reg, plugin_handle->info->name); } if(!plugin_handle || prefer_edl) { if(!bg_input_plugin_load(plugin_reg, url, input_info, &plugin_handle, NULL, prefer_edl)) { bg_log(BG_LOG_ERROR, LOG_DOMAIN, "Loading %s failed", url); return NULL; } } if(plugin_handle->edl) bg_cfg_section_set_parameter_int(track_defaults_section, "prefer_edl", 1); else bg_cfg_section_set_parameter_int(track_defaults_section, "prefer_edl", 0); input = (bg_input_plugin_t*)plugin_handle->plugin; input_section = bg_plugin_registry_get_section(plugin_reg, input_info->name); /* Decide what to load */ num_tracks = input->get_num_tracks ? input->get_num_tracks(plugin_handle->priv) : 1; if(track >= 0) { /* Load single track */ track_info = input->get_track_info(plugin_handle->priv, track); if(name) track_info->name = bg_strdup(track_info->name, name); new_track = calloc(1, sizeof(*new_track)); ret = new_track; if(track_info->url) { new_track->url = bg_strdup(new_track->url, track_info->url); } else { enable_streams(input, plugin_handle->priv, track, track_info->num_audio_streams, track_info->num_video_streams, track_info->num_subtitle_streams); streams_enabled = 1; } set_track(new_track, track_info, plugin_handle, input_info, url, track, num_tracks, plugin_reg); create_sections(new_track, track_defaults_section, input_section, encoder_section, track_info); bg_transcoder_track_set_encoders(new_track, plugin_reg, encoder_section); if(streams_enabled) disable_streams(input, plugin_handle->priv); } else { /* Load all tracks */ for(i = 0; i < num_tracks; i++) { track_info = input->get_track_info(plugin_handle->priv, i); if(name) track_info->name = bg_strdup(track_info->name, name); new_track = calloc(1, sizeof(*new_track)); if(ret) { end_track->next = new_track; end_track = end_track->next; } else { ret = new_track; end_track = new_track; } if(track_info->url) { new_track->url = bg_strdup(new_track->url, track_info->url); } else { enable_streams(input, plugin_handle->priv, i, track_info->num_audio_streams, track_info->num_video_streams, track_info->num_subtitle_streams); streams_enabled = 1; } set_track(new_track, track_info, plugin_handle, input_info, url, i, num_tracks, plugin_reg); create_sections(new_track, track_defaults_section, input_section, encoder_section, track_info); bg_transcoder_track_set_encoders(new_track, plugin_reg, encoder_section); if(streams_enabled) { disable_streams(input, plugin_handle->priv); streams_enabled = 0; } } } bg_plugin_unref(plugin_handle); return ret; } static bg_transcoder_track_t * remove_redirectors(bg_transcoder_track_t * entries, bg_plugin_registry_t * plugin_reg, bg_cfg_section_t * track_defaults_section, bg_cfg_section_t * encoder_section) { bg_transcoder_track_t * before, * e; bg_transcoder_track_t * new_entry, * end_entry; int done = 0; const char * plugin_name = NULL; const bg_plugin_info_t * info; done = 1; e = entries; while(e) { if(e->url) { bg_cfg_section_get_parameter_string(e->general_section, "plugin", &plugin_name); if(plugin_name) info = bg_plugin_find_by_name(plugin_reg, plugin_name); else info = NULL; /* Load "real" url */ new_entry = bg_transcoder_track_create(e->url, info, 0, -1, plugin_reg, track_defaults_section, encoder_section, NULL); if(new_entry) { /* Insert new entries into list */ if(e != entries) { before = entries; while(before->next != e) before = before->next; before->next = new_entry; } else { entries = new_entry; } end_entry = new_entry; while(end_entry->next) end_entry = end_entry->next; end_entry->next = e->next; bg_transcoder_track_destroy(e); e = new_entry; } else { /* Remove e from list */ if(e != entries) { before = entries; while(before->next != e) before = before->next; before->next = e->next; } else { entries = e->next; before = NULL; } bg_transcoder_track_destroy(e); e = (before) ? before->next : entries; } } else { /* Leave e as it is */ e = e->next; } } return entries; } bg_transcoder_track_t * bg_transcoder_track_create_from_urilist(const char * list, int len, bg_plugin_registry_t * plugin_reg, bg_cfg_section_t * track_defaults_section, bg_cfg_section_t * encoder_section) { int i; char ** uri_list; bg_transcoder_track_t * ret_last = NULL; bg_transcoder_track_t * ret = NULL; uri_list = bg_urilist_decode(list, len); if(!uri_list) return NULL; i = 0; while(uri_list[i]) { if(!ret) { ret = bg_transcoder_track_create(uri_list[i], NULL, 0, -1, plugin_reg, track_defaults_section, encoder_section, NULL); if(ret) { ret_last = ret; while(ret_last->next) ret_last = ret_last->next; } } else { ret_last->next = bg_transcoder_track_create(uri_list[i], NULL, 0, -1, plugin_reg, track_defaults_section, encoder_section, NULL); if(ret) { while(ret_last->next) ret_last = ret_last->next; } } i++; } bg_urilist_free(uri_list); ret = remove_redirectors(ret, plugin_reg, track_defaults_section, encoder_section); return ret; } bg_transcoder_track_t * bg_transcoder_track_create_from_albumentries(const char * xml_string, bg_plugin_registry_t * plugin_reg, bg_cfg_section_t * track_defaults_section, bg_cfg_section_t * encoder_section) { bg_album_entry_t * new_entries, *entry; bg_transcoder_track_t * ret_last =NULL; bg_transcoder_track_t * ret =NULL; const bg_plugin_info_t * plugin_info; int prefer_edl; new_entries = bg_album_entries_new_from_xml(xml_string); entry = new_entries; while(entry) { if(entry->plugin) plugin_info = bg_plugin_find_by_name(plugin_reg, entry->plugin); else plugin_info = NULL; if(entry->flags & BG_ALBUM_ENTRY_EDL) prefer_edl = 1; else prefer_edl = 0; if(!ret) { ret = bg_transcoder_track_create(entry->location, plugin_info, prefer_edl, entry->index, plugin_reg, track_defaults_section, encoder_section, entry->name); ret_last = ret; } else { ret_last->next = bg_transcoder_track_create(entry->location, plugin_info, prefer_edl, entry->index, plugin_reg, track_defaults_section, encoder_section, entry->name); ret_last = ret_last->next; } entry = entry->next; } bg_album_entries_destroy(new_entries); ret = remove_redirectors(ret, plugin_reg, track_defaults_section, encoder_section); return ret; } static void free_encoders(bg_transcoder_track_t * track) { int i; /* Free all encoder related data */ if(track->audio_encoder_section) { bg_cfg_section_destroy(track->audio_encoder_section); track->audio_encoder_section = NULL; } if(track->video_encoder_section) { bg_cfg_section_destroy(track->video_encoder_section); track->video_encoder_section = NULL; } if(track->subtitle_text_encoder_section) { bg_cfg_section_destroy(track->subtitle_text_encoder_section); track->subtitle_text_encoder_section = NULL; } if(track->subtitle_overlay_encoder_section) { bg_cfg_section_destroy(track->subtitle_overlay_encoder_section); track->subtitle_overlay_encoder_section = NULL; } for(i = 0; i < track->num_audio_streams; i++) { if(track->audio_streams[i].encoder_section) { bg_cfg_section_destroy(track->audio_streams[i].encoder_section); track->audio_streams[i].encoder_section = NULL; } } for(i = 0; i < track->num_video_streams; i++) { if(track->video_streams[i].encoder_section) { bg_cfg_section_destroy(track->video_streams[i].encoder_section); track->video_streams[i].encoder_section = NULL; } } for(i = 0; i < track->num_subtitle_text_streams; i++) { if(track->subtitle_text_streams[i].encoder_section_text) { bg_cfg_section_destroy(track->subtitle_text_streams[i].encoder_section_text); track->subtitle_text_streams[i].encoder_section_text = NULL; } if(track->subtitle_text_streams[i].encoder_section_overlay) { bg_cfg_section_destroy(track->subtitle_text_streams[i].encoder_section_overlay); track->subtitle_text_streams[i].encoder_section_overlay = NULL; } } for(i = 0; i < track->num_subtitle_overlay_streams; i++) { if(track->subtitle_overlay_streams[i].encoder_section) { bg_cfg_section_destroy(track->subtitle_overlay_streams[i].encoder_section); track->subtitle_overlay_streams[i].encoder_section = NULL; } } } void bg_transcoder_track_destroy(bg_transcoder_track_t * t) { int i; free_encoders(t); /* Shredder everything */ for(i = 0; i < t->num_audio_streams; i++) { if(t->audio_streams[i].general_section) bg_cfg_section_destroy(t->audio_streams[i].general_section); if(t->audio_streams[i].encoder_section) bg_cfg_section_destroy(t->audio_streams[i].encoder_section); if(t->audio_streams[i].filter_section) bg_cfg_section_destroy(t->audio_streams[i].filter_section); if(t->audio_streams[i].label) free(t->audio_streams[i].label); bg_parameter_info_destroy_array(t->audio_streams[i].filter_parameters); } for(i = 0; i < t->num_video_streams; i++) { if(t->video_streams[i].general_section) bg_cfg_section_destroy(t->video_streams[i].general_section); if(t->video_streams[i].encoder_section) bg_cfg_section_destroy(t->video_streams[i].encoder_section); if(t->video_streams[i].filter_section) bg_cfg_section_destroy(t->video_streams[i].filter_section); if(t->video_streams[i].label) free(t->video_streams[i].label); bg_parameter_info_destroy_array(t->video_streams[i].filter_parameters); } for(i = 0; i < t->num_subtitle_text_streams; i++) { if(t->subtitle_text_streams[i].general_section) bg_cfg_section_destroy(t->subtitle_text_streams[i].general_section); if(t->subtitle_text_streams[i].encoder_section_text) bg_cfg_section_destroy(t->subtitle_text_streams[i].encoder_section_text); if(t->subtitle_text_streams[i].encoder_section_overlay) bg_cfg_section_destroy(t->subtitle_text_streams[i].encoder_section_overlay); if(t->subtitle_text_streams[i].textrenderer_section) bg_cfg_section_destroy(t->subtitle_text_streams[i].textrenderer_section); if(t->subtitle_text_streams[i].general_parameters) bg_parameter_info_destroy_array(t->subtitle_text_streams[i].general_parameters); if(t->subtitle_text_streams[i].label) free(t->subtitle_text_streams[i].label); } for(i = 0; i < t->num_subtitle_overlay_streams; i++) { if(t->subtitle_overlay_streams[i].general_section) bg_cfg_section_destroy(t->subtitle_overlay_streams[i].general_section); if(t->subtitle_overlay_streams[i].encoder_section) bg_cfg_section_destroy(t->subtitle_overlay_streams[i].encoder_section); if(t->subtitle_overlay_streams[i].general_parameters) bg_parameter_info_destroy_array(t->subtitle_overlay_streams[i].general_parameters); if(t->subtitle_overlay_streams[i].label) free(t->subtitle_overlay_streams[i].label); } if(t->audio_streams) free(t->audio_streams); if(t->video_streams) free(t->video_streams); if(t->general_section) bg_cfg_section_destroy(t->general_section); if(t->input_section) bg_cfg_section_destroy(t->input_section); if(t->metadata_section) bg_cfg_section_destroy(t->metadata_section); if(t->audio_encoder_section) bg_cfg_section_destroy(t->audio_encoder_section); if(t->video_encoder_section) bg_cfg_section_destroy(t->video_encoder_section); if(t->subtitle_text_encoder_section) bg_cfg_section_destroy(t->subtitle_text_encoder_section); if(t->subtitle_overlay_encoder_section) bg_cfg_section_destroy(t->subtitle_overlay_encoder_section); if(t->general_parameters) bg_parameter_info_destroy_array(t->general_parameters); if(t->metadata_parameters) bg_parameter_info_destroy_array(t->metadata_parameters); if(t->chapter_list) bg_chapter_list_destroy(t->chapter_list); if(t->url) free(t->url); free(t); } static const bg_parameter_info_t general_parameters_video[] = { { .name = "general", .long_name = TRS("General"), .type = BG_PARAMETER_SECTION }, { .name = "action", .long_name = TRS("Action"), .type = BG_PARAMETER_STRINGLIST, .multi_names = (char const *[]){ "transcode", "copy", "forget", NULL }, .multi_labels = (char const *[]){ TRS("Transcode"), TRS("Copy (if possible)"), TRS("Forget"), NULL }, .val_default = { .val_str = "transcode" }, .help_string = TRS("Choose the desired action for the stream. If copying is not possible, the stream will be transcoded"), }, { .name = "twopass", .long_name = TRS("Enable 2-pass encoding"), .type = BG_PARAMETER_CHECKBUTTON, .help_string = TRS("Encode this stream in 2 passes, i.e. analyze it first and do the final\ transcoding in the second pass. This enables higher quality within the given bitrate constraints but roughly doubles the video encoding time."), }, BG_GAVL_PARAM_CONVERSION_QUALITY, BG_GAVL_PARAM_FRAMERATE, BG_GAVL_PARAM_ALPHA, BG_GAVL_PARAM_RESAMPLE_CHROMA, BG_GAVL_PARAM_THREADS, { /* End of parameters */ } }; static const bg_parameter_info_t general_parameters_audio[] = { { .name = "action", .long_name = TRS("Action"), .type = BG_PARAMETER_STRINGLIST, .multi_names = (char const *[]){ "transcode", "copy", "forget", NULL }, .multi_labels = (char const *[]){ TRS("Transcode"), TRS("Copy (if possible)"), TRS("Forget"), NULL }, .val_default = { .val_str = "transcode" }, .help_string = TRS("Choose the desired action for the stream. If copying is not possible, the stream will be transcoded"), }, { .name = "in_language", .long_name = TRS("Input Language"), .type = BG_PARAMETER_STRING, .flags = BG_PARAMETER_HIDE_DIALOG, }, { .name = "language", .long_name = TRS("Language"), .type = BG_PARAMETER_STRINGLIST, .val_default = { .val_str = "eng" }, .multi_names = bg_language_codes, .multi_labels = bg_language_labels, }, { .name = "force_language", .long_name = TRS("Force language"), .type = BG_PARAMETER_CHECKBUTTON, .val_default = { .val_i = 1 }, .help_string = TRS("Force the given language even if the input has the language set differently.") }, { .name = "normalize", .long_name = TRS("Normalize audio"), .type = BG_PARAMETER_CHECKBUTTON, .help_string = TRS("This will enable 2 pass transcoding. In the first pass, the peak volume\ is detected. In the second pass, the stream is transcoded with normalized volume.") }, BG_GAVL_PARAM_FORCE_SAMPLEFORMAT, BG_GAVL_PARAM_CONVERSION_QUALITY, BG_GAVL_PARAM_AUDIO_DITHER_MODE, BG_GAVL_PARAM_SAMPLERATE, BG_GAVL_PARAM_RESAMPLE_MODE, BG_GAVL_PARAM_CHANNEL_SETUP, { /* End of parameters */ } }; /* Audio stream parameters */ const bg_parameter_info_t * bg_transcoder_track_audio_get_general_parameters() { return general_parameters_audio; } /* Video stream parameters */ const bg_parameter_info_t * bg_transcoder_track_video_get_general_parameters() { return general_parameters_video; } const bg_parameter_info_t * bg_transcoder_track_subtitle_text_get_general_parameters() { return general_parameters_subtitle_text; } const bg_parameter_info_t * bg_transcoder_track_subtitle_overlay_get_general_parameters() { return general_parameters_subtitle_overlay; } const bg_parameter_info_t * bg_transcoder_track_get_general_parameters(bg_transcoder_track_t * t) { return parameters_general; } char * bg_transcoder_track_get_name(bg_transcoder_track_t * t) { bg_parameter_value_t val; bg_parameter_info_t info; memset(&val, 0, sizeof(val)); memset(&info, 0, sizeof(info)); info.name = "name"; bg_cfg_section_get_parameter(t->general_section, &info, &val); return val.val_str; } const char * bg_transcoder_track_get_audio_encoder(bg_transcoder_track_t * t) { const char * ret; bg_cfg_section_get_parameter_string(t->general_section, "audio_encoder", &ret); return ret; } const char * bg_transcoder_track_get_video_encoder(bg_transcoder_track_t * t) { const char * ret; bg_cfg_section_get_parameter_string(t->general_section, "video_encoder", &ret); return ret; } const char * bg_transcoder_track_get_subtitle_text_encoder(bg_transcoder_track_t * t) { const char * ret; bg_cfg_section_get_parameter_string(t->general_section, "subtitle_text_encoder", &ret); return ret; } const char * bg_transcoder_track_get_subtitle_overlay_encoder(bg_transcoder_track_t * t) { const char * ret; bg_cfg_section_get_parameter_string(t->general_section, "subtitle_overlay_encoder", &ret); return ret; } void bg_transcoder_track_get_duration(bg_transcoder_track_t * t, gavl_time_t * ret, gavl_time_t * ret_total) { gavl_time_t start_time = 0, end_time = 0, duration_total = 0; int set_start_time = 0, set_end_time = 0; bg_cfg_section_get_parameter_int(t->general_section, "set_start_time", &set_start_time); bg_cfg_section_get_parameter_int(t->general_section, "set_end_time", &set_end_time); bg_cfg_section_get_parameter_time(t->general_section, "duration", &duration_total); bg_cfg_section_get_parameter_time(t->general_section, "start_time", &start_time); bg_cfg_section_get_parameter_time(t->general_section, "end_time", &end_time); *ret_total = duration_total; if(duration_total == GAVL_TIME_UNDEFINED) { if(set_end_time) *ret = end_time; else *ret = duration_total; } else { if(set_start_time) { if(set_end_time) /* Start and end */ { *ret = end_time - start_time; if(*ret < 0) *ret = 0; } else /* Start only */ { *ret = duration_total - start_time; if(*ret < 0) *ret = 0; } } else { if(set_end_time) /* End only */ { *ret = end_time; } else { *ret = duration_total; } } } return; } #if 0 void bg_transcoder_track_set_encoders(bg_transcoder_track_t * track, bg_plugin_registry_t * plugin_reg, const bg_encoder_info_t * info) { free_encoders(track); /* Update the plugin entries in the general section */ bg_cfg_section_set_parameter_string(track->general_section, "audio_encoder", (info->audio_info) ? info->audio_info->name : info->video_info->name); bg_cfg_section_set_parameter_string(track->general_section, "video_encoder", info->video_info->name); bg_cfg_section_set_parameter_string(track->general_section, "subtitle_text_encoder", (info->subtitle_text_info) ? info->subtitle_text_info->name : info->video_info->name); bg_cfg_section_set_parameter_string(track->general_section, "subtitle_overlay_encoder", (info->subtitle_overlay_info) ? info->subtitle_overlay_info->name : info->video_info->name); bg_transcoder_track_create_encoder_sections(track, info); } #endif void bg_transcoder_track_global_to_reg(bg_transcoder_track_global_t * g, bg_plugin_registry_t * plugin_reg) { bg_cfg_section_t * plugin_section; if(g->pp_plugin) { bg_plugin_registry_set_default(plugin_reg, BG_PLUGIN_ENCODER_PP, BG_PLUGIN_PP, g->pp_plugin); bg_plugin_registry_set_encode_pp(plugin_reg, 1); plugin_section = bg_plugin_registry_get_section(plugin_reg, g->pp_plugin); bg_cfg_section_transfer(g->pp_section, plugin_section); } else { bg_plugin_registry_set_encode_pp(plugin_reg, 0); } } void bg_transcoder_track_global_from_reg(bg_transcoder_track_global_t * g, bg_plugin_registry_t * plugin_reg) { bg_cfg_section_t * plugin_section; const bg_plugin_info_t * plugin_info; bg_transcoder_track_global_free(g); if(bg_plugin_registry_get_encode_pp(plugin_reg)) { plugin_info = bg_plugin_registry_get_default(plugin_reg, BG_PLUGIN_ENCODER_PP, BG_PLUGIN_PP); g->pp_plugin = bg_strdup(NULL, plugin_info->name); plugin_section = bg_plugin_registry_get_section(plugin_reg, plugin_info->name); g->pp_section = bg_cfg_section_copy(plugin_section); } } void bg_transcoder_track_global_free(bg_transcoder_track_global_t * g) { if(g->pp_plugin) { free(g->pp_plugin); g->pp_plugin = NULL; } if(g->pp_section) { bg_cfg_section_destroy(g->pp_section); g->pp_section = NULL; } } // /* Functions, which operate on lists of transcoder tracks */ bg_transcoder_track_t * bg_transcoder_tracks_delete_selected(bg_transcoder_track_t * t) { bg_transcoder_track_t * track, *tmp_track; bg_transcoder_track_t * new_tracks = NULL; bg_transcoder_track_t * end_track = NULL; track = t; while(track) { if(track->selected) { /* Copy non selected tracks */ tmp_track = track->next; bg_transcoder_track_destroy(track); track = tmp_track; } else { /* Insert into new list */ if(!new_tracks) { new_tracks = track; end_track = track; } else { end_track->next = track; end_track = end_track->next; } track = track->next; end_track->next = NULL; } } return new_tracks; } bg_transcoder_track_t * bg_transcoder_tracks_append(bg_transcoder_track_t * t, bg_transcoder_track_t * tail) { bg_transcoder_track_t * end; if(!t) return tail; end = t; while(end->next) end = end->next; end->next = tail; return t; } bg_transcoder_track_t * bg_transcoder_tracks_prepend(bg_transcoder_track_t * t, bg_transcoder_track_t * head) { return bg_transcoder_tracks_append(head, t); } bg_transcoder_track_t * bg_transcoder_tracks_extract_selected(bg_transcoder_track_t ** t) { bg_transcoder_track_t * track; bg_transcoder_track_t * ret = NULL; bg_transcoder_track_t * ret_end = NULL; bg_transcoder_track_t * new_tracks = NULL; bg_transcoder_track_t * new_tracks_end = NULL; track = *t; while(track) { if(track->selected) { if(!ret_end) { ret = track; ret_end = ret; } else { ret_end->next = track; ret_end = ret_end->next; } } else { if(!new_tracks_end) { new_tracks = track; new_tracks_end = new_tracks; } else { new_tracks_end->next = track; new_tracks_end = new_tracks_end->next; } } track = track->next; } /* Zero terminate */ if(ret_end) ret_end->next = NULL; if(new_tracks_end) new_tracks_end->next = NULL; *t = new_tracks; return ret; } bg_transcoder_track_t * bg_transcoder_tracks_move_selected_up(bg_transcoder_track_t * t) { bg_transcoder_track_t * selected; selected = bg_transcoder_tracks_extract_selected(&t); if(selected) t = bg_transcoder_tracks_prepend(t, selected); return t; } bg_transcoder_track_t * bg_transcoder_tracks_move_selected_down(bg_transcoder_track_t * t) { bg_transcoder_track_t * selected; selected = bg_transcoder_tracks_extract_selected(&t); if(selected) t = bg_transcoder_tracks_append(t, selected); return t; } void bg_transcoder_track_get_encoders(bg_transcoder_track_t * t, bg_plugin_registry_t * plugin_reg, bg_cfg_section_t * encoder_section) { bg_cfg_section_t * dst; const char * video_name; const char * name; /* Video */ video_name = bg_transcoder_track_get_video_encoder(t); bg_cfg_section_set_parameter_string(encoder_section, "video_encoder", video_name); dst = bg_cfg_section_find_subsection(encoder_section, "video_encoder"); dst = bg_cfg_section_find_subsection(dst, video_name); if(t->video_encoder_section) bg_cfg_section_transfer(t->video_encoder_section, dst); if(t->video_streams && t->video_streams->encoder_section) { dst = bg_cfg_section_find_subsection(dst, "$video"); bg_cfg_section_transfer(t->video_streams->encoder_section, dst); } /* Audio */ name = bg_transcoder_track_get_audio_encoder(t); if(name && strcmp(name, video_name)) { bg_cfg_section_set_parameter_string(encoder_section, "audio_encoder", name); bg_cfg_section_set_parameter_int(encoder_section, "encode_audio_to_video", 0); dst = bg_cfg_section_find_subsection(encoder_section, "audio_encoder"); dst = bg_cfg_section_find_subsection(dst, name); if(t->audio_encoder_section) bg_cfg_section_transfer(t->audio_encoder_section, dst); if(t->audio_streams && t->audio_streams->encoder_section) { dst = bg_cfg_section_find_subsection(dst, "$audio"); bg_cfg_section_transfer(t->audio_streams->encoder_section, dst); } } else { bg_cfg_section_set_parameter_string(encoder_section, "audio_encoder", NULL); bg_cfg_section_set_parameter_int(encoder_section, "encode_audio_to_video", 1); } /* Text subtitles */ name = bg_transcoder_track_get_subtitle_text_encoder(t); if(name && strcmp(name, video_name)) { bg_cfg_section_set_parameter_int(encoder_section, "encode_subtitle_text_to_video", 0); bg_cfg_section_set_parameter_string(encoder_section, "subtitle_text_encoder", name); dst = bg_cfg_section_find_subsection(encoder_section, "subtitle_text_encoder"); dst = bg_cfg_section_find_subsection(dst, name); if(t->subtitle_text_encoder_section) bg_cfg_section_transfer(t->subtitle_text_encoder_section, dst); if(t->subtitle_text_streams && t->subtitle_text_streams->encoder_section_text) { dst = bg_cfg_section_find_subsection(dst, "$subtitle_text"); bg_cfg_section_transfer(t->subtitle_text_streams->encoder_section_text, dst); } } else { bg_cfg_section_set_parameter_int(encoder_section, "encode_subtitle_text_to_video", 1); bg_cfg_section_set_parameter_string(encoder_section, "subtitle_text_encoder", 0); } /* Overlay subtitles */ name = bg_transcoder_track_get_subtitle_overlay_encoder(t); if(name && strcmp(name, video_name)) { bg_cfg_section_set_parameter_int(encoder_section, "encode_subtitle_overlay_to_video", 0); bg_cfg_section_set_parameter_string(encoder_section, "subtitle_overlay_encoder", name); dst = bg_cfg_section_find_subsection(encoder_section, "subtitle_overlay_encoder"); dst = bg_cfg_section_find_subsection(dst, name); if(t->subtitle_overlay_encoder_section) bg_cfg_section_transfer(t->subtitle_overlay_encoder_section, dst); dst = bg_cfg_section_find_subsection(dst, "$subtitle_overlay"); if(t->subtitle_overlay_streams && t->subtitle_overlay_streams->encoder_section) bg_cfg_section_transfer(t->subtitle_overlay_streams->encoder_section, dst); else if(t->subtitle_text_streams && t->subtitle_text_streams->encoder_section_overlay) bg_cfg_section_transfer(t->subtitle_text_streams->encoder_section_overlay, dst); } else { bg_cfg_section_set_parameter_int(encoder_section, "encode_subtitle_overlay_to_video", 1); bg_cfg_section_set_parameter_string(encoder_section, "subtitle_overlay_encoder", NULL); } } static void delete_subsection(bg_cfg_section_t * s, const char * name) { if(bg_cfg_section_has_subsection(s, name)) bg_cfg_section_delete_subsection(s, bg_cfg_section_find_subsection(s, name)); } static void clean_section(bg_cfg_section_t * s) { delete_subsection(s, "$audio"); delete_subsection(s, "$video"); delete_subsection(s, "$subtitle_text"); delete_subsection(s, "$subtitle_overlay"); } #define DELETE_SECTION(s) if(s) { bg_cfg_section_destroy(s); s = NULL; } void bg_transcoder_track_set_encoders(bg_transcoder_track_t * t, bg_plugin_registry_t * plugin_reg, bg_cfg_section_t * encoder_section) { int i; bg_cfg_section_t * s; bg_cfg_section_t * s1; const char * name; static const uint32_t stream_flags = BG_STREAM_AUDIO | BG_STREAM_VIDEO | BG_STREAM_SUBTITLE_TEXT | BG_STREAM_SUBTITLE_OVERLAY; /* Delete config sections */ DELETE_SECTION(t->audio_encoder_section); DELETE_SECTION(t->video_encoder_section); DELETE_SECTION(t->subtitle_text_encoder_section); DELETE_SECTION(t->subtitle_overlay_encoder_section); for(i = 0; i < t->num_audio_streams; i++) DELETE_SECTION(t->audio_streams[i].encoder_section); for(i = 0; i < t->num_video_streams; i++) DELETE_SECTION(t->video_streams[i].encoder_section); for(i = 0; i < t->num_subtitle_text_streams; i++) { DELETE_SECTION(t->subtitle_text_streams[i].encoder_section_text); DELETE_SECTION(t->subtitle_text_streams[i].encoder_section_overlay); } for(i = 0; i < t->num_subtitle_overlay_streams; i++) DELETE_SECTION(t->subtitle_overlay_streams[i].encoder_section); /* Audio encoder */ name = bg_encoder_section_get_plugin(plugin_reg, encoder_section, BG_STREAM_AUDIO, stream_flags); bg_cfg_section_set_parameter_string(t->general_section, "audio_encoder", name); bg_encoder_section_get_plugin_config(plugin_reg, encoder_section, BG_STREAM_AUDIO, stream_flags, &s, NULL); if(s) { t->audio_encoder_section = bg_cfg_section_copy(s); clean_section(t->audio_encoder_section); } // else // fprintf(stderr, "Got no audio encoder section\n"); bg_encoder_section_get_stream_config(plugin_reg, encoder_section, BG_STREAM_AUDIO, stream_flags, &s, NULL); if(s) { for(i = 0; i < t->num_audio_streams; i++) t->audio_streams[i].encoder_section = bg_cfg_section_copy(s); } /* Video encoder */ name = bg_encoder_section_get_plugin(plugin_reg, encoder_section, BG_STREAM_VIDEO, stream_flags); bg_cfg_section_set_parameter_string(t->general_section, "video_encoder", name); bg_encoder_section_get_plugin_config(plugin_reg, encoder_section, BG_STREAM_VIDEO, stream_flags, &s, NULL); if(s) { t->video_encoder_section = bg_cfg_section_copy(s); clean_section(t->video_encoder_section); // fprintf(stderr, "Got video encoder section\n"); } // else // fprintf(stderr, "Got no video encoder section\n"); bg_encoder_section_get_stream_config(plugin_reg, encoder_section, BG_STREAM_VIDEO, stream_flags, &s, NULL); if(s) { for(i = 0; i < t->num_video_streams; i++) t->video_streams[i].encoder_section = bg_cfg_section_copy(s); } /* Subtitle text encoder */ name = bg_encoder_section_get_plugin(plugin_reg, encoder_section, BG_STREAM_SUBTITLE_TEXT, stream_flags); bg_cfg_section_set_parameter_string(t->general_section, "subtitle_text_encoder", name); bg_encoder_section_get_plugin_config(plugin_reg, encoder_section, BG_STREAM_SUBTITLE_TEXT, stream_flags, &s, NULL); if(s) { t->subtitle_text_encoder_section = bg_cfg_section_copy(s); clean_section(t->subtitle_text_encoder_section); } bg_encoder_section_get_stream_config(plugin_reg, encoder_section, BG_STREAM_SUBTITLE_TEXT, stream_flags, &s, NULL); bg_encoder_section_get_stream_config(plugin_reg, encoder_section, BG_STREAM_SUBTITLE_OVERLAY, stream_flags, &s1, NULL); if(s) { for(i = 0; i < t->num_subtitle_text_streams; i++) t->subtitle_text_streams[i].encoder_section_text = bg_cfg_section_copy(s); } if(s1) { for(i = 0; i < t->num_subtitle_text_streams; i++) t->subtitle_text_streams[i].encoder_section_overlay = bg_cfg_section_copy(s); } /* Subtitle overlay encoder */ name = bg_encoder_section_get_plugin(plugin_reg, encoder_section, BG_STREAM_SUBTITLE_OVERLAY, stream_flags); bg_cfg_section_set_parameter_string(t->general_section, "subtitle_overlay_encoder", name); bg_encoder_section_get_plugin_config(plugin_reg, encoder_section, BG_STREAM_SUBTITLE_OVERLAY, stream_flags, &s, NULL); if(s) { t->subtitle_overlay_encoder_section = bg_cfg_section_copy(s); clean_section(t->subtitle_overlay_encoder_section); } bg_encoder_section_get_stream_config(plugin_reg, encoder_section, BG_STREAM_SUBTITLE_OVERLAY, stream_flags, &s, NULL); if(s) { for(i = 0; i < t->num_subtitle_overlay_streams; i++) t->subtitle_overlay_streams[i].encoder_section = bg_cfg_section_copy(s); } } gmerlin-1.2.0~dfsg/lib/album.c0000644000175000017500000020212411764363410016111 0ustar alessioalessio/***************************************************************** * gmerlin - a general purpose multimedia framework and applications * * Copyright (c) 2001 - 2011 Members of the Gmerlin project * gmerlin-general@lists.sourceforge.net * http://gmerlin.sourceforge.net * * 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 of the License, 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 this program. If not, see . * *****************************************************************/ #include #include #include #include #include #include /* For stat/opendir */ #include #include #include #include #include #include #include #include #include #include #include #include #define LOG_DOMAIN "album" #ifdef HAVE_INOTIFY #include #endif /* * This must be called, whenever the tracks in an album * change. */ static void delete_shuffle_list(bg_album_t * album) { bg_shuffle_list_destroy(album->com->shuffle_list); album->com->shuffle_list = NULL; } static char * new_filename(bg_album_t * album) { /* * Album filenames are constructed like "aXXXXXXXX.xml", * where XXXXXXXX is a hexadecimal unique identifier */ char * template = NULL; char * path = NULL; char * ret = NULL; char * pos; template = bg_sprintf("%s/a%%08x.xml", album->com->directory); path = bg_create_unique_filename(template); if(!path) goto fail; pos = strrchr(path, '/'); pos++; ret = bg_strdup(NULL, pos); free(path); fail: if(template) free(template); return ret; } void bg_album_set_default_location(bg_album_t * album) { if(!album->xml_file) { album->xml_file = new_filename(album); } } static void entry_from_track_info(bg_album_common_t * com, bg_album_entry_t * entry, bg_track_info_t * track_info, int update_name) { int i; int name_set = 0; entry->num_audio_streams = track_info->num_audio_streams; entry->num_video_streams = 0; entry->num_still_streams = 0; for(i = 0; i < track_info->num_video_streams; i++) { if(track_info->video_streams[i].format.framerate_mode == GAVL_FRAMERATE_STILL) entry->num_still_streams++; else entry->num_video_streams++; } entry->num_subtitle_streams = track_info->num_subtitle_streams; if(!entry->name || update_name) { if(entry->name) { free(entry->name); entry->name = NULL; } if(entry->name_w) { free(entry->name_w); entry->name_w = NULL; entry->len_w = 0; } /* Track info has a name */ if(com && com->use_metadata && com->metadata_format) { entry->name = bg_create_track_name(&track_info->metadata, com->metadata_format); if(entry->name) name_set = 1; } if(!name_set) { if(track_info->name) { entry->name = bg_strdup(entry->name, track_info->name); } /* Take filename minus extension */ else { entry->name = bg_get_track_name_default(entry->location, entry->index, entry->total_tracks); } } } entry->duration = track_info->duration; entry->flags &= ~BG_ALBUM_ENTRY_ERROR; if(track_info->url) { entry->location = bg_strdup(entry->location, track_info->url); entry->index = 0; entry->total_tracks = 1; entry->flags = BG_ALBUM_ENTRY_REDIRECTOR; } } void bg_album_update_entry(bg_album_t * album, bg_album_entry_t * entry, bg_track_info_t * track_info, int callback, int update_name) { entry_from_track_info(album->com, entry, track_info, update_name); if(callback) bg_album_entry_changed(album, entry); } bg_album_entry_t * bg_album_entry_create_from_track_info(bg_track_info_t * track_info, const char * url) { bg_album_entry_t * ret; ret = bg_album_entry_create(); ret->location = bg_strdup(ret->location, url); entry_from_track_info(NULL, ret, track_info, 1); return ret; } bg_album_t * bg_album_create(bg_album_common_t * com, bg_album_type_t type, bg_album_t * parent) { bg_album_t * ret = calloc(1, sizeof(*ret)); ret->com = com; ret->parent = parent; ret->type = type; #ifdef HAVE_INOTIFY ret->inotify_wd = -1; #endif return ret; } char * bg_album_get_name(bg_album_t * a) { return a->name; } int bg_album_get_num_entries(bg_album_t * a) { int ret = 0; bg_album_entry_t * entry; entry = a->entries; while(entry) { ret++; entry = entry->next; } return ret; } bg_album_entry_t * bg_album_get_entry(bg_album_t * a, int i) { bg_album_entry_t * ret; ret = a->entries; while(i--) { if(!ret) return NULL; ret = ret->next; } return ret; } /* Add items */ static void insertion_done(bg_album_t * album, int start, int num) { switch(album->type) { case BG_ALBUM_TYPE_INCOMING: case BG_ALBUM_TYPE_FAVOURITES: break; case BG_ALBUM_TYPE_REGULAR: case BG_ALBUM_TYPE_TUNER: if(!album->xml_file) album->xml_file = new_filename(album); break; case BG_ALBUM_TYPE_REMOVABLE: case BG_ALBUM_TYPE_PLUGIN: break; } delete_shuffle_list(album); if(album->insert_callback) album->insert_callback(album, start, num, album->insert_callback_data); } void bg_album_insert_entries_after(bg_album_t * album, bg_album_entry_t * new_entries, bg_album_entry_t * before) { bg_album_entry_t * last_new_entry; int start, num; if(!new_entries) return; last_new_entry = new_entries; num = 1; while(last_new_entry->next) { last_new_entry = last_new_entry->next; num++; } if(!before) { last_new_entry->next = album->entries; album->entries = new_entries; start = 0; } else { start = bg_album_get_index(album, before) + 1; last_new_entry->next = before->next; before->next = new_entries; } insertion_done(album, start, num); } void bg_album_insert_entries_before(bg_album_t * album, bg_album_entry_t * new_entries, bg_album_entry_t * after) { bg_album_entry_t * before; bg_album_entry_t * last_new_entry; int start, num; if(!new_entries) return; last_new_entry = new_entries; num = 1; while(last_new_entry->next) { last_new_entry = last_new_entry->next; num++; } /* Fill empty album */ if(!album->entries) { album->entries = new_entries; start = 0; } /* Append as first item */ else if(after == album->entries) { last_new_entry->next = album->entries; album->entries = new_entries; start = 0; } else { before = album->entries; start = 1; while(before->next != after) { before = before->next; start++; } before->next = new_entries; last_new_entry->next = after; } insertion_done(album, start, num); } void bg_album_insert_urls_before(bg_album_t * a, char ** locations, const char * plugin, int prefer_edl, bg_album_entry_t * after) { int i = 0; bg_album_entry_t * new_entries; while(locations[i]) { new_entries = bg_album_load_url(a, locations[i], plugin, prefer_edl); bg_album_insert_entries_before(a, new_entries, after); // bg_album_changed(a); i++; } } void bg_album_insert_file_before(bg_album_t * a, char * file, const char * plugin, int prefer_edl, bg_album_entry_t * after, time_t mtime) { bg_album_entry_t * new_entries; bg_album_entry_t * e; new_entries = bg_album_load_url(a, file, plugin, prefer_edl); e = new_entries; while(e) { e->mtime = mtime; e->flags |= BG_ALBUM_ENTRY_SYNC; e = e->next; } bg_album_insert_entries_before(a, new_entries, after); // bg_album_changed(a); } void bg_album_insert_urls_after(bg_album_t * a, char ** locations, const char * plugin, int prefer_edl, bg_album_entry_t * before) { int i = 0; bg_album_entry_t * new_entries; while(locations[i]) { new_entries = bg_album_load_url(a, locations[i], plugin, prefer_edl); bg_album_insert_entries_after(a, new_entries, before); before = new_entries; if(before) { while(before->next) before = before->next; } // bg_album_changed(a); i++; } } /* Inserts a string of the type text/uri-list into the album */ void bg_album_insert_urilist_after(bg_album_t * a, const char * str, int len, bg_album_entry_t * before) { char ** uri_list; uri_list = bg_urilist_decode(str, len); if(!uri_list) return; bg_album_insert_urls_after(a, uri_list, NULL, 0, before); bg_urilist_free(uri_list); } void bg_album_insert_urilist_before(bg_album_t * a, const char * str, int len, bg_album_entry_t * after) { char ** uri_list; uri_list = bg_urilist_decode(str, len); if(!uri_list) return; bg_album_insert_urls_before(a, uri_list, NULL, 0, after); bg_urilist_free(uri_list); } static char * get_playlist_location(const char * orig, int strip_leading, const char * prefix) { int i; char * pos; if(!strncmp(orig, "file://", 7)) orig += 7; if((*orig == '/') && strip_leading) { for(i = 0; i < strip_leading; i++) { pos = strchr(orig+1, '/'); if(pos) orig = pos; else return NULL; } } if(prefix) return bg_sprintf("%s%s", prefix, orig); else return bg_strdup(NULL, orig); } int bg_album_entries_save_extm3u(bg_album_entry_t * e, const char * name, int strip_leading, const char * prefix) { FILE * out; char * tmp_string; if(!e) { bg_log(BG_LOG_ERROR, LOG_DOMAIN, "Not exporting empty album"); return 0; } out = fopen(name, "w"); if(!out) { bg_log(BG_LOG_ERROR, LOG_DOMAIN, "Could not open %s: %s", name, strerror(errno)); return 0; } fprintf(out, "#EXTM3U\r\n"); while(e) { tmp_string = get_playlist_location(e->location, strip_leading, prefix); if(!tmp_string) { e = e->next; continue; } fprintf(out, "#EXTINF:%d,%s\r\n", (int)(e->duration / GAVL_TIME_SCALE), e->name); fprintf(out, "%s\r\n", tmp_string); free(tmp_string); e = e->next; } fclose(out); return 1; } int bg_album_entries_save_pls(bg_album_entry_t * e, const char * name, int strip_leading, const char * prefix) { FILE * out; int count = 1; char * tmp_string; if(!e) { bg_log(BG_LOG_ERROR, LOG_DOMAIN, "Not exporting empty album"); return 0; } out = fopen(name, "w"); if(!out) { bg_log(BG_LOG_ERROR, LOG_DOMAIN, "Could not open %s: %s", name, strerror(errno)); return 0; } fprintf(out, "[Playlist]\r\n"); while(e) { tmp_string = get_playlist_location(e->location, strip_leading, prefix); if(!tmp_string) { e = e->next; continue; } fprintf(out, "File%d=%s\r\n", count, tmp_string); fprintf(out, "Title%d=%s\r\n",count, e->name); fprintf(out, "Length%d=%d\r\n",count, (int)(e->duration / GAVL_TIME_SCALE)); free(tmp_string); e = e->next; count++; } // Footer fprintf(out, "NumberOfEntries=%d\r\n", count-1); fprintf(out, "Version=2\r\n"); fclose(out); return 1; } /* Open / close */ static int open_device(bg_album_t * a) { bg_track_info_t * track_info; int i, j; int num_tracks; bg_input_plugin_t * plugin; bg_album_entry_t * new_entry; a->handle = bg_plugin_load(a->com->plugin_reg, a->plugin_info); bg_plugin_lock(a->handle); plugin = (bg_input_plugin_t*)a->handle->plugin; /* Open the plugin */ if(!plugin->open(a->handle->priv, a->device)) { bg_plugin_unlock(a->handle); return 0; } if(plugin->get_disc_name) { a->disc_name = bg_strdup(a->disc_name, plugin->get_disc_name(a->handle->priv)); if(!a->disc_name || (*a->disc_name == '\0')) a->disc_name = bg_strdup(a->disc_name, TR("Unnamed disc")); } if(plugin->eject_disc) a->flags |= BG_ALBUM_CAN_EJECT; /* Get number of tracks */ num_tracks = plugin->get_num_tracks(a->handle->priv); for(i = 0; i < num_tracks; i++) { track_info = plugin->get_track_info(a->handle->priv, i); new_entry = calloc(1, sizeof(*new_entry)); new_entry->index = i; new_entry->total_tracks = num_tracks; new_entry->name = bg_strdup(NULL, track_info->name); new_entry->plugin = bg_strdup(NULL, a->handle->info->name); new_entry->location = bg_strdup(new_entry->location, a->device); new_entry->num_audio_streams = track_info->num_audio_streams; new_entry->num_still_streams = 0; new_entry->num_video_streams = 0; for(j = 0; j < track_info->num_video_streams; j++) { if(track_info->video_streams[j].format.framerate_mode == GAVL_FRAMERATE_STILL) new_entry->num_still_streams++; else new_entry->num_video_streams++; } new_entry->num_subtitle_streams = track_info->num_subtitle_streams; new_entry->duration = track_info->duration; bg_album_insert_entries_before(a, new_entry, NULL); } bg_plugin_unlock(a->handle); return 1; } bg_album_type_t bg_album_get_type(bg_album_t * a) { return a->type; } static bg_album_entry_t * find_next_with_location(bg_album_t * a, char * filename, bg_album_entry_t * before) { if(!before) before = a->entries; else before = before->next; while(before) { if(!strcmp(before->location, filename)) break; before = before->next; } return before; } static void sync_dir_add(bg_album_t * a, char * filename, time_t mtime) { bg_album_insert_file_before(a, filename, NULL, 0, NULL, mtime); } static void sync_dir_modify(bg_album_t * a, char * filename, time_t mtime) { bg_album_delete_with_file(a, filename); sync_dir_add(a, filename, mtime); } int bg_album_inotify(bg_album_t * a, uint8_t * event1) { #ifdef HAVE_INOTIFY char * filename; bg_album_t * child; struct stat stat_buf; if(a->inotify_wd >= 0) { struct inotify_event *event = ( struct inotify_event * ) event1; if(event->wd == a->inotify_wd) { switch(event->mask) { case IN_DELETE: case IN_MOVED_FROM: filename = bg_sprintf("%s/%s", a->watch_dir, event->name); bg_log(BG_LOG_INFO, LOG_DOMAIN, "%s disappeared, updating album", filename); bg_album_delete_with_file(a, filename); free(filename); break; case IN_CLOSE_WRITE: case IN_MOVED_TO: filename = bg_sprintf("%s/%s", a->watch_dir, event->name); bg_log(BG_LOG_INFO, LOG_DOMAIN, "%s appeared, updating album", filename); if(stat(filename, &stat_buf)) { free(filename); return 1; } sync_dir_add(a, filename, stat_buf.st_mtime); free(filename); break; } return 1; } } /* Not our event, try children */ child = a->children; while(child) { if(bg_album_inotify(child, event1)) return 1; child = child->next; } return 0; #else return 0; #endif } static void sync_with_dir(bg_album_t * a) { // char * tmp_string; DIR * dir; char filename[FILENAME_MAX]; struct dirent * dent_ptr; struct stat stat_buf; bg_album_entry_t * e; struct { struct dirent d; char b[NAME_MAX]; /* Make sure there is enough memory */ } dent; dir = opendir(a->watch_dir); if(!dir) return; while(!readdir_r(dir, &dent.d, &dent_ptr)) { if(!dent_ptr) break; if(dent.d.d_name[0] == '.') /* Don't import hidden files */ continue; sprintf(filename, "%s/%s", a->watch_dir, dent.d.d_name); if(stat(filename, &stat_buf)) continue; /* Add directory as subalbum */ if(S_ISDIR(stat_buf.st_mode)) continue; else if(S_ISREG(stat_buf.st_mode)) { e = find_next_with_location(a, filename, NULL); if(e) { while(e) { if(e->mtime != stat_buf.st_mtime) { sync_dir_modify(a, filename, stat_buf.st_mtime); break; } else e->flags |= BG_ALBUM_ENTRY_SYNC; e = find_next_with_location(a, filename, e); } } else sync_dir_add(a, filename, stat_buf.st_mtime); } } closedir(dir); bg_album_delete_unsync(a); } int bg_album_open(bg_album_t * a) { char * tmp_filename; FILE * testfile; bg_input_plugin_t * plugin; if(a->open_count) { bg_log(BG_LOG_DEBUG, LOG_DOMAIN, "Album %s already open", a->name); a->open_count++; return 1; } bg_log(BG_LOG_DEBUG, LOG_DOMAIN, "Opening album %s", a->name); a->cfg_section = bg_cfg_section_create(NULL); switch(a->type) { case BG_ALBUM_TYPE_REGULAR: case BG_ALBUM_TYPE_FAVOURITES: case BG_ALBUM_TYPE_INCOMING: if(a->xml_file) { tmp_filename = bg_sprintf("%s/%s", a->com->directory, a->xml_file); /* If the file cannot be opened, it was deleted earlier we exit quietly here */ if(!(testfile = fopen(tmp_filename,"r"))) { free(tmp_filename); break; } fclose(testfile); bg_album_load(a, tmp_filename); free(tmp_filename); } break; case BG_ALBUM_TYPE_TUNER: if(a->xml_file) { tmp_filename = bg_sprintf("%s/%s", a->com->directory, a->xml_file); /* If the file cannot be opened, it was deleted earlier we exit quietly here */ if(!(testfile = fopen(tmp_filename,"r"))) { free(tmp_filename); if(!open_device(a)) return 0; break; } fclose(testfile); bg_album_load(a, tmp_filename); free(tmp_filename); a->handle = bg_plugin_load(a->com->plugin_reg, a->plugin_info); bg_plugin_lock(a->handle); plugin = (bg_input_plugin_t*)a->handle->plugin; /* Open the plugin */ if(!plugin->open(a->handle->priv, a->device)) { bg_plugin_unlock(a->handle); return 0; } bg_plugin_unlock(a->handle); } else if(!open_device(a)) return 0; break; case BG_ALBUM_TYPE_REMOVABLE: /* Get infos from the plugin */ if(!open_device(a)) return 0; break; case BG_ALBUM_TYPE_PLUGIN: return 0; /* Cannot be opened */ break; } a->open_count++; if((a->type == BG_ALBUM_TYPE_REGULAR) && a->watch_dir) { sync_with_dir(a); #ifdef HAVE_INOTIFY a->inotify_wd = inotify_add_watch(a->com->inotify_fd, a->watch_dir, IN_CLOSE_WRITE | IN_DELETE | IN_MOVED_TO | IN_MOVED_FROM); #endif } return 1; } void bg_album_entry_destroy(bg_album_entry_t * entry) { if(entry->name) free(entry->name); if(entry->location) free(entry->location); if(entry->plugin) free(entry->plugin); free(entry); } void bg_album_entries_destroy(bg_album_entry_t * entries) { bg_album_entry_t * tmp_entry; while(entries) { tmp_entry = entries->next; bg_album_entry_destroy(entries); entries = tmp_entry; } } int bg_album_entries_count(bg_album_entry_t * e) { int ret = 0; while(e) { ret++; e = e->next; } return ret; } bg_album_entry_t * bg_album_entry_create() { bg_album_entry_t * ret; ret = calloc(1, sizeof(*ret)); return ret; } void bg_album_close(bg_album_t *a ) { // char * tmp_filename; a->open_count--; if(a->open_count) { bg_log(BG_LOG_DEBUG, LOG_DOMAIN, "Not closing album %s (open_count > 0)", a->name); return; } bg_log(BG_LOG_DEBUG, LOG_DOMAIN, "Closing album %s", a->name); /* Tell the tree, if we are the current album */ if((a == a->com->current_album) && a->com->set_current_callback) { a->com->set_current_callback(a->com->set_current_callback_data, NULL, NULL); } switch(a->type) { case BG_ALBUM_TYPE_REMOVABLE: case BG_ALBUM_TYPE_TUNER: a->flags &= ~BG_ALBUM_CAN_EJECT; bg_plugin_unref(a->handle); a->handle = NULL; if(a->disc_name) { free(a->disc_name); a->disc_name = NULL; } if(a->type == BG_ALBUM_TYPE_TUNER) bg_album_save(a, NULL); break; case BG_ALBUM_TYPE_REGULAR: case BG_ALBUM_TYPE_INCOMING: case BG_ALBUM_TYPE_FAVOURITES: bg_album_save(a, NULL); break; case BG_ALBUM_TYPE_PLUGIN: break; } /* Delete entries */ bg_album_entries_destroy(a->entries); a->entries = NULL; /* Delete shuffle list */ delete_shuffle_list(a); /* Destroy config data */ if(a->cfg_section) { bg_cfg_section_destroy(a->cfg_section); a->cfg_section = NULL; } #ifdef HAVE_INOTIFY if(a->inotify_wd >= 0) { inotify_rm_watch(a->com->inotify_fd, a->inotify_wd); a->inotify_wd = -1; } #endif // if(a->watch_dir) } void bg_album_set_expanded(bg_album_t * a, int expanded) { if(expanded) a->flags |= BG_ALBUM_EXPANDED; else { bg_album_t * child; a->flags &= ~BG_ALBUM_EXPANDED; /* Unexpand the children too */ child = a->children; while(child) { bg_album_set_expanded(child, 0); child = child->next; } } } int bg_album_get_expanded(bg_album_t * a) { if(a->flags & BG_ALBUM_EXPANDED) return 1; return 0; } int bg_album_is_open(bg_album_t * a) { return (a->open_count) ? 1 : 0; } void bg_album_destroy(bg_album_t * a) { // char * tmp_filename; bg_album_t * tmp_album; /* Things to do if an album was open */ if(a->open_count) { bg_album_save(a, NULL); } if(a->name) free(a->name); if(a->xml_file) free(a->xml_file); if(a->device) free(a->device); if(a->disc_name) free(a->disc_name); if(a->cfg_section) bg_cfg_section_destroy(a->cfg_section); /* Free entries */ bg_album_entries_destroy(a->entries); /* Free Children */ while(a->children) { tmp_album = a->children->next; bg_album_destroy(a->children); a->children = tmp_album; } /* free rest */ free(a); } void bg_album_delete_selected(bg_album_t * album) { int num_selected = 0; bg_album_entry_t * cur; bg_album_entry_t * cur_next; bg_album_entry_t * new_entries_end = NULL; bg_album_entry_t * new_entries; int index, i; int * indices = NULL; if(!album->entries) return; cur = album->entries; num_selected = bg_album_num_selected(album); if(!num_selected) return; if(album->delete_callback) { indices = malloc((num_selected +1)*sizeof(*indices)); } cur = album->entries; new_entries = NULL; index = 0; i = 0; while(cur) { cur_next = cur->next; if(cur->flags & BG_ALBUM_ENTRY_SELECTED) { if(cur == album->com->current_entry) { album->com->current_entry = NULL; album->com->current_album = NULL; } bg_album_entry_destroy(cur); if(indices) indices[i] = index; i++; } else { if(!new_entries) { new_entries = cur; new_entries_end = cur; } else { new_entries_end->next = cur; new_entries_end = new_entries_end->next; } } cur = cur_next; index++; } if(new_entries) new_entries_end->next = NULL; album->entries = new_entries; delete_shuffle_list(album); if(indices) { indices[i] = -1; album->delete_callback(album, indices, album->delete_callback_data); free(indices); } // bg_album_changed(album); } void bg_album_delete_unsync(bg_album_t * album) { int num_selected = 0; bg_album_entry_t * cur; bg_album_entry_t * cur_next; bg_album_entry_t * new_entries_end = NULL; bg_album_entry_t * new_entries; int index, i; int * indices = NULL; if(!album->entries) return; cur = album->entries; num_selected = bg_album_num_unsync(album); if(!num_selected) return; if(album->delete_callback) { indices = malloc((num_selected +1)*sizeof(*indices)); } cur = album->entries; new_entries = NULL; index = 0; i = 0; while(cur) { cur_next = cur->next; if(!(cur->flags & BG_ALBUM_ENTRY_SYNC)) { if(cur == album->com->current_entry) { album->com->current_entry = NULL; album->com->current_album = NULL; } bg_album_entry_destroy(cur); if(indices) indices[i] = index; i++; } else { if(!new_entries) { new_entries = cur; new_entries_end = cur; } else { new_entries_end->next = cur; new_entries_end = new_entries_end->next; } } cur = cur_next; index++; } if(new_entries) new_entries_end->next = NULL; album->entries = new_entries; delete_shuffle_list(album); if(indices) { indices[i] = -1; album->delete_callback(album, indices, album->delete_callback_data); free(indices); } // bg_album_changed(album); } void bg_album_delete_with_file(bg_album_t * album, const char * filename) { bg_album_entry_t * cur; bg_album_entry_t * cur_next; bg_album_entry_t * new_entries_end = NULL; bg_album_entry_t * new_entries; int index, i; int * indices = NULL; if(!album->entries) return; cur = album->entries; cur = album->entries; new_entries = NULL; index = 0; i = 0; while(cur) { cur_next = cur->next; if(!strcmp(cur->location, filename)) { if(cur == album->com->current_entry) { album->com->current_entry = NULL; album->com->current_album = NULL; } bg_album_entry_destroy(cur); if(album->delete_callback) { indices = realloc(indices, (i+1) * sizeof(indices)); indices[i] = index; } i++; } else { if(!new_entries) { new_entries = cur; new_entries_end = cur; } else { new_entries_end->next = cur; new_entries_end = new_entries_end->next; } } cur = cur_next; index++; } if(new_entries) new_entries_end->next = NULL; album->entries = new_entries; delete_shuffle_list(album); if(indices) { indices = realloc(indices, (i+1) * sizeof(indices)); indices[i] = -1; album->delete_callback(album, indices, album->delete_callback_data); free(indices); } } void bg_album_select_error_tracks(bg_album_t * album) { bg_album_entry_t * cur; cur = album->entries; while(cur) { if(cur->flags & BG_ALBUM_ENTRY_ERROR) cur->flags |= BG_ALBUM_ENTRY_SELECTED; else cur->flags &= ~BG_ALBUM_ENTRY_SELECTED; cur = cur->next; } bg_album_changed(album); } static bg_album_entry_t * copy_selected(bg_album_t * album) { bg_album_entry_t * ret = NULL; bg_album_entry_t * ret_end = NULL; bg_album_entry_t * tmp_entry; tmp_entry = album->entries; while(tmp_entry) { if(tmp_entry->flags & BG_ALBUM_ENTRY_SELECTED) { if(ret) { ret_end->next = bg_album_entry_copy(album, tmp_entry); ret_end = ret_end->next; } else { ret = bg_album_entry_copy(album, tmp_entry); ret_end = ret; } } tmp_entry = tmp_entry->next; } return ret; } static bg_album_entry_t * extract_selected(bg_album_t * album) { bg_album_entry_t * selected_end = NULL; bg_album_entry_t * other_end = NULL; bg_album_entry_t * tmp_entry; bg_album_entry_t * other = NULL; bg_album_entry_t * selected = NULL; while(album->entries) { tmp_entry = album->entries->next; if(album->entries->flags & BG_ALBUM_ENTRY_SELECTED) { if(!selected) { selected = album->entries; selected_end = selected; } else { selected_end->next = album->entries; selected_end = selected_end->next; } selected_end->next = NULL; } else { if(!other) { other = album->entries; other_end = other; } else { other_end->next = album->entries; other_end = other_end->next; } other_end->next = NULL; } album->entries = tmp_entry; } album->entries = other; return selected; } void bg_album_move_selected_up(bg_album_t * album) { bg_album_entry_t * selected; selected = extract_selected(album); bg_album_insert_entries_after(album, selected, NULL); bg_album_changed(album); } void bg_album_move_selected_down(bg_album_t * album) { bg_album_entry_t * selected; selected = extract_selected(album); bg_album_insert_entries_before(album, selected, NULL); bg_album_changed(album); } typedef struct { bg_album_entry_t * entry; char * sort_string; } sort_entries_struct; void bg_album_sort_entries(bg_album_t * album) { int num_entries; int i, j; char * tmp_string; int sort_string_len; sort_entries_struct * s_tmp; int keep_going; sort_entries_struct ** s; bg_album_entry_t * tmp_entry; /* 1. Count the entries */ num_entries = 0; tmp_entry = album->entries; while(tmp_entry) { tmp_entry = tmp_entry->next; num_entries++; } if(!num_entries) return; /* Set up the album array */ s = malloc(num_entries * sizeof(*s)); tmp_entry = album->entries; for(i = 0; i < num_entries; i++) { s[i] = calloc(1, sizeof(*(s[i]))); s[i]->entry = tmp_entry; /* Set up the sort string */ tmp_string = bg_utf8_to_system(tmp_entry->name, strlen(tmp_entry->name)); sort_string_len = strxfrm(NULL, tmp_string, 0); s[i]->sort_string = malloc(sort_string_len+1); strxfrm(s[i]->sort_string, tmp_string, sort_string_len+1); free(tmp_string); /* Advance */ tmp_entry = tmp_entry->next; } /* Now, do a braindead bubblesort algorithm */ for(i = 0; i < num_entries - 1; i++) { keep_going = 0; for(j = num_entries-1; j > i; j--) { if(strcmp(s[j]->sort_string, s[j-1]->sort_string) < 0) { s_tmp = s[j]; s[j] = s[j-1]; s[j-1] = s_tmp; keep_going = 1; } } if(!keep_going) break; } /* Rechain entries */ album->entries = s[0]->entry; for(i = 0; i < num_entries-1; i++) { s[i]->entry->next = s[i+1]->entry; } s[num_entries-1]->entry->next = NULL; /* Free everything */ for(i = 0; i < num_entries; i++) { free(s[i]->sort_string); free(s[i]); } free(s); bg_album_changed(album); } typedef struct { bg_album_t * child; char * sort_string; } sort_children_struct; void bg_album_sort_children(bg_album_t * album) { int num_children; int i, j; char * tmp_string; int sort_string_len; sort_children_struct * s_tmp; int keep_going; sort_children_struct ** s; bg_album_t * tmp_child; /* 1. Count the children */ num_children = 0; tmp_child = album->children; while(tmp_child) { tmp_child = tmp_child->next; num_children++; } if(!num_children) return; /* Set up the album array */ s = malloc(num_children * sizeof(*s)); tmp_child = album->children; for(i = 0; i < num_children; i++) { s[i] = calloc(1, sizeof(*(s[i]))); s[i]->child = tmp_child; /* Set up the sort string */ tmp_string = bg_utf8_to_system(tmp_child->name, strlen(tmp_child->name)); sort_string_len = strxfrm(NULL, tmp_string, 0); s[i]->sort_string = malloc(sort_string_len+1); strxfrm(s[i]->sort_string, tmp_string, sort_string_len+1); free(tmp_string); /* Advance */ tmp_child = tmp_child->next; } /* Now, do a braindead bubblesort algorithm */ for(i = 0; i < num_children - 1; i++) { keep_going = 0; for(j = num_children-1; j > i; j--) { if(strcmp(s[j]->sort_string, s[j-1]->sort_string) < 0) { s_tmp = s[j]; s[j] = s[j-1]; s[j-1] = s_tmp; keep_going = 1; } } if(!keep_going) break; } /* Rechain children */ album->children = s[0]->child; for(i = 0; i < num_children-1; i++) { s[i]->child->next = s[i+1]->child; } s[num_children-1]->child->next = NULL; /* Free everything */ for(i = 0; i < num_children; i++) { free(s[i]->sort_string); free(s[i]); } free(s); } /* END */ void bg_album_rename_track(bg_album_t * album, const bg_album_entry_t * entry_c, const char * name) { bg_album_entry_t * entry; entry = album->entries; while(entry) { if(entry == entry_c) break; entry = entry->next; } entry->name = bg_strdup(entry->name, name); if(entry->name_w) { free(entry->name_w); entry->name_w = NULL; entry->len_w = 0; } bg_album_entry_changed(album, entry); } void bg_album_rename(bg_album_t * a, const char * name) { a->name = bg_strdup(a->name, name); if(((a->type == BG_ALBUM_TYPE_REMOVABLE) || (a->type == BG_ALBUM_TYPE_TUNER)) && a->plugin_info) { bg_plugin_registry_set_device_name(a->com->plugin_reg, a->plugin_info->name, a->device, name); } if(a->name_change_callback) a->name_change_callback(a, name, a->name_change_callback_data); } bg_album_entry_t * bg_album_get_current_entry(bg_album_t * a) { return a->com->current_entry; } int bg_album_next(bg_album_t * a, int wrap) { if(a->com->current_entry) { if(!a->com->current_entry->next) { if(wrap) { if(a->com->set_current_callback) a->com->set_current_callback(a->com->set_current_callback_data, a, a->entries); return 1; } else return 0; } else { if(a->com->set_current_callback) a->com->set_current_callback(a->com->set_current_callback_data, a, a->com->current_entry->next); return 1; } } else return 0; } gavl_time_t bg_album_get_duration(bg_album_t * a) { gavl_time_t ret = 0; bg_album_entry_t * e; e = a->entries; while(e) { if(e->duration == GAVL_TIME_UNDEFINED) return GAVL_TIME_UNDEFINED; else ret += e->duration; e = e->next; } return ret; } int bg_album_get_index(bg_album_t* a, const bg_album_entry_t * entry) { int index = 0; const bg_album_entry_t * e; e = a->entries; while(1) { if(e == entry) return index; index++; e = e->next; if(!e) break; } return -1; } int bg_album_previous(bg_album_t * a, int wrap) { bg_album_entry_t * tmp_entry; if(!a->com->current_entry) return 0; if(a->com->current_entry == a->entries) { if(!wrap) return 0; tmp_entry = a->entries; while(tmp_entry->next) tmp_entry = tmp_entry->next; if(a->com->set_current_callback) a->com->set_current_callback(a->com->set_current_callback_data, a, tmp_entry); return 1; } else { tmp_entry = a->entries; while(tmp_entry->next != a->com->current_entry) tmp_entry = tmp_entry->next; if(a->com->set_current_callback) a->com->set_current_callback(a->com->set_current_callback_data, a, tmp_entry); return 1; } } void bg_album_set_change_callback(bg_album_t * a, void (*change_callback)(bg_album_t * a, void * data), void * change_callback_data) { a->change_callback = change_callback; a->change_callback_data = change_callback_data; } void bg_album_set_entry_change_callback(bg_album_t * a, void (*change_callback)(bg_album_t * a, const bg_album_entry_t * e, void * data), void * change_callback_data) { a->entry_change_callback = change_callback; a->entry_change_callback_data = change_callback_data; } void bg_album_set_current_change_callback(bg_album_t * a, void (*change_callback)(bg_album_t * a, const bg_album_entry_t * e, void * data), void * change_callback_data) { a->current_change_callback = change_callback; a->current_change_callback_data = change_callback_data; } void bg_album_set_delete_callback(bg_album_t * a, void (*delete_callback)(bg_album_t * current_album, int * indices, void * data), void * delete_callback_data) { a->delete_callback = delete_callback; a->delete_callback_data = delete_callback_data; } void bg_album_set_insert_callback(bg_album_t * a, void (*insert_callback)(bg_album_t * current_album, int start, int num, void * data), void * insert_callback_data) { a->insert_callback = insert_callback; a->insert_callback_data = insert_callback_data; } void bg_album_set_name_change_callback(bg_album_t * a, void (*name_change_callback)(bg_album_t * a, const char * name, void * data), void * name_change_callback_data) { a->name_change_callback = name_change_callback; a->name_change_callback_data = name_change_callback_data; } void bg_album_changed(bg_album_t * a) { if(a->change_callback) a->change_callback(a, a->change_callback_data); } void bg_album_current_changed(bg_album_t * a) { if(a->current_change_callback) a->current_change_callback(a->com->current_album, a->com->current_entry, a->current_change_callback_data); } void bg_album_entry_changed(bg_album_t * a, const bg_album_entry_t * e) { if(a->entry_change_callback) a->entry_change_callback(a->com->current_album, e, a->entry_change_callback_data); } void bg_album_set_current(bg_album_t * a, const bg_album_entry_t * e) { bg_album_entry_t * tmp_entry; tmp_entry = a->entries; while(tmp_entry != e) tmp_entry = tmp_entry->next; if(a->com->set_current_callback) a->com->set_current_callback(a->com->set_current_callback_data, a, tmp_entry); // bg_album_current_changed(a); } void bg_album_play(bg_album_t * a) { if(a->com->play_callback) a->com->play_callback(a->com->play_callback_data); } bg_cfg_section_t * bg_album_get_cfg_section(bg_album_t * album) { return album->cfg_section; } int bg_album_is_current(bg_album_t * a) { return (a == a->com->current_album) ? 1 : 0; } int bg_album_entry_is_current(bg_album_t * a, bg_album_entry_t * e) { return ((a == a->com->current_album) && (e == a->com->current_entry)) ? 1 : 0; } bg_plugin_registry_t * bg_album_get_plugin_registry(bg_album_t * a) { return a->com->plugin_reg; } void bg_album_get_times(bg_album_t * a, gavl_time_t * duration_before, gavl_time_t * duration_current, gavl_time_t * duration_after) { bg_album_entry_t * e; if(a != a->com->current_album) { *duration_before = GAVL_TIME_UNDEFINED; *duration_current = GAVL_TIME_UNDEFINED; *duration_after = GAVL_TIME_UNDEFINED; return; } e = a->entries; *duration_before = 0; while(e != a->com->current_entry) { if(e->duration == GAVL_TIME_UNDEFINED) { *duration_before = GAVL_TIME_UNDEFINED; break; } *duration_before += e->duration; e = e->next; } *duration_current = a->com->current_entry->duration; *duration_after = 0; e = a->com->current_entry->next; while(e) { if(e->duration == GAVL_TIME_UNDEFINED) { *duration_after = GAVL_TIME_UNDEFINED; break; } *duration_after += e->duration; e = e->next; } } void bg_album_set_error(bg_album_t * a, int err) { if(err) a->flags |= BG_ALBUM_ERROR; else a->flags &= ~BG_ALBUM_ERROR; } int bg_album_get_error(bg_album_t * a) { return !!(a->flags & BG_ALBUM_ERROR); } void bg_album_append_child(bg_album_t * parent, bg_album_t * child) { bg_album_t * album_before; if(parent->children) { album_before = parent->children; while(album_before->next) album_before = album_before->next; album_before->next = child; } else parent->children = child; } static void add_device(bg_album_t * album, const char * device, const char * name) { bg_album_t * device_album; bg_album_type_t type = BG_ALBUM_TYPE_REGULAR; if(album->plugin_info->flags & BG_PLUGIN_REMOVABLE) type = BG_ALBUM_TYPE_REMOVABLE; else if(album->plugin_info->flags & BG_PLUGIN_TUNER) type = BG_ALBUM_TYPE_TUNER; device_album = bg_album_create(album->com, type, album); device_album->device = bg_strdup(device_album->device, device); if(name) { device_album->name = bg_strdup(device_album->name, name); } else { device_album->name = bg_strdup(device_album->name, device); } device_album->plugin_info = album->plugin_info; bg_album_append_child(album, device_album); } void bg_album_add_device(bg_album_t * album, const char * device, const char * name) { add_device(album, device, name); bg_plugin_registry_add_device(album->com->plugin_reg, album->plugin_info->name, device, name); } static bg_album_t * remove_from_list(bg_album_t * list, bg_album_t * album, int * index) { bg_album_t * sibling_before; *index = 0; if(album == list) return album->next; else { sibling_before = list; (*index)++; while(sibling_before->next != album) { sibling_before = sibling_before->next; (*index)++; } sibling_before->next = album->next; return list; } } void bg_album_remove_from_parent(bg_album_t * album) { int index; if(!album->parent) return; album->parent->children = remove_from_list(album->parent->children, album, &index); if(album->type == BG_ALBUM_TYPE_REMOVABLE) { bg_plugin_registry_remove_device(album->com->plugin_reg, album->plugin_info->name, album->plugin_info->devices[index].device, album->plugin_info->devices[index].name); } } void bg_album_set_devices(bg_album_t * a) { bg_album_t * tmp_album; int j; /* Delete previous children */ while(a->children) { tmp_album = a->children->next; bg_album_destroy(a->children); a->children = tmp_album; } if(a->plugin_info->devices && a->plugin_info->devices->device) { j = 0; while(a->plugin_info->devices[j].device) { add_device(a, a->plugin_info->devices[j].device, a->plugin_info->devices[j].name); j++; } /* Device loop */ } } void bg_album_find_devices(bg_album_t * a) { bg_plugin_registry_find_devices(a->com->plugin_reg, a->plugin_info->name); bg_album_set_devices(a); } static bg_album_entry_t * remove_redirectors(bg_album_t * album, bg_album_entry_t * entries) { bg_album_entry_t * before; bg_album_entry_t * e; bg_album_entry_t * new_entry, * end_entry; int done = 0; const bg_plugin_info_t * info; const char * name; done = 1; e = entries; while(e) { if(e->flags & BG_ALBUM_ENTRY_REDIRECTOR) { /* Load "real" url */ if(e->plugin) { info = bg_plugin_find_by_name(album->com->plugin_reg, e->plugin); name = info->name; } else name = NULL; new_entry = bg_album_load_url(album, e->location, name, 0); if(new_entry) { /* Insert new entries into list */ if(e != entries) { before = entries; while(before->next != e) before = before->next; before->next = new_entry; } else { entries = new_entry; } end_entry = new_entry; while(end_entry->next) { /* Set plugin so we don't have to set it next time */ end_entry->plugin = bg_strdup(end_entry->plugin, album->com->load_handle->info->name); end_entry = end_entry->next; } /* Set plugin so we don't have to set it next time */ end_entry->plugin = bg_strdup(end_entry->plugin, album->com->load_handle->info->name); end_entry->next = e->next; bg_album_entry_destroy(e); e = new_entry; } else { /* Remove e from list */ if(e != entries) { before = entries; while(before->next != e) before = before->next; before->next = e->next; } else { entries = e->next; before = NULL; } bg_album_entry_destroy(e); e = (before) ? before->next : entries; } } else { /* Leave e as it is */ e = e->next; } } return entries; } static int is_blacklisted(bg_album_common_t * com, const char * url) { const char * pos; if(!com->blacklist) // No blacklist return 0; if(strncmp(url, "file:", 5) && (*url != '/')) // Remote file return 0; pos = strrchr(url, '.'); if(pos) { pos++; if(bg_string_match(pos, com->blacklist)) { bg_log(BG_LOG_DEBUG, LOG_DOMAIN, "Not loading %s (blacklisted extension)", url); return 1; } } pos = strrchr(url, '/'); if(pos) { pos++; if(bg_string_match(pos, com->blacklist_files)) { bg_log(BG_LOG_DEBUG, LOG_DOMAIN, "Not loading %s (blacklisted filename)", url); return 1; } } return 0; } bg_album_entry_t * bg_album_load_url(bg_album_t * album, char * url, const char * plugin_name, int prefer_edl) { int i, num_entries; bg_album_entry_t * new_entry; bg_album_entry_t * end_entry = NULL; bg_album_entry_t * ret = NULL; // char * system_location; bg_input_plugin_t * plugin; bg_track_info_t * track_info; const bg_plugin_info_t * info; // const char * file_plugin_name; if(is_blacklisted(album->com, url)) { return NULL; } bg_log(BG_LOG_INFO, LOG_DOMAIN, "Loading %s", url); /* Load the appropriate plugin */ if(plugin_name) { info = bg_plugin_find_by_name(album->com->plugin_reg, plugin_name); } else info = NULL; bg_album_common_prepare_callbacks(album->com, NULL); if(!bg_input_plugin_load(album->com->plugin_reg, url, info, &album->com->load_handle, &album->com->input_callbacks, prefer_edl)) { bg_log(BG_LOG_WARNING, LOG_DOMAIN, "Loading %s failed", url); return NULL; } plugin = (bg_input_plugin_t*)(album->com->load_handle->plugin); /* Open the track */ if(!plugin->get_num_tracks) num_entries = 1; else num_entries = plugin->get_num_tracks(album->com->load_handle->priv); for(i = 0; i < num_entries; i++) { track_info = plugin->get_track_info(album->com->load_handle->priv, i); new_entry = bg_album_entry_create(); // new_entry->location = bg_system_to_utf8(url, strlen(url)); new_entry->location = bg_strdup(new_entry->location, url); new_entry->index = i; new_entry->total_tracks = num_entries; if(album->com->load_handle->edl) new_entry->flags |= BG_ALBUM_ENTRY_EDL; bg_log(BG_LOG_INFO, LOG_DOMAIN, "Loaded %s (track %d of %d)", url, new_entry->index+1, new_entry->total_tracks); bg_album_common_set_auth_info(album->com, new_entry); bg_album_update_entry(album, new_entry, track_info, 0, 1); new_entry->plugin = bg_strdup(new_entry->plugin, plugin_name); if(ret) { end_entry->next = new_entry; end_entry = end_entry->next; } else { ret = new_entry; end_entry = ret; } } plugin->close(album->com->load_handle->priv); ret = remove_redirectors(album, ret); return ret; } int bg_album_get_unique_id(bg_album_t * album) { album->com->highest_id++; return album->com->highest_id; } static int refresh_entry(bg_album_t * album, bg_album_entry_t * entry, bg_edl_t * edl) { const bg_plugin_info_t * info; // char * system_location; bg_input_plugin_t * plugin; bg_track_info_t * track_info; int i; /* Check, which plugin to use */ if(entry->plugin) { info = bg_plugin_find_by_name(album->com->plugin_reg, entry->plugin); } else info = NULL; // system_location = bg_utf8_to_system(entry->location, // strlen(entry->location)); bg_album_common_prepare_callbacks(album->com, entry); if(!bg_input_plugin_load(album->com->plugin_reg, entry->location, info, &album->com->load_handle, &album->com->input_callbacks, !!(entry->flags & BG_ALBUM_ENTRY_EDL))) { entry->flags |= BG_ALBUM_ENTRY_ERROR; bg_album_entry_changed(album, entry); return 0; } plugin = (bg_input_plugin_t*)(album->com->load_handle->plugin); track_info = plugin->get_track_info(album->com->load_handle->priv, entry->index); bg_album_common_set_auth_info(album->com, entry); if(edl) /* Need timescales */ { if(plugin->set_track) plugin->set_track(album->com->load_handle->priv, entry->index); if(plugin->set_audio_stream) { for(i = 0; i < track_info->num_audio_streams; i++) plugin->set_audio_stream(album->com->load_handle->priv, i, BG_STREAM_ACTION_DECODE); } if(plugin->set_video_stream) { for(i = 0; i < track_info->num_video_streams; i++) plugin->set_video_stream(album->com->load_handle->priv, i, BG_STREAM_ACTION_DECODE); } if(plugin->set_subtitle_stream) { for(i = 0; i < track_info->num_subtitle_streams; i++) plugin->set_subtitle_stream(album->com->load_handle->priv, i, BG_STREAM_ACTION_DECODE); } if(plugin->start) plugin->start(album->com->load_handle->priv); bg_edl_append_track_info(edl, track_info, entry->location, entry->index, entry->total_tracks, entry->name); } bg_album_update_entry(album, entry, track_info, 1, 1); plugin->close(album->com->load_handle->priv); bg_album_entry_changed(album, entry); return 1; } void bg_album_refresh_selected(bg_album_t * album) { bg_album_entry_t * cur; cur = album->entries; while(cur) { if(cur->flags & BG_ALBUM_ENTRY_SELECTED) refresh_entry(album, cur, NULL); cur = cur->next; } } bg_edl_t * bg_album_selected_to_edl(bg_album_t * album) { bg_edl_t * ret; bg_album_entry_t * cur; ret = bg_edl_create(); cur = album->entries; while(cur) { if(cur->flags & BG_ALBUM_ENTRY_SELECTED) refresh_entry(album, cur, ret); cur = cur->next; } return ret; } void bg_album_copy_selected_to_favourites(bg_album_t * a) { int was_open; bg_album_entry_t * sel; sel = copy_selected(a); if(!bg_album_is_open(a->com->favourites)) { bg_album_open(a->com->favourites); was_open = 0; } was_open = 1; bg_album_insert_entries_before(a->com->favourites, sel, NULL); if(!was_open) bg_album_close(a->com->favourites); } void bg_album_move_selected_to_favourites(bg_album_t * a) { int was_open; bg_album_entry_t * sel; sel = extract_selected(a); if(!bg_album_is_open(a->com->favourites)) { bg_album_open(a->com->favourites); was_open = 0; } was_open = 1; bg_album_insert_entries_before(a->com->favourites, sel, NULL); if(!was_open) bg_album_close(a->com->favourites); } const char * bg_album_get_disc_name(bg_album_t * a) { return a->disc_name; } char * bg_album_get_label(bg_album_t * a) { return a->disc_name ? a->disc_name : a->name; } int bg_album_can_eject(bg_album_t * a) { /* Leave this disabled until ejecting really works */ return !!(a->flags & BG_ALBUM_CAN_EJECT); // return 0; } void bg_album_eject(bg_album_t * a) { bg_input_plugin_t * plugin; bg_plugin_handle_t * handle; handle = bg_plugin_load(a->com->plugin_reg, a->plugin_info); plugin = (bg_input_plugin_t*)handle->plugin; if(!plugin->eject_disc(a->device)) bg_log(BG_LOG_ERROR, LOG_DOMAIN, "Ejecting disc failed"); bg_plugin_unref(handle); } char * bg_album_selected_to_string(bg_album_t * a) { char time_string[GAVL_TIME_STRING_LEN]; bg_album_entry_t * entry; char * ret = NULL; char * tmp_string; int index = 1; entry = a->entries; while(entry) { if(entry->flags & BG_ALBUM_ENTRY_SELECTED) { if(ret) ret = bg_strcat(ret, "\n"); gavl_time_prettyprint(entry->duration, time_string); tmp_string = bg_sprintf("%d.\t%s\t%s", index, entry->name, time_string); ret = bg_strcat(ret, tmp_string); free(tmp_string); } entry = entry->next; index++; } return ret; } void bg_album_select_entry(bg_album_t * a, int entry) { bg_album_entry_t * e; e = bg_album_get_entry(a, entry); e->flags |= BG_ALBUM_ENTRY_SELECTED; } void bg_album_unselect_entry(bg_album_t * a, int entry) { bg_album_entry_t * e; e = bg_album_get_entry(a, entry); e->flags &= ~BG_ALBUM_ENTRY_SELECTED; } void bg_album_unselect_all(bg_album_t * a) { bg_album_entry_t * e; e = a->entries; while(e) { e->flags &= ~BG_ALBUM_ENTRY_SELECTED; e = e->next; } } int bg_album_num_selected(bg_album_t * a) { bg_album_entry_t * e; int ret = 0; e = a->entries; while(e) { if(e->flags & BG_ALBUM_ENTRY_SELECTED) ret++; e = e->next; } return ret; } int bg_album_num_unsync(bg_album_t * a) { bg_album_entry_t * e; int ret = 0; e = a->entries; while(e) { if(!(e->flags & BG_ALBUM_ENTRY_SYNC)) ret++; e = e->next; } return ret; } int bg_album_entry_is_selected(bg_album_t * a, int entry) { bg_album_entry_t * e; e = bg_album_get_entry(a, entry); return !!(e->flags & BG_ALBUM_ENTRY_SELECTED); } void bg_album_toggle_select_entry(bg_album_t * a, int entry) { bg_album_entry_t * e; e = bg_album_get_entry(a, entry); if(e->flags & BG_ALBUM_ENTRY_SELECTED) e->flags &= ~BG_ALBUM_ENTRY_SELECTED; else e->flags |= BG_ALBUM_ENTRY_SELECTED; } void bg_album_select_entries(bg_album_t * a, int start, int end) { int i; int swp; bg_album_entry_t * e; if(end < start) { swp = end; end = start; start = swp; } e = bg_album_get_entry(a, start); for(i = start; i <= end; i++) { if(!e) { bg_log(BG_LOG_DEBUG, LOG_DOMAIN, "Invalid selection range given"); return; } e->flags |= BG_ALBUM_ENTRY_SELECTED; e = e->next; } } /********************************* * Seek support *********************************/ struct bg_album_seek_data_s { char * str; int ignore; int exact; int changed; struct { wchar_t * str; int len; int matched; } * substrings; int num_substrings; int substrings_alloc; int (*match_func)(const wchar_t *s1, const wchar_t *s2, size_t n); bg_charset_converter_t * cnv; }; bg_album_seek_data_t * bg_album_seek_data_create() { bg_album_seek_data_t * ret; ret = calloc(1, sizeof(*ret)); ret->cnv = bg_charset_converter_create("UTF-8", "WCHAR_T"); return ret; } void bg_album_seek_data_set_string(bg_album_seek_data_t * d, const char * str) { if(d->str && !strcmp(d->str, str)) return; d->str = bg_strdup(d->str, str); d->changed = 1; } void bg_album_seek_data_ignore_case(bg_album_seek_data_t * d, int ignore) { if(d->ignore == ignore) return; d->ignore = ignore; d->changed = 1; } void bg_album_seek_data_exact_string(bg_album_seek_data_t * d, int exact) { if(d->exact == exact) return; d->exact = exact; d->changed = 1; } static int match_string_ignore(const wchar_t *s1, const wchar_t *s2, size_t n) { int i; for(i = 0; i < n; i++) { if(!(*s1) || !(*s2) || (towlower(*s1) != towlower(*s2))) return 0; s1++; s2++; } return 1; } static int match_string(const wchar_t *s1, const wchar_t *s2, size_t n) { int i; for(i = 0; i < n; i++) { if(!(*s1) || !(*s2) || (*s1 != *s2)) return 0; s1++; s2++; } return 1; } static void update_seek_data(bg_album_seek_data_t * d) { int i; char ** substrings; char ** substrings_d = NULL; char * substrings_s[2]; if(d->exact) { d->num_substrings = 1; substrings_s[0] = d->str; substrings_s[1] = NULL; substrings = substrings_s; } else { substrings_d = bg_strbreak(d->str, ' '); d->num_substrings = 0; while(substrings_d[d->num_substrings]) d->num_substrings++; substrings = substrings_d; } if(d->num_substrings > d->substrings_alloc) { d->substrings = realloc(d->substrings, d->num_substrings * sizeof(*d->substrings)); memset(d->substrings + d->substrings_alloc, 0, sizeof(*d->substrings) * (d->num_substrings - d->substrings_alloc)); d->substrings_alloc = d->num_substrings; } for(i = 0; i < d->num_substrings; i++) { if(d->substrings[i].str) free(d->substrings[i].str); d->substrings[i].str = (wchar_t*)bg_convert_string(d->cnv, substrings[i], -1, &d->substrings[i].len); d->substrings[i].len /= sizeof(wchar_t); } if(d->ignore) d->match_func = match_string_ignore; else d->match_func = match_string; if(substrings_d) bg_strbreak_free(substrings_d); d->changed = 0; } static int entry_matches(bg_album_entry_t * entry, bg_album_seek_data_t * d) { int i, j, keep_going; wchar_t * ptr; if(d->changed) update_seek_data(d); if(!entry->name_w) { entry->name_w = (wchar_t*)bg_convert_string(d->cnv, entry->name, -1, &entry->len_w); entry->len_w /= sizeof(wchar_t); } ptr = entry->name_w; for(j = 0; j < d->num_substrings; j++) d->substrings[j].matched = 0; keep_going = 1; for(i = 0; i < entry->len_w-1; i++) { keep_going = 0; for(j = 0; j < d->num_substrings; j++) { if(!d->substrings[j].matched) d->substrings[j].matched = d->match_func(d->substrings[j].str, ptr, d->substrings[j].len); if(!d->substrings[j].matched) keep_going = 1; } if(!keep_going) break; ptr++; } if(keep_going) return 0; return 1; } bg_album_entry_t * bg_album_seek_entry_after(bg_album_t * a, bg_album_entry_t * e, bg_album_seek_data_t * d) { if(!e) e = a->entries; else e = e->next; while(e) { if(entry_matches(e, d)) return e; e = e->next; } return e; } bg_album_entry_t * bg_album_seek_entry_before(bg_album_t * a, bg_album_entry_t * e, bg_album_seek_data_t * d) { bg_album_entry_t * cur; bg_album_entry_t * match = NULL; if(!e) { e = a->entries; while(e->next) e = e->next; if(entry_matches(e, d)) return e; } cur = a->entries; while(1) { if(cur == e) return match; if(entry_matches(cur, d)) { if(cur->next == e) return cur; match = cur; } cur = cur->next; if(!cur) break; } return NULL; } void bg_album_seek_data_destroy(bg_album_seek_data_t * d) { int i; bg_charset_converter_destroy(d->cnv); if(d->str) free(d->str); for(i = 0; i < d->substrings_alloc; i++) { if(d->substrings[i].str) free(d->substrings[i].str); } if(d->substrings) free(d->substrings); free(d); } int bg_album_seek_data_changed(bg_album_seek_data_t * d) { return d->changed; } bg_album_entry_t * bg_album_entry_copy(bg_album_t * a, bg_album_entry_t * e) { bg_album_entry_t * ret; /* Also sets unique ID */ ret = bg_album_entry_create(); ret->name = bg_strdup(ret->name, e->name); ret->location = bg_strdup(ret->location, e->location); ret->plugin = bg_strdup(ret->plugin, e->plugin); ret->duration = e->duration; ret->num_audio_streams = e->num_audio_streams; ret->num_still_streams = e->num_still_streams; ret->num_video_streams = e->num_video_streams; ret->num_subtitle_streams = e->num_subtitle_streams; /* * Track index for multi track files/plugins */ ret->index = e->index; ret->total_tracks = e->total_tracks; /* Authentication data */ ret->username = bg_strdup(ret->username, e->username); ret->password = bg_strdup(ret->password, e->password); ret->flags = e->flags; /* Clear selected bit */ ret->flags &= ~(BG_ALBUM_ENTRY_SELECTED); /* The wchar stuff will be rebuilt on demand */ return ret; } void bg_album_set_watch_dir(bg_album_t * a, const char * dir) { char * pos; a->watch_dir = bg_strdup(a->watch_dir, dir); pos = a->watch_dir + strlen(a->watch_dir) - 1; if(*pos == '\n') *pos = '\0'; } gmerlin-1.2.0~dfsg/lib/player_thread.c0000644000175000017500000001530111764363410017633 0ustar alessioalessio/***************************************************************** * gmerlin - a general purpose multimedia framework and applications * * Copyright (c) 2001 - 2011 Members of the Gmerlin project * gmerlin-general@lists.sourceforge.net * http://gmerlin.sourceforge.net * * 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 of the License, 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 this program. If not, see . * *****************************************************************/ #include #include #include #include #define LOG_DOMAIN "player.thread" #include #include /* Binary semaphores: Like POSIX semaphores but the value can only be 1 or 0 */ typedef struct { int count; int nwaiting; pthread_mutex_t lock; pthread_cond_t cond; } bin_sem_t; static void bin_sem_init(bin_sem_t * s) { pthread_mutex_init(&s->lock, NULL); pthread_cond_init(&s->cond, NULL); } static void bin_sem_destroy(bin_sem_t * s) { pthread_mutex_destroy(&s->lock); pthread_cond_destroy(&s->cond); } static void bin_sem_wait(bin_sem_t * s) { pthread_mutex_lock(&s->lock); if(!s->count) { s->nwaiting++; pthread_cond_wait(&s->cond, &s->lock); s->nwaiting--; } s->count = 0; pthread_mutex_unlock(&s->lock); } static void bin_sem_post(bin_sem_t * s) { pthread_mutex_lock(&s->lock); s->count = 1; if(s->nwaiting) pthread_cond_broadcast(&s->cond); pthread_mutex_unlock(&s->lock); } static void bin_sem_reset(bin_sem_t * s) { pthread_mutex_lock(&s->lock); s->count = 0; pthread_mutex_unlock(&s->lock); } struct bg_player_thread_common_s { pthread_cond_t start_cond; pthread_mutex_t start_mutex; }; struct bg_player_thread_s { bg_player_thread_common_t * com; pthread_t thread; bin_sem_t sem; void * (*func)(void*); void * arg; int do_stop; int do_pause; pthread_mutex_t mutex; }; bg_player_thread_common_t * bg_player_thread_common_create() { bg_player_thread_common_t * com = calloc(1, sizeof(*com)); pthread_cond_init(&com->start_cond, NULL); pthread_mutex_init(&com->start_mutex, NULL); return com; } void bg_player_thread_common_destroy(bg_player_thread_common_t * com) { pthread_cond_destroy(&com->start_cond); pthread_mutex_destroy(&com->start_mutex); free(com); } bg_player_thread_t * bg_player_thread_create(bg_player_thread_common_t * com) { bg_player_thread_t * th = calloc(1, sizeof(*th)); th->com = com; bin_sem_init(&th->sem); pthread_mutex_init(&th->mutex, NULL); return th; } void bg_player_thread_destroy(bg_player_thread_t * th) { bin_sem_destroy(&th->sem); pthread_mutex_destroy(&th->mutex); free(th); } void bg_player_thread_set_func(bg_player_thread_t * th, void * (*func)(void*), void * arg) { th->func = func; th->arg = arg; th->do_pause = 0; th->do_stop = 0; } void bg_player_threads_init(bg_player_thread_t ** th, int num) { int i; for(i = 0; i < num; i++) { if(th[i]->func) { // fprintf(stderr, "Starting thread...\n"); pthread_create(&th[i]->thread, NULL, th[i]->func, th[i]->arg); // fprintf(stderr, "Starting thread done\n"); } } /* Wait until all threads are started */ for(i = 0; i < num; i++) { if(th[i]->func) { // fprintf(stderr, "Sem wait..."); bin_sem_wait(&th[i]->sem); // fprintf(stderr, "done ret: %d, val: %d\n", ret, val); } } } void bg_player_threads_start(bg_player_thread_t ** th, int num) { int i; /* Lock the global mutex. This will succeed after all threads wait for the start condition */ pthread_mutex_lock(&th[0]->com->start_mutex); pthread_cond_broadcast(&th[0]->com->start_cond); pthread_mutex_unlock(&th[0]->com->start_mutex); /* Wait until all threads woke up */ for(i = 0; i < num; i++) { if(th[i]->func) { // fprintf(stderr, "Sem wait..."); bin_sem_wait(&th[i]->sem); // fprintf(stderr, "done ret: %d, val: %d\n", ret, val); } } } void bg_player_threads_pause(bg_player_thread_t ** th, int num) { int i; /* Set pause flag */ for(i = 0; i < num; i++) { if(th[i]->func) { pthread_mutex_lock(&th[i]->mutex); th[i]->do_pause = 1; pthread_mutex_unlock(&th[i]->mutex); } } /* Wait until all threads are paused */ for(i = 0; i < num; i++) { if(th[i]->func) bin_sem_wait(&th[i]->sem); } } void bg_player_threads_join(bg_player_thread_t ** th, int num) { int i; /* Set stop flag */ for(i = 0; i < num; i++) { if(th[i]->func) { pthread_mutex_lock(&th[i]->mutex); th[i]->do_stop = 1; pthread_mutex_unlock(&th[i]->mutex); } } /* Start the threads if they where paused. If not paused, this call does no harm */ bg_player_threads_start(th, num); for(i = 0; i < num; i++) { if(th[i]->func) { // fprintf(stderr, "Joining thread...\n"); pthread_join(th[i]->thread, NULL); // fprintf(stderr, "Joining thread done, sem\n"); bin_sem_reset(&th[i]->sem); // bin_sem_init(&th[i]->sem, 0, 0); } } } /* called from within the thread */ int bg_player_thread_wait_for_start(bg_player_thread_t * th) { int ret = 1; pthread_mutex_lock(&th->com->start_mutex); // fprintf(stderr, "Sem post...\n"); bin_sem_post(&th->sem); // fprintf(stderr, "Sem post done\n"); pthread_cond_wait(&th->com->start_cond, &th->com->start_mutex); pthread_mutex_unlock(&th->com->start_mutex); pthread_mutex_lock(&th->mutex); th->do_pause = 0; if(th->do_stop) ret = 0; pthread_mutex_unlock(&th->mutex); bin_sem_post(&th->sem); return ret; } int bg_player_thread_check(bg_player_thread_t * th) { int do_pause; pthread_mutex_lock(&th->mutex); if(th->do_stop) { pthread_mutex_unlock(&th->mutex); bin_sem_post(&th->sem); return 0; } do_pause = th->do_pause; pthread_mutex_unlock(&th->mutex); if(do_pause) { pthread_mutex_lock(&th->mutex); th->do_pause = 0; pthread_mutex_unlock(&th->mutex); return bg_player_thread_wait_for_start(th); } return 1; } gmerlin-1.2.0~dfsg/lib/formats.c0000644000175000017500000001506211764363410016467 0ustar alessioalessio/***************************************************************** * gmerlin - a general purpose multimedia framework and applications * * Copyright (c) 2001 - 2011 Members of the Gmerlin project * gmerlin-general@lists.sourceforge.net * http://gmerlin.sourceforge.net * * 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 of the License, 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 this program. If not, see . * *****************************************************************/ #include #include #include #include static char * get_dB(float val) { if(val == 0.0) return bg_strdup(NULL, TR("Zero")); else return bg_sprintf("%02f dB", val); } char * bg_audio_format_to_string(gavl_audio_format_t * f, int use_tabs) { const char * format; char * channel_order = NULL; char * center_level; char * rear_level; char * ret; int i; center_level = get_dB(f->center_level); rear_level = get_dB(f->rear_level); /* Create channel order string */ for(i = 0; i < f->num_channels; i++) { channel_order = bg_strcat(channel_order, TRD(gavl_channel_id_to_string(f->channel_locations[i]), NULL)); if(i < f->num_channels - 1) channel_order = bg_strcat(channel_order, ", "); } if(!use_tabs) format = TR("Channels: %d\nChannel order: %s\nSamplerate: %d\nSamples per frame: %d\nInterleave Mode: %s\nSample format: %s"); else format = TR("Channels:\t %d\nChannel order\t %s\nSamplerate:\t %d\nSamples per frame:\t %d\nInterleave Mode:\t %s\nSample format:\t %s"); ret = bg_sprintf(format, f->num_channels, channel_order, f->samplerate, f->samples_per_frame, TRD(gavl_interleave_mode_to_string(f->interleave_mode), NULL), TRD(gavl_sample_format_to_string(f->sample_format), NULL)); free(channel_order); free(center_level); free(rear_level); return ret; } char * bg_video_format_to_string(gavl_video_format_t * format, int use_tabs) { char * str, *ret; const char * s; if(!use_tabs) s = TR("Frame size: %d x %d\nImage size: %d x %d\nPixel size: %d x %d\nPixel format: %s\n"); else s = TR("Frame size:\t %d x %d\nImage size:\t %d x %d\nPixel size:\t %d x %d\nPixel format:\t %s\n"); ret = bg_sprintf(s, format->frame_width, format->frame_height, format->image_width, format->image_height, format->pixel_width, format->pixel_height, TRD(gavl_pixelformat_to_string(format->pixelformat), NULL)); if(format->framerate_mode == GAVL_FRAMERATE_STILL) { ret = bg_strcat(ret, TR("Still image\n")); } else if(!format->frame_duration && (format->framerate_mode == GAVL_FRAMERATE_VARIABLE)) { if(!use_tabs) s = TR("Framerate: Variable (timescale: %d)\n"); else s = TR("Framerate:\tVariable (timescale: %d)\n"); str = bg_sprintf(s, format->timescale); ret = bg_strcat(ret, str); free(str); } else { if(!use_tabs) s = TR("Framerate: %f fps [%d / %d]%s\n"); else s = TR("Framerate:\t%f fps [%d / %d]%s\n"); str = bg_sprintf(s, (float)(format->timescale)/((float)format->frame_duration), format->timescale, format->frame_duration, ((format->framerate_mode == GAVL_FRAMERATE_CONSTANT) ? TR(" (constant)") : TR(" (variable)"))); ret = bg_strcat(ret, str); free(str); } if(!use_tabs) s = TR("Interlace mode: %s"); else s = TR("Interlace mode:\t%s"); str = bg_sprintf(s, TRD(gavl_interlace_mode_to_string(format->interlace_mode), NULL)); ret = bg_strcat(ret, str); free(str); if(format->pixelformat == GAVL_YUV_420_P) { if(!use_tabs) s = TR("\nChroma placement: %s"); else s = TR("\nChroma placement:\t%s"); str = bg_sprintf(s, TRD(gavl_chroma_placement_to_string(format->chroma_placement), NULL)); ret = bg_strcat(ret, str); free(str); } if(format->timecode_format.int_framerate) { if(!use_tabs) s = TR("\nTimecode rate: %d"); else s = TR("\nTimecode rate:\t%d"); str = bg_sprintf(s, format->timecode_format.int_framerate); ret = bg_strcat(ret, str); free(str); if(format->timecode_format.flags) { if(!use_tabs) s = TR("\nTimecode flags: "); else s = TR("\nTimecode flags:\t"); ret = bg_strcat(ret, s); if(format->timecode_format.flags & GAVL_TIMECODE_DROP_FRAME) ret = bg_strcat(ret, TR("Drop ")); } } return ret; } /* * When gavl will be gettextized (probably never), the * following stuff must be removed */ // gavl_channel_id_t TRU("Unknown channel") TRU("Front C") TRU("Front L") TRU("Front R") TRU("Front CL") TRU("Front CR") TRU("Rear C") TRU("Rear L") TRU("Rear R") TRU("Side L") TRU("Side R") TRU("LFE") TRU("AUX") // gavl_sample_format_t TRU("Not specified") TRU("Unsigned 8 bit") TRU("Signed 8 bit") TRU("Unsigned 16 bit") TRU("Signed 16 bit") TRU("Signed 32 bit") TRU("Floating point") TRU("Double precision") // gavl_interleave_mode_t TRU("Not interleaved") TRU("Interleaved channel pairs") TRU("All channels interleaved") // gavl_interlace_mode_t TRU("None (Progressive)") TRU("Top field first") TRU("Bottom field first") TRU("Mixed") // gavl_chroma_placement_t TRU("MPEG-1/JPEG") TRU("MPEG-2") TRU("DV PAL") // gavl_pixelformat_t TRU("15 bpp RGB") TRU("15 bpp BGR") TRU("16 bpp RGB") TRU("16 bpp BGR") TRU("24 bpp RGB") TRU("24 bpp BGR") TRU("32 bpp RGB") TRU("32 bpp BGR") TRU("32 bpp RGBA") TRU("48 bpp RGB") TRU("64 bpp RGBA") TRU("Float RGB") TRU("Float RGBA") TRU("YUV 422 (YUY2)") TRU("YUV 422 (UYVY)") TRU("YUVA 4444") TRU("YUV 420 Planar") TRU("YUV 410 Planar") TRU("YUV 411 Planar") TRU("YUV 422 Planar") TRU("YUV 422 Planar (16 bit)") TRU("YUV 444 Planar") TRU("YUV 444 Planar (16 bit)") TRU("YUVJ 420 Planar") TRU("YUVJ 422 Planar") TRU("YUVJ 444 Planar") TRU("Undefined") gmerlin-1.2.0~dfsg/lib/fileformat.c0000644000175000017500000002274611764363410017153 0ustar alessioalessio/***************************************************************** * gmerlin - a general purpose multimedia framework and applications * * Copyright (c) 2001 - 2011 Members of the Gmerlin project * gmerlin-general@lists.sourceforge.net * http://gmerlin.sourceforge.net * * 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 of the License, 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 this program. If not, see . * *****************************************************************/ #include #include #include #include #include #include #include static int read_stdio(void * priv, uint8_t * data, int len) { FILE * f = priv; return fread(data, 1, len, f); } static int write_stdio(void * priv, const uint8_t * data, int len) { FILE * f = priv; return fwrite(data, 1, len, f); } static int64_t ftell_stdio(void * priv) { FILE * f = priv; return ftell(f); } static int64_t seek_stdio(void * priv, int64_t pos, int whence) { FILE * f = priv; fseek(f, pos, whence); return ftell(f); } static void close_stdio(void * priv) { FILE * f = priv; if(f) fclose(f); } int bg_f_io_open_stdio_read(bg_f_io_t * io, const char * filename) { FILE * f; f = fopen(filename, "r"); if(!f) return 0; io->data = f; io->read_callback = read_stdio; io->seek_callback = seek_stdio; io->ftell_callback = ftell_stdio; io->close_callback = close_stdio; return 1; } int bg_f_io_open_stdio_write(bg_f_io_t * io, const char * filename) { FILE * f; f = fopen(filename, "w"); if(!f) return 0; io->data = f; io->write_callback = write_stdio; io->seek_callback = seek_stdio; io->ftell_callback = ftell_stdio; io->close_callback = close_stdio; return 1; } void bg_f_io_close(bg_f_io_t * io) { if(io->close_callback) io->close_callback(io->data); if(io->buffer) free(io->buffer); } static void bg_f_io_buffer_alloc(bg_f_io_t * io, int len) { if(len <= io->buffer_alloc) return; io->buffer_alloc = len + 512; io->buffer = realloc(io->buffer, io->buffer_alloc); } static inline int read_32(bg_f_io_t * io, uint32_t * val) { uint8_t data[4]; if(io->read_callback(io->data, data, 4) < 4) return 0; *val = ((data[0] << 24) | (data[1] << 16) | (data[2] << 8) | data[3]); return 1; } static inline int read_64(bg_f_io_t * io, uint64_t * val) { uint8_t data[8]; if(io->read_callback(io->data, data, 8) < 8) return 0; *val = data[0]; *val <<= 8; *val |= data[1]; *val <<= 8; *val |= data[2]; *val <<= 8; *val |= data[3]; *val <<= 8; *val |= data[4]; *val <<= 8; *val |= data[5]; *val <<= 8; *val |= data[6]; *val <<= 8; *val |= data[7]; return 1; } static inline int write_32(bg_f_io_t * io, uint32_t val) { uint8_t data[4]; data[0] = (val & 0xff000000) >> 24; data[1] = (val & 0xff0000) >> 16; data[2] = (val & 0xff00) >> 8; data[3] = (val & 0xff); return io->write_callback(io->data, data, 4); } static inline int write_64(bg_f_io_t * io, uint64_t val) { uint8_t data[8]; data[0] = (val & 0xff00000000000000LL) >> 56; data[1] = (val & 0x00ff000000000000LL) >> 48; data[2] = (val & 0x0000ff0000000000LL) >> 40; data[3] = (val & 0x000000ff00000000LL) >> 32; data[4] = (val & 0x00000000ff000000LL) >> 24; data[5] = (val & 0x0000000000ff0000LL) >> 16; data[6] = (val & 0x000000000000ff00LL) >> 8; data[7] = (val & 0x00000000000000ffLL); return io->write_callback(io->data, data, 8); } int bg_f_chunk_read(bg_f_io_t * io, bg_f_chunk_t * ch) { ch->start = io->ftell_callback(io->data); if(!read_32(io, &ch->type) || !read_64(io, &ch->size)) return 0; return 1; } int bg_f_chunk_write_header(bg_f_io_t * io, bg_f_chunk_t * ch, bg_f_chunk_type_t type) { ch->type = type; ch->start = io->ftell_callback(io->data); if(!write_32(io, ch->type) || !write_64(io, ch->size)) return 0; return 1; } int bg_f_chunk_write_footer(bg_f_io_t * io, bg_f_chunk_t * ch) { int64_t end_pos = io->ftell_callback(io->data); io->seek_callback(io->data, ch->start + 4, SEEK_SET); ch->size = end_pos - ch->start - 12; if(!write_64(io, ch->size)) return 0; io->seek_callback(io->data, end_pos, SEEK_SET); return 1; } int bg_f_signature_read(bg_f_io_t * io, bg_f_chunk_t * ch, bg_f_signature_t * sig) { if(!read_32(io, &sig->type)) return 0; return 1; } int bg_f_signature_write(bg_f_io_t * io, bg_f_signature_t * sig) { bg_f_chunk_t ch; if(!bg_f_chunk_write_header(io, &ch, CHUNK_TYPE_SIGNATURE)) return 0; if(!write_32(io, sig->type)) return 0; if(!bg_f_chunk_write_footer(io, &ch)) return 0; return 1; } int bg_f_audio_format_read(bg_f_io_t * io, bg_f_chunk_t * ch, gavl_audio_format_t * f, int * big_endian) { bg_f_io_buffer_alloc(io, ch->size); if(io->read_callback(io->data, io->buffer, ch->size) < ch->size) return 0; bg_deserialize_audio_format(f, io->buffer, ch->size, big_endian); return 1; } int bg_f_audio_format_write(bg_f_io_t * io, const gavl_audio_format_t * f) { bg_f_chunk_t ch; int len; if(!bg_f_chunk_write_header(io, &ch, CHUNK_TYPE_AUDIO_FORMAT)) return 0; len = bg_serialize_audio_format(f, NULL, 0); bg_f_io_buffer_alloc(io, len); len = bg_serialize_audio_format(f, io->buffer, len); if(io->write_callback(io->data, io->buffer, len) < len) return 0; if(!bg_f_chunk_write_footer(io, &ch)) return 0; return 1; } int bg_f_video_format_read(bg_f_io_t * io, bg_f_chunk_t * ch, gavl_video_format_t * f, int * big_endian) { bg_f_io_buffer_alloc(io, ch->size); if(io->read_callback(io->data, io->buffer, ch->size) < ch->size) return 0; bg_deserialize_video_format(f, io->buffer, ch->size, big_endian); return 1; } int bg_f_video_format_write(bg_f_io_t * io, const gavl_video_format_t * f) { bg_f_chunk_t ch; int len; if(!bg_f_chunk_write_header(io, &ch, CHUNK_TYPE_VIDEO_FORMAT)) return 0; len = bg_serialize_video_format(f, NULL, 0); bg_f_io_buffer_alloc(io, len); len = bg_serialize_video_format(f, io->buffer, len); if(io->write_callback(io->data, io->buffer, len) < len) return 0; if(!bg_f_chunk_write_footer(io, &ch)) return 0; return 1; } int bg_f_audio_frame_read(bg_f_io_t * io, bg_f_chunk_t * ch, const gavl_audio_format_t * format, gavl_audio_frame_t * f, int big_endian, gavl_dsp_context_t * ctx) { int len; len = bg_serialize_audio_frame_header(format, f, NULL, 0); bg_f_io_buffer_alloc(io, len); if(io->read_callback(io->data, io->buffer, len) < len) return 0; bg_deserialize_audio_frame_header(format, f, io->buffer, len); return bg_deserialize_audio_frame(ctx, format, f, io->read_callback, io->data, big_endian); } int bg_f_audio_frame_write(bg_f_io_t * io, const gavl_audio_format_t * format, const gavl_audio_frame_t * f) { int len; bg_f_chunk_t ch; if(!bg_f_chunk_write_header(io, &ch, CHUNK_TYPE_AUDIO_FRAME)) return 0; len = bg_serialize_audio_frame_header(format, f, NULL, 0); bg_f_io_buffer_alloc(io, len); bg_serialize_audio_frame_header(format, f, io->buffer, len); if(io->write_callback(io->data, io->buffer, len) < len) return 0; if(!bg_serialize_audio_frame(format, f, io->write_callback, io->data)) return 0; if(!bg_f_chunk_write_footer(io, &ch)) return 0; return 1; } int bg_f_video_frame_read(bg_f_io_t * io, bg_f_chunk_t * ch, const gavl_video_format_t * format, gavl_video_frame_t * f, int big_endian, gavl_dsp_context_t * ctx) { int len; len = bg_serialize_video_frame_header(format, f, NULL, 0); bg_f_io_buffer_alloc(io, len); if(io->read_callback(io->data, io->buffer, len) < len) return 0; bg_deserialize_video_frame_header(format, f, io->buffer, len); return bg_deserialize_video_frame(ctx, format, f, io->read_callback, io->data, big_endian); } int bg_f_video_frame_write(bg_f_io_t * io, const gavl_video_format_t * format, const gavl_video_frame_t * f) { int len; bg_f_chunk_t ch; if(!bg_f_chunk_write_header(io, &ch, CHUNK_TYPE_VIDEO_FRAME)) return 0; len = bg_serialize_video_frame_header(format, f, NULL, 0); bg_f_io_buffer_alloc(io, len); bg_serialize_video_frame_header(format, f, io->buffer, len); if(io->write_callback(io->data, io->buffer, len) < len) return 0; if(!bg_serialize_video_frame(format, f, io->write_callback, io->data)) return 0; if(!bg_f_chunk_write_footer(io, &ch)) return 0; return 1; } gmerlin-1.2.0~dfsg/lib/remote.c0000644000175000017500000002641111764363410016307 0ustar alessioalessio/***************************************************************** * gmerlin - a general purpose multimedia framework and applications * * Copyright (c) 2001 - 2011 Members of the Gmerlin project * gmerlin-general@lists.sourceforge.net * http://gmerlin.sourceforge.net * * 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 of the License, 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 this program. If not, see . * *****************************************************************/ #include #include #ifdef HAVE_SYS_SELECT_H #include #else #include #include #endif #include #include #include #include #include #include /* For INADDR_ Macros */ #include #define LOG_DOMAIN_SERVER "remote.server" #define LOG_DOMAIN_CLIENT "remote.client" /* * Server */ typedef struct server_connection_s { int fd; int do_put_msg; struct server_connection_s * next; } server_connection_t; struct bg_remote_server_s { int fd; char * protocol_id; /* Configuration stuff */ int allow_remote; int listen_port; int max_connections; server_connection_t * connections; int do_reopen; bg_msg_t * msg; int last_read_fd; }; bg_remote_server_t * bg_remote_server_create(int listen_port, char * protocol_id) { bg_remote_server_t * ret; ret = calloc(1, sizeof(*ret)); ret->listen_port = listen_port; ret->protocol_id = bg_strdup(ret->protocol_id, protocol_id); ret->fd = -1; ret->msg = bg_msg_create(); return ret; } int bg_remote_server_init(bg_remote_server_t * s) { int flags = 0; if(!s->allow_remote) flags |= BG_SOCKET_LOOPBACK; s->fd = bg_listen_socket_create_inet(s->listen_port, s->max_connections, flags); if(s->fd < 0) { bg_log(BG_LOG_WARNING, LOG_DOMAIN_SERVER, "Setting up socket failed, this instance won't be reachable via remote"); return 0; } bg_log(BG_LOG_INFO, LOG_DOMAIN_SERVER, "Remote socket listening at port %d", s->listen_port); return 1; } static server_connection_t * add_connection(bg_remote_server_t * s, int fd) { int len; char ** strings = NULL; char * welcome_msg = NULL; char * buffer = NULL; int buffer_alloc = 0; server_connection_t * ret = NULL; if(!bg_socket_read_line(fd, &buffer, &buffer_alloc, 1)) { bg_log(BG_LOG_INFO, LOG_DOMAIN_SERVER, "Reading hello line failed"); goto fail; } strings = bg_strbreak(buffer, ' '); if(!strings[0] || strcmp(strings[0], s->protocol_id) || !strings[1] || strcmp(strings[1], VERSION) || !strings[2]) { bg_log(BG_LOG_INFO, LOG_DOMAIN_SERVER, "Protocol mismatch"); goto fail; } /* Write the answer message */ welcome_msg = bg_sprintf("%s %s\r\n", s->protocol_id, VERSION); len = strlen(welcome_msg); if(bg_socket_write_data(fd, (uint8_t*)welcome_msg, len) < len) goto fail; ret = calloc(1, sizeof(*ret)); ret->fd = fd; ret->do_put_msg = atoi(strings[2]); fail: if(buffer) free(buffer); if(welcome_msg) free(welcome_msg); if(strings) bg_strbreak_free(strings); if(!ret) close(fd); return ret; } static server_connection_t * remove_connection(server_connection_t * connections, server_connection_t * conn) { server_connection_t * before; if(conn == connections) { connections = connections->next; } else { before = connections; while(before->next != conn) before = before->next; before->next = conn->next; } close(conn->fd); free(conn); bg_log(BG_LOG_DEBUG, LOG_DOMAIN_SERVER, "Client connection closed"); return connections; } static void bg_remote_server_cleanup(bg_remote_server_t * s) { close(s->fd); s->fd = -1; while(s->connections) s->connections = remove_connection(s->connections, s->connections); } static void check_connections(bg_remote_server_t * s) { int new_fd; server_connection_t * conn; /* Check for new connections */ new_fd = bg_listen_socket_accept(s->fd); if(new_fd >= 0) { bg_log(BG_LOG_DEBUG, LOG_DOMAIN_SERVER, "New client connection"); conn = add_connection(s, new_fd); if(conn) { conn->next = s->connections; s->connections = conn; } } } static int select_socket(int fd, int milliseconds) { fd_set rset; struct timeval timeout; FD_ZERO (&rset); FD_SET (fd, &rset); timeout.tv_sec = milliseconds / 1000; timeout.tv_usec = (milliseconds % 1000) * 1000; if(select (fd+1, &rset, NULL, NULL, &timeout) > 0) return 1; return 0; } bg_msg_t * bg_remote_server_get_msg(bg_remote_server_t * s) { server_connection_t * conn, * tmp_conn; check_connections(s); if(!s->connections) return NULL; conn = s->connections; while(conn) { if(select_socket(conn->fd, 0)) { bg_msg_free(s->msg); if(bg_msg_read_socket(s->msg, conn->fd, -1)) { s->last_read_fd = conn->fd; return s->msg; } else /* Select said reading won't block but reading failed -> Client probably disconnected */ { tmp_conn = conn->next; s->connections = remove_connection(s->connections, conn); conn = tmp_conn; } } else conn = conn->next; } return NULL; } bg_msg_t * bg_remote_server_get_msg_write(bg_remote_server_t * s) { bg_msg_free(s->msg); return s->msg; } int bg_remote_server_done_msg_write(bg_remote_server_t * s) { /* Write message */ return bg_msg_write_socket(s->msg, s->last_read_fd); } void bg_remote_server_wait_close(bg_remote_server_t * s) { gavl_time_t delay_time = GAVL_TIME_SCALE/200; while(1) { bg_remote_server_get_msg(s); if(!s->connections) break; gavl_time_delay(&delay_time); } } void bg_remote_server_put_msg(bg_remote_server_t * s, bg_msg_t * m) { } void bg_remote_server_destroy(bg_remote_server_t * s) { while(s->connections) s->connections = remove_connection(s->connections, s->connections); if(s->protocol_id) free(s->protocol_id); if(s->fd >= 0) close(s->fd); if(s->msg) bg_msg_destroy(s->msg); free(s); } static const bg_parameter_info_t server_parameters[] = { { .name = "allow_remote", .long_name = TRS("Allow connections from other machines"), .type = BG_PARAMETER_CHECKBUTTON, .val_default = { .val_i = 0 }, }, { .name = "max_connections", .long_name = TRS("Maximum number of connections"), .type = BG_PARAMETER_INT, .val_min = { .val_i = 0 }, .val_max = { .val_i = 100 }, .val_default = { .val_i = 5 }, }, { /* End of parameters */ } }; const bg_parameter_info_t * bg_remote_server_get_parameters(bg_remote_server_t * s) { return server_parameters; } void bg_remote_server_set_parameter(void * data, const char * name, const bg_parameter_value_t * v) { bg_remote_server_t * s; s = (bg_remote_server_t *)data; if(!name) { if((s->fd < 0) && s->max_connections) s->do_reopen = 1; if(!s->max_connections) { s->do_reopen = 0; if(s->fd >= 0) bg_remote_server_cleanup(s); /* Close everything */ } else if(s->do_reopen) { if(s->fd >= 0) bg_remote_server_cleanup(s); /* Close everything */ bg_remote_server_init(s); } return; } else if(!strcmp(name, "allow_remote")) { if(s->allow_remote != v->val_i) s->do_reopen = 1; s->allow_remote = v->val_i; } else if(!strcmp(name, "max_connections")) s->max_connections = v->val_i; } /* Client */ struct bg_remote_client_s { int fd; char * protocol_id; int read_messages; bg_msg_t * msg; int milliseconds; /* Read and connect timeout */ }; bg_remote_client_t * bg_remote_client_create(const char * protocol_id, int read_messages) { bg_remote_client_t * ret; ret = calloc(1, sizeof(*ret)); ret->protocol_id = bg_strdup(ret->protocol_id, protocol_id); ret->read_messages = read_messages; ret->msg = bg_msg_create(); return ret; } void bg_remote_client_close(bg_remote_client_t * c) { close(c->fd); c->fd = -1; } int bg_remote_client_init(bg_remote_client_t * c, const char * host, int port, int milliseconds) { int ret = 0; char ** strings = NULL; int buffer_alloc = 0; char * buffer = NULL; int len; char * answer_message; bg_host_address_t * addr = bg_host_address_create(); c->milliseconds = milliseconds; if(!bg_host_address_set(addr, host, port, SOCK_STREAM)) goto fail; c->fd = bg_socket_connect_inet(addr, c->milliseconds); if(c->fd < 0) { bg_log(BG_LOG_ERROR, LOG_DOMAIN_CLIENT, "Connecting failed"); goto fail; } /* Send hello line */ answer_message = bg_sprintf("%s %s %s\r\n", c->protocol_id, VERSION, (c->read_messages ? "1" : "0")); len = strlen(answer_message); if(bg_socket_write_data(c->fd, (uint8_t*)answer_message, len) < len) { bg_log(BG_LOG_ERROR, LOG_DOMAIN_CLIENT, "Sending initialization string failed"); goto fail; } /* Read welcome message */ if(!bg_socket_read_line(c->fd, &buffer, &buffer_alloc, c->milliseconds)) { bg_log(BG_LOG_ERROR, LOG_DOMAIN_CLIENT, "Reading welcome line failed"); goto fail; } strings = bg_strbreak(buffer, ' '); if((!strings[0] || strcmp(strings[0], c->protocol_id)) || (!strings[1] || strcmp(strings[1], VERSION))) { bg_log(BG_LOG_ERROR, LOG_DOMAIN_CLIENT, "Protocol mismatch"); goto fail; } ret = 1; fail: if(strings) bg_strbreak_free(strings); bg_host_address_destroy(addr); return ret; } void bg_remote_client_destroy(bg_remote_client_t * c) { bg_msg_destroy(c->msg); if(c->protocol_id) free(c->protocol_id); if(c->fd >= 0) close(c->fd); free(c); } bg_msg_t * bg_remote_client_get_msg_write(bg_remote_client_t * c) { bg_msg_free(c->msg); return c->msg; } int bg_remote_client_done_msg_write(bg_remote_client_t * c) { /* Write message */ return bg_msg_write_socket(c->msg, c->fd); } bg_msg_t * bg_remote_client_get_msg_read(bg_remote_client_t * c) { if(select_socket(c->fd, 1000)) { bg_msg_free(c->msg); if(bg_msg_read_socket(c->msg, c->fd, -1)) return c->msg; } return NULL; } gmerlin-1.2.0~dfsg/lib/cfg_xml.c0000644000175000017500000002405111764363410016431 0ustar alessioalessio/***************************************************************** * gmerlin - a general purpose multimedia framework and applications * * Copyright (c) 2001 - 2011 Members of the Gmerlin project * gmerlin-general@lists.sourceforge.net * http://gmerlin.sourceforge.net * * 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 of the License, 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 this program. If not, see . * *****************************************************************/ #include #include // #include #include #include #include #include static void load_item(xmlDocPtr xml_doc, xmlNodePtr xml_item, bg_cfg_section_t * cfg_section) { char * tmp_type; char * tmp_string; char * start; bg_parameter_info_t info; bg_cfg_item_t * item; memset(&info, 0, sizeof(info)); tmp_type = BG_XML_GET_PROP(xml_item, "type"); info.name = BG_XML_GET_PROP(xml_item, "name"); if(!tmp_type || !info.name) { if(tmp_type) xmlFree(tmp_type); if(info.name) xmlFree(info.name); return; } /* Check for the type */ if(!strcmp(tmp_type, "int")) { info.type = BG_PARAMETER_INT; } else if(!strcmp(tmp_type, "float")) { info.type = BG_PARAMETER_FLOAT; } else if(!strcmp(tmp_type, "string")) { info.type = BG_PARAMETER_STRING; } else if(!strcmp(tmp_type, "string_hidden")) { info.type = BG_PARAMETER_STRING_HIDDEN; } else if(!strcmp(tmp_type, "color")) { info.type = BG_PARAMETER_COLOR_RGBA; } else if(!strcmp(tmp_type, "time")) { info.type = BG_PARAMETER_TIME; } else if(!strcmp(tmp_type, "pos")) { info.type = BG_PARAMETER_POSITION; } else { return; } /* Find the item */ item = bg_cfg_section_find_item(cfg_section, &info); tmp_string = (char*)xmlNodeListGetString(xml_doc, xml_item->children, 1); switch(item->type) { case BG_CFG_INT: sscanf(tmp_string, "%d", &item->value.val_i); break; case BG_CFG_TIME: sscanf(tmp_string, "%" PRId64, &item->value.val_time); break; case BG_CFG_FLOAT: sscanf(tmp_string, "%lf", &item->value.val_f); break; case BG_CFG_STRING: item->value.val_str = bg_strdup(item->value.val_str, tmp_string); break; case BG_CFG_STRING_HIDDEN: if(item->value.val_str) { free(item->value.val_str); item->value.val_str = NULL; } if(tmp_string && (*tmp_string != '\0')) item->value.val_str = bg_descramble_string(tmp_string); break; case BG_CFG_COLOR: start = tmp_string; sscanf(tmp_string, "%f %f %f %f", &item->value.val_color[0], &item->value.val_color[1], &item->value.val_color[2], &item->value.val_color[3]); break; case BG_CFG_POSITION: start = tmp_string; sscanf(tmp_string, "%lf %lf", &item->value.val_pos[0], &item->value.val_pos[1]); break; } if(tmp_string) xmlFree(tmp_string); if(info.name) xmlFree(info.name); if(tmp_type) xmlFree(tmp_type); } void bg_cfg_xml_2_section(xmlDocPtr xml_doc, xmlNodePtr xml_section, bg_cfg_section_t * cfg_section) { xmlNodePtr cur; char * tmp_string; bg_cfg_section_t * cfg_child_section; cur = xml_section->children; tmp_string = BG_XML_GET_PROP(xml_section, "gettext_domain"); if(tmp_string) { cfg_section->gettext_domain = bg_strdup(cfg_section->gettext_domain, tmp_string); xmlFree(tmp_string); } tmp_string = BG_XML_GET_PROP(xml_section, "gettext_directory"); if(tmp_string) { cfg_section->gettext_directory = bg_strdup(cfg_section->gettext_directory, tmp_string); xmlFree(tmp_string); } while(cur) { if(!cur->name) { cur = cur->next; continue; } /* Load items */ else if(!BG_XML_STRCMP(cur->name, "ITEM")) { load_item(xml_doc, cur, cfg_section); } /* Load child */ else if(!BG_XML_STRCMP(cur->name, "SECTION")) { tmp_string = BG_XML_GET_PROP(cur, "name"); if(tmp_string) { cfg_child_section = bg_cfg_section_find_subsection(cfg_section, tmp_string); bg_cfg_xml_2_section(xml_doc, cur, cfg_child_section); xmlFree(tmp_string); } } cur = cur->next; } } void bg_cfg_registry_load(bg_cfg_registry_t * r, const char * filename) { xmlDocPtr xml_doc; xmlNodePtr node; bg_cfg_section_t * cfg_section; char * tmp_string; if(!filename) return; xml_doc = bg_xml_parse_file(filename); if(!xml_doc) return; node = xml_doc->children; if(BG_XML_STRCMP(node->name, "REGISTRY")) { xmlFreeDoc(xml_doc); return; } node = node->children; while(node) { if(node->name && !BG_XML_STRCMP(node->name, "SECTION")) { tmp_string = BG_XML_GET_PROP(node, "name"); if(tmp_string) { cfg_section = bg_cfg_registry_find_section(r, tmp_string); bg_cfg_xml_2_section(xml_doc, node, cfg_section); xmlFree(tmp_string); } } node = node->next; } xmlFreeDoc(xml_doc); } void bg_cfg_section_2_xml(const bg_cfg_section_t * section, xmlNodePtr xml_section) { char * tmp_string; bg_cfg_item_t * item; bg_cfg_section_t * tmp_section; char buffer[1024]; xmlNodePtr xml_item, xml_child; /* Save items */ item = section->items; if(section->gettext_domain) BG_XML_SET_PROP(xml_section, "gettext_domain", section->gettext_domain); if(section->gettext_directory) BG_XML_SET_PROP(xml_section, "gettext_directory", section->gettext_directory); xmlAddChild(xml_section, BG_XML_NEW_TEXT("\n")); while(item) { xml_item = xmlNewTextChild(xml_section, NULL, (xmlChar*)"ITEM", NULL); BG_XML_SET_PROP(xml_item, "name", item->name); switch(item->type) { case BG_CFG_INT: BG_XML_SET_PROP(xml_item, "type", "int"); sprintf(buffer, "%d", item->value.val_i); xmlAddChild(xml_item, BG_XML_NEW_TEXT(buffer)); break; case BG_CFG_TIME: BG_XML_SET_PROP(xml_item, "type", "time"); sprintf(buffer, "%" PRId64, item->value.val_time); xmlAddChild(xml_item, BG_XML_NEW_TEXT(buffer)); break; case BG_CFG_FLOAT: BG_XML_SET_PROP(xml_item, "type", "float"); sprintf(buffer, "%.15e", item->value.val_f); xmlAddChild(xml_item, BG_XML_NEW_TEXT(buffer)); break; case BG_CFG_STRING: BG_XML_SET_PROP(xml_item, "type", "string"); /* Yes, that's stupid */ if(item->value.val_str) xmlAddChild(xml_item, BG_XML_NEW_TEXT(item->value.val_str)); break; case BG_CFG_STRING_HIDDEN: BG_XML_SET_PROP(xml_item, "type", "string_hidden"); /* Yes, that's stupid */ if(item->value.val_str) { tmp_string = bg_scramble_string(item->value.val_str); xmlAddChild(xml_item, BG_XML_NEW_TEXT(tmp_string)); free(tmp_string); } break; case BG_CFG_COLOR: BG_XML_SET_PROP(xml_item, "type", "color"); sprintf(buffer, "%f %f %f %f", item->value.val_color[0], item->value.val_color[1], item->value.val_color[2], item->value.val_color[3]); xmlAddChild(xml_item, BG_XML_NEW_TEXT(buffer)); break; case BG_CFG_POSITION: BG_XML_SET_PROP(xml_item, "type", "pos"); sprintf(buffer, "%f %f", item->value.val_pos[0], item->value.val_pos[1]); xmlAddChild(xml_item, BG_XML_NEW_TEXT(buffer)); break; } xmlAddChild(xml_section, BG_XML_NEW_TEXT("\n")); item = item->next; } /* Save child sections */ tmp_section = section->children; while(tmp_section) { xml_child = xmlNewTextChild(xml_section, NULL, (xmlChar*)"SECTION", NULL); BG_XML_SET_PROP(xml_child, "name", tmp_section->name); bg_cfg_section_2_xml(tmp_section, xml_child); xmlAddChild(xml_section, BG_XML_NEW_TEXT("\n")); tmp_section = tmp_section->next; } } void bg_cfg_registry_save(bg_cfg_registry_t * r, const char * filename) { xmlDocPtr xml_doc; xmlNodePtr xml_registry, xml_section; bg_cfg_section_t * tmp_section; if(!filename) return; xml_doc = xmlNewDoc((xmlChar*)"1.0"); xml_registry = xmlNewDocRawNode(xml_doc, NULL, (xmlChar*)"REGISTRY", NULL); xmlDocSetRootElement(xml_doc, xml_registry); xmlAddChild(xml_registry, BG_XML_NEW_TEXT("\n")); tmp_section = r->sections; while(tmp_section) { xml_section = xmlNewTextChild(xml_registry, NULL, (xmlChar*)"SECTION", NULL); BG_XML_SET_PROP(xml_section, "name", tmp_section->name); bg_cfg_section_2_xml(tmp_section, xml_section); tmp_section = tmp_section->next; xmlAddChild(xml_registry, BG_XML_NEW_TEXT("\n")); } xmlSaveFile(filename, xml_doc); xmlFreeDoc(xml_doc); } void bg_cfg_section_dump(bg_cfg_section_t * section, const char * filename) { xmlDocPtr xml_doc; xmlNodePtr xml_section; xml_doc = xmlNewDoc((xmlChar*)"1.0"); xml_section = xmlNewDocRawNode(xml_doc, NULL, (xmlChar*)"SECTION", NULL); xmlDocSetRootElement(xml_doc, xml_section); BG_XML_SET_PROP(xml_section, "name", section->name); bg_cfg_section_2_xml(section, xml_section); xmlSaveFile(filename, xml_doc); xmlFreeDoc(xml_doc); } gmerlin-1.2.0~dfsg/lib/gtk/0000755000175000017500000000000011764363442015436 5ustar alessioalessiogmerlin-1.2.0~dfsg/lib/gtk/textview.c0000644000175000017500000001416511764363406017470 0ustar alessioalessio/***************************************************************** * gmerlin - a general purpose multimedia framework and applications * * Copyright (c) 2001 - 2011 Members of the Gmerlin project * gmerlin-general@lists.sourceforge.net * http://gmerlin.sourceforge.net * * 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 of the License, 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 this program. If not, see . * *****************************************************************/ #include #include #include #include #include /* Font stuff */ static GtkTextTag * text_tag = NULL; static GtkTextTagTable * tag_table = NULL; struct bg_gtk_textview_s { GtkWidget * textview; GtkTextBuffer * buffer; }; static void set_bg(GtkWidget * widget, gpointer data) { GtkRcStyle *rc_style; rc_style = gtk_rc_style_new (); rc_style->color_flags[GTK_STATE_NORMAL] = GTK_RC_BASE; #if 1 rc_style->base[GTK_STATE_NORMAL].red = widget->style->bg[GTK_STATE_NORMAL].red; rc_style->base[GTK_STATE_NORMAL].green = widget->style->bg[GTK_STATE_NORMAL].green; rc_style->base[GTK_STATE_NORMAL].blue = widget->style->bg[GTK_STATE_NORMAL].blue; rc_style->base[GTK_STATE_NORMAL].pixel = widget->style->bg[GTK_STATE_NORMAL].pixel; #endif gtk_widget_modify_style(widget, rc_style); #if GTK_MINOR_VERSION >= 12 g_object_unref (rc_style); #else gtk_rc_style_unref (rc_style); #endif } bg_gtk_textview_t * bg_gtk_textview_create() { bg_gtk_textview_t * t; t = calloc(1, sizeof(*t)); if(!tag_table) { tag_table = gtk_text_tag_table_new(); text_tag = gtk_text_tag_new("Font"); g_object_set(text_tag, "editable", 0, NULL); gtk_text_tag_table_add(tag_table, text_tag); } t->buffer = gtk_text_buffer_new(tag_table); t->textview = gtk_text_view_new_with_buffer(t->buffer); g_signal_connect(G_OBJECT(t->textview), "realize", G_CALLBACK(set_bg), NULL); gtk_text_view_set_cursor_visible(GTK_TEXT_VIEW(t->textview), FALSE); gtk_text_view_set_wrap_mode(GTK_TEXT_VIEW(t->textview), GTK_WRAP_NONE); gtk_text_view_set_editable(GTK_TEXT_VIEW(t->textview), 0); gtk_widget_show(t->textview); return t; } void bg_gtk_textview_destroy(bg_gtk_textview_t * t) { g_object_unref(t->buffer); free(t); } void bg_gtk_textview_update(bg_gtk_textview_t * t, const char * text) { const char * next_tab; const char * pos; const char * end_pos; int line; int tab_pos; int line_width; int i; PangoTabArray * tab_array; GtkTextIter start_iter; GtkTextIter end_iter; GdkRectangle start_rect; GdkRectangle end_rect; pos = text; next_tab = strchr(pos, '\t'); /* No tabs here, just copy the text */ if(!next_tab) { gtk_text_view_set_wrap_mode(GTK_TEXT_VIEW(t->textview), GTK_WRAP_WORD); gtk_text_buffer_set_text(t->buffer, text, -1); } else /* This is the complicated version */ { line = 0; tab_pos = 0; while(1) { next_tab = strchr(pos, '\t'); end_pos = strchr(pos, '\n'); if(!end_pos) end_pos = pos + strlen(pos); if(next_tab > end_pos) next_tab = NULL; /* Insert everything before the tab and calculate width */ gtk_text_buffer_get_end_iter(t->buffer, &end_iter); if(!next_tab) { gtk_text_buffer_insert(t->buffer, &end_iter, pos, (int)(end_pos - pos)); } else { gtk_text_buffer_insert(t->buffer, &end_iter, pos, (int)(next_tab - pos)); } gtk_text_buffer_get_bounds(t->buffer, &start_iter, &end_iter); for(i = 0; i < line; i++) { gtk_text_view_forward_display_line(GTK_TEXT_VIEW(t->textview), &start_iter); } gtk_text_view_get_iter_location(GTK_TEXT_VIEW(t->textview), &start_iter, &start_rect); gtk_text_view_get_iter_location(GTK_TEXT_VIEW(t->textview), &end_iter, &end_rect); line_width = end_rect.x + end_rect.width; if(tab_pos < line_width) tab_pos = line_width; /* Insert everything after the tab */ if(next_tab) { gtk_text_buffer_get_end_iter(t->buffer, &end_iter); gtk_text_buffer_insert(t->buffer, &end_iter, next_tab, (int)(end_pos - next_tab)); } pos = end_pos; line++; if(*pos == '\0') break; else { while(*pos == '\n') { gtk_text_buffer_get_end_iter(t->buffer, &end_iter); gtk_text_buffer_insert(t->buffer, &end_iter, pos, 1); pos++; } } } /* Set the tab positions */ tab_array = pango_tab_array_new_with_positions(1, /* gint size, */ 1, /* gboolean positions_in_pixels, */ PANGO_TAB_LEFT, /* PangoTabAlign first_alignment, */ tab_pos+10 /* gint first_position, */ ); gtk_text_view_set_tabs(GTK_TEXT_VIEW(t->textview), tab_array); pango_tab_array_free(tab_array); } gtk_text_buffer_get_bounds(t->buffer, &start_iter, &end_iter); gtk_text_buffer_apply_tag(t->buffer, text_tag, &start_iter, &end_iter); }; GtkWidget * bg_gtk_textview_get_widget(bg_gtk_textview_t * t) { return t->textview; } gmerlin-1.2.0~dfsg/lib/gtk/Makefile.am0000644000175000017500000000231511764363406017473 0ustar alessioalessioplugindir=$(pkglibdir)/plugins INCLUDES = -I$(top_srcdir)/include AM_CFLAGS = \ @GTK_CFLAGS@ \ @FREETYPE_CFLAGS@ \ @FONTCONFIG_CFLAGS@ \ -DLOCALE_DIR=\"$(localedir)\" \ -DPLUGIN_DIR=\"$(plugindir)\" \ -DDOC_DIR=\"$(docdir)\" \ -DDATA_DIR=\"$(pkgdatadir)\" libgmerlin_gtk_la_LDFLAGS = -version-info @LTVERSION_CURRENT@:@LTVERSION_REVISION@:@LTVERSION_AGE@ lib_LTLIBRARIES = libgmerlin_gtk.la noinst_HEADERS = gtk_dialog.h libgmerlin_gtk_la_SOURCES = \ aboutwindow.c \ albumentry.c \ albumwidget.c \ albumwindow.c \ auth.c \ button.c \ cfg_button.c \ cfg_checkbutton.c \ cfg_color.c \ cfg_device.c \ cfg_dialog.c \ cfg_file.c \ cfg_font.c \ cfg_multi_list.c \ cfg_multi_menu.c \ cfg_position.c \ cfg_slider.c \ cfg_spinbutton.c \ cfg_string.c \ cfg_stringlist.c \ cfg_time.c \ chapterdialog.c \ display.c \ driveselect.c \ fileselect.c \ fileentry.c \ gtkutils.c \ infowindow.c \ logwindow.c \ message.c \ multiinfo.c \ plugininfo.c \ plugin_multi.c \ plugin_single.c \ pluginmenu.c \ presetmenu.c \ question.c \ slider.c \ scrolltext.c \ textview.c \ textwindow.c \ treewidget.c \ treewindow.c \ urllink.c \ urlselect.c \ vumeter.c libgmerlin_gtk_la_LIBADD = @GTK_LIBS@ $(top_builddir)/lib/libgmerlin.la @XML2_LIBS@ @LIBM@ gmerlin-1.2.0~dfsg/lib/gtk/treewindow.c0000644000175000017500000001403711764363406017776 0ustar alessioalessio/***************************************************************** * gmerlin - a general purpose multimedia framework and applications * * Copyright (c) 2001 - 2011 Members of the Gmerlin project * gmerlin-general@lists.sourceforge.net * http://gmerlin.sourceforge.net * * 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 of the License, 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 this program. If not, see . * *****************************************************************/ #include #include #include #include #include #include #include extern void gtk_decorated_window_move_resize_window(GtkWindow*,int, int, int, int); struct bg_gtk_tree_window_s { bg_gtk_tree_widget_t * widget; GtkWidget * window; void (*close_callback)(bg_gtk_tree_window_t*,void*); void * close_callback_data; /* Configuration stuff */ bg_cfg_section_t * cfg_section; int x, y, width, height; }; /* Configuration stuff */ static const bg_parameter_info_t parameters[] = { { .name = "x", .long_name = "X", .type = BG_PARAMETER_INT, .val_default = { .val_i = 100 } }, { .name = "y", .long_name = "Y", .type = BG_PARAMETER_INT, .val_default = { .val_i = 100 } }, { .name = "width", .long_name = "Width", .type = BG_PARAMETER_INT, .val_default = { .val_i = 200 } }, { .name = "height", .long_name = "Height", .type = BG_PARAMETER_INT, .val_default = { .val_i = 300 } }, { /* End of parameters */ } }; static void set_parameter(void * data, const char * name, const bg_parameter_value_t * val) { bg_gtk_tree_window_t * win; win = (bg_gtk_tree_window_t*)data; if(!name) return; else if(!strcmp(name, "x")) { win->x = val->val_i; } else if(!strcmp(name, "y")) { win->y = val->val_i; } else if(!strcmp(name, "width")) { win->width = val->val_i; } else if(!strcmp(name, "height")) { win->height = val->val_i; } } static int get_parameter(void * data, const char * name, bg_parameter_value_t * val) { bg_gtk_tree_window_t * win; win = (bg_gtk_tree_window_t*)data; if(!name) return 1; else if(!strcmp(name, "x")) { val->val_i = win->x; return 1; } else if(!strcmp(name, "y")) { val->val_i = win->y; return 1; } else if(!strcmp(name, "width")) { val->val_i = win->width; return 1; } else if(!strcmp(name, "height")) { val->val_i = win->height; return 1; } return 0; } static gboolean delete_callback(GtkWidget * w, GdkEventAny * event, gpointer data) { bg_gtk_tree_window_t * win; win = (bg_gtk_tree_window_t*)data; if(win->close_callback) win->close_callback(win, win->close_callback_data); bg_gtk_tree_window_hide(win); return TRUE; } bg_gtk_tree_window_t * bg_gtk_tree_window_create(bg_media_tree_t * tree, void (*close_callback)(bg_gtk_tree_window_t*,void*), void * close_callback_data, GtkAccelGroup * accel_group) { bg_gtk_tree_window_t * ret = calloc(1, sizeof(*ret)); ret->cfg_section = bg_cfg_section_find_subsection(bg_media_tree_get_cfg_section(tree), "gtk_treewindow"); ret->window = bg_gtk_window_new(GTK_WINDOW_TOPLEVEL); gtk_window_add_accel_group(GTK_WINDOW(ret->window), accel_group); ret->widget = bg_gtk_tree_widget_create(tree, accel_group, ret->window); ret->close_callback = close_callback; ret->close_callback_data = close_callback_data; g_signal_connect(G_OBJECT(ret->window), "delete-event", G_CALLBACK(delete_callback), ret); gtk_container_add(GTK_CONTAINER(ret->window), bg_gtk_tree_widget_get_widget(ret->widget)); gtk_window_set_title(GTK_WINDOW(ret->window), TR("Gmerlin Media Tree")); return ret; } void bg_gtk_tree_window_destroy(bg_gtk_tree_window_t * w) { bg_gtk_tree_widget_destroy(w->widget); gtk_widget_hide(w->window); gtk_widget_destroy(w->window); free(w); } void bg_gtk_tree_window_show(bg_gtk_tree_window_t* w) { gtk_widget_show(w->window); // gtk_window_present(GTK_WINDOW(w->window)); bg_cfg_section_apply(w->cfg_section, parameters, set_parameter, w); if((w->width > 0) && (w->height > 0)) { gtk_decorated_window_move_resize_window(GTK_WINDOW(w->window), w->x, w->y, w->width, w->height); } } void bg_gtk_tree_window_hide(bg_gtk_tree_window_t* w) { if(w->window->window) { gdk_window_get_geometry(w->window->window, NULL, NULL, &w->width, &w->height, NULL); gdk_window_get_root_origin(w->window->window, &w->x, &w->y); bg_cfg_section_get(w->cfg_section, parameters, get_parameter, w); } gtk_widget_hide(w->window); } void bg_gtk_tree_window_open_incoming(bg_gtk_tree_window_t * win) { bg_gtk_tree_widget_open_incoming(win->widget); } void bg_gtk_tree_window_goto_current(bg_gtk_tree_window_t * win) { bg_gtk_tree_widget_goto_current(win->widget); } void bg_gtk_tree_window_update(bg_gtk_tree_window_t * w, int open_albums) { bg_gtk_tree_widget_update(w->widget, open_albums); } gmerlin-1.2.0~dfsg/lib/gtk/presetmenu.c0000644000175000017500000002374411764363406020003 0ustar alessioalessio/***************************************************************** * gmerlin - a general purpose multimedia framework and applications * * Copyright (c) 2001 - 2011 Members of the Gmerlin project * gmerlin-general@lists.sourceforge.net * http://gmerlin.sourceforge.net * * 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 of the License, 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 this program. If not, see . * *****************************************************************/ #include #include #include #include #include #include #include #include #include #include #include typedef struct { GtkWidget * menu; GtkWidget ** preset_items; int num_preset_items; int preset_items_alloc; } preset_menu_t; struct bg_gtk_preset_menu_s { GtkWidget * menubar; GtkWidget * menu; GtkWidget * save_item; GtkWidget * load_item; GtkWidget * delete_item; GtkWidget * save_to_item; char * path; void (*load_cb)(void*); void (*save_cb)(void*); void * cb_data; char * preset_name; preset_menu_t load_menu; preset_menu_t save_to_menu; preset_menu_t delete_menu; bg_cfg_section_t * section; bg_preset_t * presets; }; static void menu_callback(GtkWidget * w, gpointer data); static void set_name_parameter(void * data, const char * name, const bg_parameter_value_t * val) { bg_gtk_preset_menu_t * menu = data; if(!name) return; if(!strcmp(name, "name")) menu->preset_name = bg_strdup(menu->preset_name, val->val_str); } static void do_update_menu(preset_menu_t * menu, bg_preset_t * presets, void * callback_data) { bg_preset_t * tmp; int i; // Count presets menu->num_preset_items = 0; tmp = presets; while(tmp) { menu->num_preset_items++; tmp = tmp->next; } if(menu->num_preset_items > menu->preset_items_alloc) { // Create preset items int old_alloc = menu->preset_items_alloc; menu->preset_items_alloc = menu->num_preset_items + 4; menu->preset_items = realloc(menu->preset_items, menu->preset_items_alloc * sizeof(*menu->preset_items)); for(i = old_alloc; i < menu->preset_items_alloc; i++) { menu->preset_items[i] = gtk_menu_item_new_with_label(""); g_signal_connect(G_OBJECT(menu->preset_items[i]), "activate", G_CALLBACK(menu_callback), (gpointer)callback_data); gtk_menu_shell_append(GTK_MENU_SHELL(menu->menu), menu->preset_items[i]); } } tmp = presets; for(i = 0; i < menu->num_preset_items; i++) { gtk_label_set_text(GTK_LABEL(gtk_bin_get_child(GTK_BIN(menu->preset_items[i]))), tmp->name); gtk_widget_show(menu->preset_items[i]); tmp = tmp->next; } for(i = menu->num_preset_items; i < menu->preset_items_alloc; i++) { gtk_widget_hide(menu->preset_items[i]); } } static void update_menu(bg_gtk_preset_menu_t * menu) { do_update_menu(&menu->load_menu, menu->presets, menu); do_update_menu(&menu->save_to_menu, menu->presets, menu); do_update_menu(&menu->delete_menu, menu->presets, menu); } static bg_preset_t * has_preset_widget(preset_menu_t * menu, GtkWidget * w, bg_preset_t * presets) { int i, index; bg_preset_t * ret; for(i = 0; i < menu->num_preset_items; i++) { if(w == menu->preset_items[i]) break; } if(i >= menu->num_preset_items) return NULL; index = i; ret = presets; for(i = 0; i < index; i++) ret = ret->next; return ret; } static void menu_callback(GtkWidget * w, gpointer data) { bg_gtk_preset_menu_t * menu = data; bg_preset_t * p; if(w == menu->save_item) { bg_parameter_info_t pi[2]; bg_dialog_t * dlg; if(menu->save_cb) menu->save_cb(menu->cb_data); memset(pi, 0, sizeof(pi)); pi[0].name = "name"; pi[0].long_name = TR("Name"); pi[0].type = BG_PARAMETER_STRING; pi[0].val_default.val_str = TR("New preset"); dlg = bg_dialog_create(NULL, set_name_parameter, NULL, menu, pi, TR("Save preset")); if(!bg_dialog_show(dlg, menu->menubar)) return; if(!menu->preset_name) return; if(bg_preset_find_by_name(menu->presets, menu->preset_name)) { char * question = bg_sprintf("Overwrite preset %s?", menu->preset_name); if(!bg_gtk_question(question, menu->menubar)) { free(question); return; } free(question); } menu->presets = bg_preset_add(menu->presets, menu->path, menu->preset_name, menu->section); update_menu(menu); } else if ((p = has_preset_widget(&menu->load_menu, w, menu->presets))) { bg_cfg_section_t * preset_section; preset_section = bg_preset_load(p); bg_cfg_section_transfer(preset_section, menu->section); if(menu->load_cb) menu->load_cb(menu->cb_data); bg_cfg_section_destroy(preset_section); } else if ((p = has_preset_widget(&menu->delete_menu, w, menu->presets))) { char * question = bg_sprintf("Delete preset %s?", p->name); if(!bg_gtk_question(question, menu->menubar)) { free(question); return; } free(question); menu->presets = bg_preset_delete(menu->presets, p); update_menu(menu); } else if ((p = has_preset_widget(&menu->save_to_menu, w, menu->presets))) { char * question = bg_sprintf("Overwrite preset %s?", p->name); if(!bg_gtk_question(question, menu->menubar)) { free(question); return; } free(question); if(menu->save_cb) menu->save_cb(menu->cb_data); menu->presets = bg_preset_add(menu->presets, menu->path, p->name, menu->section); } } static GtkWidget * create_item(bg_gtk_preset_menu_t * w, GtkWidget * parent, const char * label, const char * pixmap) { GtkWidget * ret, *image; char * path; if(pixmap) { path = bg_search_file_read("icons", pixmap); if(path) { image = gtk_image_new_from_file(path); free(path); } else image = gtk_image_new(); gtk_widget_show(image); ret = gtk_image_menu_item_new_with_label(label); gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(ret), image); } else { ret = gtk_menu_item_new_with_label(label); } g_signal_connect(G_OBJECT(ret), "activate", G_CALLBACK(menu_callback), (gpointer)w); gtk_widget_show(ret); gtk_menu_shell_append(GTK_MENU_SHELL(parent), ret); return ret; } static void init_preset_menu(preset_menu_t * menu) { menu->menu = gtk_menu_new(); gtk_widget_show(menu->menu); } bg_gtk_preset_menu_t * bg_gtk_preset_menu_create(const char * preset_path, bg_cfg_section_t * s, void (*load_cb)(void *), void (*save_cb)(void *), void * cb_data) { GtkWidget * item; bg_gtk_preset_menu_t * ret = calloc(1, sizeof(*ret)); ret->load_cb = load_cb; ret->save_cb = save_cb; ret->cb_data = cb_data; ret->path = bg_strdup(ret->path, preset_path); ret->presets = bg_presets_load(ret->path); ret->section = s; ret->menu = gtk_menu_new(); init_preset_menu(&ret->load_menu); init_preset_menu(&ret->save_to_menu); init_preset_menu(&ret->delete_menu); ret->save_item = create_item(ret, ret->menu, TR("Save new..."), "save_16.png"); ret->load_item = create_item(ret, ret->menu, TR("Load..."), "folder_open_16.png"); gtk_menu_item_set_submenu(GTK_MENU_ITEM(ret->load_item), ret->load_menu.menu); ret->save_to_item = create_item(ret, ret->menu, TR("Save to..."), "save_16.png"); gtk_menu_item_set_submenu(GTK_MENU_ITEM(ret->save_to_item), ret->save_to_menu.menu); ret->delete_item = create_item(ret, ret->menu, TR("Delete..."), "trash_16.png"); gtk_menu_item_set_submenu(GTK_MENU_ITEM(ret->delete_item), ret->delete_menu.menu); item = gtk_separator_menu_item_new(); gtk_widget_show(item); gtk_menu_shell_append(GTK_MENU_SHELL(ret->menu), item); ret->menubar = gtk_menu_bar_new(); item = gtk_menu_item_new_with_label(TR("Preset")); gtk_menu_item_set_submenu(GTK_MENU_ITEM(item), ret->menu); gtk_widget_show(item); gtk_menu_shell_append(GTK_MENU_SHELL(ret->menubar), item); gtk_widget_show(ret->menubar); update_menu(ret); return ret; } static void free_preset_menu(preset_menu_t * m) { if(m->preset_items) free(m->preset_items); } void bg_gtk_preset_menu_destroy(bg_gtk_preset_menu_t * m) { free_preset_menu(&m->load_menu); free_preset_menu(&m->save_to_menu); free_preset_menu(&m->delete_menu); if(m->preset_name) free(m->preset_name); if(m->path) free(m->path); free(m); } GtkWidget * bg_gtk_preset_menu_get_widget(bg_gtk_preset_menu_t * m) { return m->menubar; } gmerlin-1.2.0~dfsg/lib/gtk/driveselect.c0000644000175000017500000001767611764363406020134 0ustar alessioalessio/***************************************************************** * gmerlin - a general purpose multimedia framework and applications * * Copyright (c) 2001 - 2011 Members of the Gmerlin project * gmerlin-general@lists.sourceforge.net * http://gmerlin.sourceforge.net * * 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 of the License, 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 this program. If not, see . * *****************************************************************/ #include #include #include #include #include #include #include #include #include #include struct bg_gtk_drivesel_s { GtkWidget * window; GtkWidget * add_button; GtkWidget * close_button; GtkWidget * drive_menu; const bg_plugin_info_t * plugin_info; bg_gtk_plugin_menu_t * plugin_menu; void (*add_files)(char ** files, const char * plugin, int prefer_edl, void * data); void (*close_notify)(bg_gtk_drivesel_t * f, void * data); void * callback_data; int is_modal; int num_drives; bg_plugin_registry_t * plugin_reg; }; static void plugin_change_callback(bg_gtk_plugin_menu_t * m, void * data) { int i; bg_gtk_drivesel_t * ds; bg_device_info_t * devices; ds = (bg_gtk_drivesel_t*)data; for(i = 0; i < ds->num_drives; i++) bg_gtk_combo_box_remove_text(ds->drive_menu, 0); ds->plugin_info = bg_plugin_find_by_name(ds->plugin_reg, bg_gtk_plugin_menu_get_plugin(ds->plugin_menu)); devices = ds->plugin_info->devices; ds->num_drives = 0; while(devices[ds->num_drives].device) { if(devices[ds->num_drives].name) bg_gtk_combo_box_append_text(ds->drive_menu, devices[ds->num_drives].name); else bg_gtk_combo_box_append_text(ds->drive_menu, devices[ds->num_drives].device); ds->num_drives++; } /* Select first entry */ gtk_combo_box_set_active(GTK_COMBO_BOX(ds->drive_menu), 0); } static void button_callback(GtkWidget * w, gpointer data) { bg_gtk_drivesel_t * f; const char * plugin = NULL; char * drives[2]; f = (bg_gtk_drivesel_t *)data; if(w == f->add_button) { // plugin = menu_get_current(&f->plugins); drives[0] = f->plugin_info->devices[gtk_combo_box_get_active(GTK_COMBO_BOX(f->drive_menu))].device; drives[1] = NULL; plugin = f->plugin_info->name; f->add_files(drives, plugin, 0, f->callback_data); } else if((w == f->window) || (w == f->close_button)) { if(f->close_notify) f->close_notify(f, f->callback_data); gtk_widget_hide(f->window); if(f->is_modal) gtk_main_quit(); bg_gtk_drivesel_destroy(f); } } static gboolean delete_callback(GtkWidget * w, GdkEventAny * event, gpointer data) { button_callback(w, data); return TRUE; } static gboolean destroy_callback(GtkWidget * w, GdkEvent * event, gpointer data) { button_callback(w, data); return TRUE; } bg_gtk_drivesel_t * bg_gtk_drivesel_create(const char * title, void (*add_files)(char ** files, const char * plugin, int prefer_edl, void * data), void (*close_notify)(bg_gtk_drivesel_t *, void * data), void * user_data, GtkWidget * parent_window, bg_plugin_registry_t * plugin_reg, int type_mask, int flag_mask) { bg_gtk_drivesel_t * ret; GtkWidget * box; GtkWidget * table; GtkWidget * mainbox; GtkWidget * label; ret = calloc(1, sizeof(*ret)); /* Create window */ ret->window = bg_gtk_window_new(GTK_WINDOW_TOPLEVEL); gtk_window_set_title(GTK_WINDOW(ret->window), title); gtk_window_set_position(GTK_WINDOW(ret->window), GTK_WIN_POS_CENTER_ON_PARENT); gtk_container_set_border_width(GTK_CONTAINER(ret->window), 5); if(parent_window) { gtk_window_set_transient_for(GTK_WINDOW(ret->window), GTK_WINDOW(parent_window)); gtk_window_set_destroy_with_parent(GTK_WINDOW(ret->window), TRUE); g_signal_connect(G_OBJECT(ret->window), "destroy-event", G_CALLBACK(destroy_callback), ret); } /* Create device menu */ ret->drive_menu = bg_gtk_combo_box_new_text(); gtk_widget_show(ret->drive_menu); /* Create plugin menu */ ret->plugin_reg = plugin_reg; ret->plugin_menu = bg_gtk_plugin_menu_create(0, plugin_reg, type_mask, flag_mask); bg_gtk_plugin_menu_set_change_callback(ret->plugin_menu, plugin_change_callback, ret); /* Create Buttons */ ret->add_button = gtk_button_new_from_stock(GTK_STOCK_ADD); ret->close_button = gtk_button_new_from_stock(GTK_STOCK_CLOSE); bg_gtk_widget_set_can_default(ret->close_button, TRUE); bg_gtk_widget_set_can_default(ret->add_button, TRUE); /* Set callbacks */ g_signal_connect(G_OBJECT(ret->window), "delete-event", G_CALLBACK(delete_callback), ret); g_signal_connect(G_OBJECT(ret->add_button), "clicked", G_CALLBACK(button_callback), ret); g_signal_connect(G_OBJECT(ret->close_button), "clicked", G_CALLBACK(button_callback), ret); /* Show Buttons */ gtk_widget_show(ret->add_button); gtk_widget_show(ret->close_button); /* Pack everything */ mainbox = gtk_vbox_new(0, 5); table = gtk_table_new(2, 2, 0); gtk_table_set_col_spacings(GTK_TABLE(table), 5); gtk_table_set_row_spacings(GTK_TABLE(table), 5); bg_gtk_plugin_menu_attach(ret->plugin_menu, table, 0, 0); label = gtk_label_new(TR("Drive:")); gtk_widget_show(label); gtk_table_attach(GTK_TABLE(table), label, 0, 1, 1, 2, GTK_FILL, GTK_FILL, 0, 0); gtk_table_attach_defaults(GTK_TABLE(table), ret->drive_menu, 1, 2, 1, 2); gtk_widget_show(table); bg_gtk_box_pack_start_defaults(GTK_BOX(mainbox), table); box = gtk_hbutton_box_new(); gtk_container_add(GTK_CONTAINER(box), ret->close_button); gtk_container_add(GTK_CONTAINER(box), ret->add_button); gtk_widget_show(box); bg_gtk_box_pack_start_defaults(GTK_BOX(mainbox), box); gtk_widget_show(mainbox); gtk_container_add(GTK_CONTAINER(ret->window), mainbox); /* Set pointers */ ret->add_files = add_files; ret->close_notify = close_notify; ret->callback_data = user_data; plugin_change_callback(ret->plugin_menu, ret); return ret; } /* Destroy driveselector */ void bg_gtk_drivesel_destroy(bg_gtk_drivesel_t * drivesel) { free(drivesel); } /* Show the window */ void bg_gtk_drivesel_run(bg_gtk_drivesel_t * drivesel, int modal, GtkWidget * parent) { if(modal) { parent = bg_gtk_get_toplevel(parent); if(parent) gtk_window_set_transient_for(GTK_WINDOW(drivesel->window), GTK_WINDOW(parent)); } gtk_window_set_modal(GTK_WINDOW(drivesel->window), modal); gtk_widget_show(drivesel->window); gtk_widget_grab_focus(drivesel->close_button); gtk_widget_grab_default(drivesel->close_button); drivesel->is_modal = modal; if(modal) gtk_main(); } gmerlin-1.2.0~dfsg/lib/gtk/treewidget.c0000644000175000017500000016517211764363406017761 0ustar alessioalessio/***************************************************************** * gmerlin - a general purpose multimedia framework and applications * * Copyright (c) 2001 - 2011 Members of the Gmerlin project * gmerlin-general@lists.sourceforge.net * http://gmerlin.sourceforge.net * * 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 of the License, 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 this program. If not, see . * *****************************************************************/ #include #include #include #include #include #include #include #include //#include #include #include #include #include static void set_tabbed_mode(bg_gtk_tree_widget_t * w); static void set_windowed_mode(bg_gtk_tree_widget_t * w); static GdkPixbuf * root_pixbuf = NULL; static GdkPixbuf * folder_closed_pixbuf = NULL; static GdkPixbuf * folder_open_pixbuf = NULL; static GdkPixbuf * favourites_closed_pixbuf = NULL; static GdkPixbuf * favourites_open_pixbuf = NULL; static GdkPixbuf * incoming_closed_pixbuf = NULL; static GdkPixbuf * incoming_open_pixbuf = NULL; static GdkPixbuf * removable_closed_pixbuf = NULL; static GdkPixbuf * removable_open_pixbuf = NULL; static GdkPixbuf * error_pixbuf = NULL; static GdkPixbuf * hardware_pixbuf = NULL; static GdkPixbuf * tuner_pixbuf = NULL; static int num_tree_widgets = 0; /* Atoms */ static int atoms_created = 0; GdkAtom bg_gtk_atom_entries = (GdkAtom)0; GdkAtom bg_gtk_atom_entries_r = (GdkAtom)0; GdkAtom bg_gtk_atom_album = (GdkAtom)0; void bg_gtk_tree_create_atoms() { if(atoms_created) return; atoms_created = 1; bg_gtk_atom_entries_r = gdk_atom_intern(bg_gtk_atom_entries_name_r, FALSE); bg_gtk_atom_entries = gdk_atom_intern(bg_gtk_atom_entries_name, FALSE); bg_gtk_atom_album = gdk_atom_intern(bg_gtk_atom_album_name, FALSE); } /* 0 means undefined */ #define DND_GMERLIN_TRACKS 1 #define DND_GMERLIN_TRACKS_R 2 #define DND_GMERLIN_ALBUM 3 #define DND_TEXT_URI_LIST 4 #define DND_TEXT_PLAIN 5 static const GtkTargetEntry dnd_src_entries[] = { {bg_gtk_atom_album_name, GTK_TARGET_SAME_WIDGET, DND_GMERLIN_ALBUM }, }; static const GtkTargetEntry dnd_dst_entries[] = { {bg_gtk_atom_entries_name, GTK_TARGET_SAME_APP, DND_GMERLIN_TRACKS }, {bg_gtk_atom_album_name, GTK_TARGET_SAME_WIDGET, DND_GMERLIN_ALBUM }, {"text/uri-list", 0, DND_TEXT_URI_LIST }, {"text/plain", 0, DND_TEXT_PLAIN } }; /* Open the current album if it isn't already open */ static void open_album(bg_gtk_tree_widget_t * widget, bg_album_t * album); static void load_pixmaps() { char * filename; if(num_tree_widgets) { num_tree_widgets++; return; } num_tree_widgets++; filename = bg_search_file_read("icons", "folder_closed_16.png"); if(filename) { folder_closed_pixbuf = gdk_pixbuf_new_from_file(filename, NULL); free(filename); } filename = bg_search_file_read("icons", "folder_open_16.png"); if(filename) { folder_open_pixbuf = gdk_pixbuf_new_from_file(filename, NULL); free(filename); } filename = bg_search_file_read("icons", "incoming_closed_16.png"); if(filename) { incoming_closed_pixbuf = gdk_pixbuf_new_from_file(filename, NULL); free(filename); } filename = bg_search_file_read("icons", "incoming_open_16.png"); if(filename) { incoming_open_pixbuf = gdk_pixbuf_new_from_file(filename, NULL); free(filename); } filename = bg_search_file_read("icons", "favourites_closed_16.png"); if(filename) { favourites_closed_pixbuf = gdk_pixbuf_new_from_file(filename, NULL); free(filename); } filename = bg_search_file_read("icons", "favourites_open_16.png"); if(filename) { favourites_open_pixbuf = gdk_pixbuf_new_from_file(filename, NULL); free(filename); } filename = bg_search_file_read("icons", "drive_16.png"); if(filename) { removable_closed_pixbuf = gdk_pixbuf_new_from_file(filename, NULL); free(filename); } filename = bg_search_file_read("icons", "drive_running_16.png"); if(filename) { removable_open_pixbuf = gdk_pixbuf_new_from_file(filename, NULL); free(filename); } filename = bg_search_file_read("icons", "drive_error_16.png"); if(filename) { error_pixbuf = gdk_pixbuf_new_from_file(filename, NULL); free(filename); } filename = bg_search_file_read("icons", "hardware_16.png"); if(filename) { hardware_pixbuf = gdk_pixbuf_new_from_file(filename, NULL); free(filename); } filename = bg_search_file_read("icons", "tree_root_16.png"); if(filename) { root_pixbuf = gdk_pixbuf_new_from_file(filename, NULL); free(filename); } filename = bg_search_file_read("icons", "tuner_16.png"); if(filename) { tuner_pixbuf = gdk_pixbuf_new_from_file(filename, NULL); free(filename); } } #if 0 static void unload_pixmaps() { num_tree_widgets--; if(num_tree_widgets) return; g_object_unref(root_pixbuf); g_object_unref(folder_closed_pixbuf); g_object_unref(folder_open_pixbuf); g_object_unref(removable_closed_pixbuf); g_object_unref(removable_open_pixbuf); g_object_unref(error_pixbuf); g_object_unref(hardware_pixbuf); g_object_unref(tuner_pixbuf); root_pixbuf = NULL; folder_closed_pixbuf = NULL; folder_open_pixbuf = NULL; removable_closed_pixbuf = NULL; removable_open_pixbuf = NULL; error_pixbuf = NULL; hardware_pixbuf = NULL; tuner_pixbuf = NULL; } #endif enum { COLUMN_NAME, COLUMN_PIXMAP, COLUMN_WEIGHT, COLUMN_COLOR, NUM_COLUMNS }; typedef struct { GtkWidget * menu; GtkWidget * expand_item; GtkWidget * collapse_item; GtkWidget * tabbed_mode_item; GtkWidget * windowed_mode_item; GtkWidget * goto_current_item; } tree_menu_t; typedef struct { GtkWidget * new_item; GtkWidget * new_from_directory_item; GtkWidget * rename_item; GtkWidget * open_item; GtkWidget * close_item; GtkWidget * remove_item; GtkWidget * menu; } album_menu_t; typedef struct { GtkWidget * find_devices_item; GtkWidget * add_device_item; GtkWidget * menu; } plugin_menu_t; typedef struct { GtkWidget * tree_item; tree_menu_t tree_menu; GtkWidget * album_item; album_menu_t album_menu; GtkWidget * plugin_item; plugin_menu_t plugin_menu; GtkWidget * menu; } root_menu_t; struct bg_gtk_tree_widget_s { bg_cfg_section_t * cfg_section; GtkWidget * widget; GtkWidget * treeview; bg_media_tree_t * tree; bg_album_t * selected_album; root_menu_t menu; GList * album_windows; gulong select_handler_id; guint drop_time; /* Buttons */ GtkWidget * new_button; GtkWidget * remove_button; GtkWidget * rename_button; GtkWidget * goto_current_button; /* Notebook */ GtkWidget * notebook; int tabbed_mode; GtkAccelGroup * accel_group; GtkAccelGroup * album_accel_group; GtkWidget * toplevel_window; gulong timeout_tag; }; /* Configuration */ static const bg_parameter_info_t parameters[] = { { .name = "tabbed_mode", .long_name = "Tabbed mode", .type = BG_PARAMETER_CHECKBUTTON, .flags = BG_PARAMETER_HIDE_DIALOG, .val_default = { .val_i = 1 }, }, { /* End of parameters */ } }; static void set_parameter(void * data, const char * name, const bg_parameter_value_t * val) { bg_gtk_tree_widget_t * wid; wid = (bg_gtk_tree_widget_t*)data; if(!name) return; else if(!strcmp(name, "tabbed_mode")) { if(val->val_i) set_tabbed_mode(wid); else set_windowed_mode(wid); } } static int get_parameter(void * data, const char * name, bg_parameter_value_t * val) { bg_gtk_tree_widget_t * wid; wid = (bg_gtk_tree_widget_t*)data; if(!name) return 1; else if(!strcmp(name, "tabbed_mode")) { val->val_i = wid->tabbed_mode; return 1; } return 0; } /* Utility funcions */ /* Return 1 if album and album_window match */ static gint is_window_of(gconstpointer a, gconstpointer b) { bg_gtk_album_window_t * album_win; bg_album_t * album; album_win = (bg_gtk_album_window_t*)a; album = (bg_album_t *)b; return (album == bg_gtk_album_window_get_album(album_win)) ? 0 : 1; } /* * Return the corresponding album window for a widget, * or NULL if there is none */ static bg_gtk_album_window_t * album_is_open(bg_gtk_tree_widget_t * widget, bg_album_t * album) { GList * tmp_list; tmp_list = g_list_find_custom(widget->album_windows, (gconstpointer*)(album), is_window_of); if(tmp_list) return tmp_list->data; return NULL; } /* Update the menu */ static void rename_item(GtkWidget * w, const char * label) { gtk_label_set_text(GTK_LABEL(gtk_bin_get_child(GTK_BIN(w))), label); } static void update_menu(bg_gtk_tree_widget_t * w) { bg_album_type_t type; /* En- or disable menu items */ if(w->tabbed_mode) { gtk_widget_hide(w->menu.tree_menu.tabbed_mode_item); gtk_widget_show(w->menu.tree_menu.windowed_mode_item); } else { gtk_widget_show(w->menu.tree_menu.tabbed_mode_item); gtk_widget_hide(w->menu.tree_menu.windowed_mode_item); } if(!w->selected_album) { rename_item(w->menu.album_item, "Album..."); gtk_widget_show(w->menu.album_item); gtk_widget_hide(w->menu.album_menu.remove_item); gtk_widget_set_sensitive(w->remove_button, 0); gtk_widget_set_sensitive(w->rename_button, 0); gtk_widget_set_sensitive(w->new_button, 1); gtk_widget_hide(w->menu.album_menu.rename_item); gtk_widget_hide(w->menu.album_menu.open_item); gtk_widget_hide(w->menu.album_menu.close_item); gtk_widget_show(w->menu.album_menu.new_item); gtk_widget_show(w->menu.album_menu.new_from_directory_item); gtk_widget_hide(w->menu.plugin_item); return; } else { type = bg_album_get_type(w->selected_album); switch(type) { case BG_ALBUM_TYPE_PLUGIN: gtk_widget_hide(w->menu.album_item); gtk_widget_show(w->menu.plugin_item); gtk_widget_set_sensitive(w->remove_button, 0); gtk_widget_set_sensitive(w->rename_button, 0); gtk_widget_set_sensitive(w->new_button, 0); break; case BG_ALBUM_TYPE_REMOVABLE: case BG_ALBUM_TYPE_TUNER: rename_item(w->menu.album_item, "Device..."); gtk_widget_show(w->menu.album_item); gtk_widget_hide(w->menu.plugin_item); gtk_widget_show(w->menu.album_menu.remove_item); gtk_widget_set_sensitive(w->remove_button, 1); gtk_widget_set_sensitive(w->rename_button, 1); gtk_widget_set_sensitive(w->new_button, 0); gtk_widget_show(w->menu.album_menu.rename_item); gtk_widget_hide(w->menu.album_menu.new_item); gtk_widget_hide(w->menu.album_menu.new_from_directory_item); if(album_is_open(w, w->selected_album)) { gtk_widget_hide(w->menu.album_menu.open_item); gtk_widget_show(w->menu.album_menu.close_item); } else { gtk_widget_show(w->menu.album_menu.open_item); gtk_widget_hide(w->menu.album_menu.close_item); } break; case BG_ALBUM_TYPE_REGULAR: gtk_widget_hide(w->menu.plugin_item); rename_item(w->menu.album_item, "Album..."); gtk_widget_show(w->menu.album_item); gtk_widget_show(w->menu.album_menu.remove_item); gtk_widget_set_sensitive(w->remove_button, 1); gtk_widget_set_sensitive(w->rename_button, 1); gtk_widget_set_sensitive(w->new_button, 1); gtk_widget_show(w->menu.album_menu.new_item); gtk_widget_show(w->menu.album_menu.new_from_directory_item); gtk_widget_show(w->menu.album_menu.rename_item); if(album_is_open(w, w->selected_album)) { gtk_widget_hide(w->menu.album_menu.open_item); gtk_widget_show(w->menu.album_menu.close_item); } else { gtk_widget_show(w->menu.album_menu.open_item); gtk_widget_hide(w->menu.album_menu.close_item); } break; case BG_ALBUM_TYPE_INCOMING: case BG_ALBUM_TYPE_FAVOURITES: gtk_widget_hide(w->menu.plugin_item); rename_item(w->menu.album_item, "Album..."); gtk_widget_show(w->menu.album_item); gtk_widget_hide(w->menu.album_menu.remove_item); gtk_widget_set_sensitive(w->remove_button, 0); gtk_widget_set_sensitive(w->rename_button, 0); gtk_widget_set_sensitive(w->new_button, 0); gtk_widget_hide(w->menu.album_menu.new_item); gtk_widget_hide(w->menu.album_menu.new_from_directory_item); gtk_widget_hide(w->menu.album_menu.rename_item); if(album_is_open(w, w->selected_album)) { gtk_widget_hide(w->menu.album_menu.open_item); gtk_widget_show(w->menu.album_menu.close_item); } else { gtk_widget_show(w->menu.album_menu.open_item); gtk_widget_hide(w->menu.album_menu.close_item); } break; break; } } } /* Utility functions: Convert between GtkTreeIter and bg_album_t */ static void album_2_iter(bg_gtk_tree_widget_t * widget, bg_album_t * album, GtkTreeIter * iter) { int * indices; int i; GtkTreeModel *model; GtkTreePath *path; model = gtk_tree_view_get_model(GTK_TREE_VIEW(widget->treeview)); indices = bg_media_tree_get_path(widget->tree, album); path = gtk_tree_path_new_first(); i = 0; while(indices[i] != -1) { gtk_tree_path_append_index(path, indices[i]); i++; } free(indices); gtk_tree_model_get_iter(model, iter, path); gtk_tree_path_free(path); } static bg_album_t * path_2_album(bg_gtk_tree_widget_t * w, GtkTreePath * path) { int i; bg_album_t * ret; gint * indices; gint depth; depth = gtk_tree_path_get_depth(path); if(depth < 2) return NULL; indices = gtk_tree_path_get_indices(path); ret = bg_media_tree_get_album(w->tree, indices[1]); for(i = 2; i < depth; i++) { ret = bg_album_get_child(ret, indices[i]); } return ret; } static bg_album_t * iter_2_album(bg_gtk_tree_widget_t * w, GtkTreeIter * iter) { GtkTreePath* path; GtkTreeModel * model; bg_album_t * ret; model = gtk_tree_view_get_model(GTK_TREE_VIEW(w->treeview)); path = gtk_tree_model_get_path(model, iter); ret = path_2_album(w, path); gtk_tree_path_free(path); return ret; } /* Set one album */ static void set_album(bg_gtk_tree_widget_t * widget, bg_album_t * album, GtkTreeIter * iter, int set_children, int open_window) { bg_album_type_t type; int num_children = 0; bg_album_t * child; int i; GtkTreeIter child_iter; GtkTreeModel * model; bg_album_t * current_album; bg_gtk_album_window_t * album_window; model = gtk_tree_view_get_model(GTK_TREE_VIEW(widget->treeview)); /* Open window if necessary */ // if(bg_album_is_open(album)) // open_album(widget, album); /* Set values */ /* Get the appropriate pixmap */ current_album = bg_media_tree_get_current_album(widget->tree); gtk_tree_store_set(GTK_TREE_STORE(model), iter, COLUMN_NAME, bg_album_get_label(album), -1); type = bg_album_get_type(album); switch(type) { /* Regular album */ case BG_ALBUM_TYPE_REGULAR: if(bg_album_is_open(album)) gtk_tree_store_set(GTK_TREE_STORE(model), iter, COLUMN_PIXMAP, folder_open_pixbuf, -1); else gtk_tree_store_set(GTK_TREE_STORE(model), iter, COLUMN_PIXMAP, folder_closed_pixbuf, -1); break; /* Drive for removable media */ case BG_ALBUM_TYPE_REMOVABLE: if(bg_album_is_open(album)) gtk_tree_store_set(GTK_TREE_STORE(model), iter, COLUMN_PIXMAP, removable_open_pixbuf, -1); else if(bg_album_get_error(album)) gtk_tree_store_set(GTK_TREE_STORE(model), iter, COLUMN_PIXMAP, error_pixbuf, -1); else gtk_tree_store_set(GTK_TREE_STORE(model), iter, COLUMN_PIXMAP, removable_closed_pixbuf, -1); break; /* Tuner */ case BG_ALBUM_TYPE_TUNER: if(bg_album_get_error(album)) gtk_tree_store_set(GTK_TREE_STORE(model), iter, COLUMN_PIXMAP, error_pixbuf, -1); else gtk_tree_store_set(GTK_TREE_STORE(model), iter, COLUMN_PIXMAP, tuner_pixbuf, -1); break; /* Hardware plugin (Subalbums are devices) */ case BG_ALBUM_TYPE_PLUGIN: gtk_tree_store_set(GTK_TREE_STORE(model), iter, COLUMN_PIXMAP, hardware_pixbuf, -1); break; /* Incoming album: Stuff from the commandline and the remote will go there */ case BG_ALBUM_TYPE_INCOMING: if(bg_album_is_open(album)) gtk_tree_store_set(GTK_TREE_STORE(model), iter, COLUMN_PIXMAP, incoming_open_pixbuf, -1); else gtk_tree_store_set(GTK_TREE_STORE(model), iter, COLUMN_PIXMAP, incoming_closed_pixbuf, -1); break; case BG_ALBUM_TYPE_FAVOURITES: if(bg_album_is_open(album)) gtk_tree_store_set(GTK_TREE_STORE(model), iter, COLUMN_PIXMAP, favourites_open_pixbuf, -1); else gtk_tree_store_set(GTK_TREE_STORE(model), iter, COLUMN_PIXMAP, favourites_closed_pixbuf, -1); break; } if(album == current_album) gtk_tree_store_set(GTK_TREE_STORE(model), iter, COLUMN_WEIGHT, PANGO_WEIGHT_BOLD, -1); else gtk_tree_store_set(GTK_TREE_STORE(model), iter, COLUMN_WEIGHT, PANGO_WEIGHT_NORMAL, -1); if(bg_album_get_error(album)) gtk_tree_store_set(GTK_TREE_STORE(model), iter, COLUMN_COLOR, "#FF0000", -1); else gtk_tree_store_set(GTK_TREE_STORE(model), iter, COLUMN_COLOR, "#000000", -1); if(open_window && bg_album_is_open(album) && !album_is_open(widget, album)) { album_window = bg_gtk_album_window_create(album, widget, widget->accel_group); widget->album_windows = g_list_append(widget->album_windows, album_window); if(widget->tabbed_mode) bg_gtk_album_window_attach(album_window, widget->notebook); else bg_gtk_album_window_detach(album_window); } else album_window = album_is_open(widget, album); if(album_window) bg_gtk_album_window_set_current(album_window, (album == current_album) ? 1 : 0); /* Append all subalbums of one album */ num_children = bg_album_get_num_children(album); if(set_children) { for(i = 0; i < num_children; i++) { gtk_tree_store_append(GTK_TREE_STORE(model), &child_iter, iter); child = bg_album_get_child(album, i); set_album(widget, child, &child_iter, set_children, open_window); } } } static void expand_album(bg_gtk_tree_widget_t * w, bg_album_t * album) { GtkTreeIter iter; GtkTreePath * path; GtkTreeModel * model; GtkTreeSelection * selection; int i; bg_album_t * child_album; int num_children; int expanded; int selected; expanded = bg_album_get_expanded(album); selected = (w->selected_album == album) ? 1 : 0; if(!selected && !expanded) return; model = gtk_tree_view_get_model(GTK_TREE_VIEW(w->treeview)); album_2_iter(w, album, &iter); path = gtk_tree_model_get_path(model, &iter); if(selected) { selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(w->treeview)); gtk_tree_selection_select_path(selection, path); } if(expanded) gtk_tree_view_expand_row(GTK_TREE_VIEW(w->treeview), path, 0); gtk_tree_path_free(path); num_children = bg_album_get_num_children(album); for(i = 0; i < num_children; i++) { child_album = bg_album_get_child(album, i); expand_album(w, child_album); } } /* Update the entire tree */ void bg_gtk_tree_widget_update(bg_gtk_tree_widget_t * w, int open_albums) { GtkTreeModel * model; GtkTreeIter iter; GtkTreeIter root_iter; GtkTreePath * path; int i; int num_children; bg_album_t * album; GtkTreeSelection * selection; /* We must block the selection callback */ selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(w->treeview)); g_signal_handler_block(G_OBJECT(selection), w->select_handler_id); model = gtk_tree_view_get_model(GTK_TREE_VIEW(w->treeview)); gtk_tree_store_clear(GTK_TREE_STORE(model)); gtk_tree_store_append(GTK_TREE_STORE(model), &root_iter, NULL); gtk_tree_store_set(GTK_TREE_STORE(model), &root_iter, COLUMN_NAME, "Mediatree", -1); gtk_tree_store_set(GTK_TREE_STORE(model), &root_iter, COLUMN_PIXMAP, root_pixbuf, -1); num_children = bg_media_tree_get_num_albums(w->tree); for(i = 0; i < num_children; i++) { gtk_tree_store_append(GTK_TREE_STORE(model), &iter, &root_iter); album = bg_media_tree_get_album(w->tree, i); set_album(w, album, &iter, 1, open_albums); } path = gtk_tree_model_get_path(model, &root_iter); gtk_tree_view_expand_row(GTK_TREE_VIEW(w->treeview), path, FALSE); gtk_tree_path_free(path); for(i = 0; i < num_children; i++) { album = bg_media_tree_get_album(w->tree, i); expand_album(w, album); } g_signal_handler_unblock(G_OBJECT(selection), w->select_handler_id); } /* * Remove an album window from the list * This is called by the destructor of album windows */ void bg_gtk_tree_widget_close_album(bg_gtk_tree_widget_t * widget, bg_gtk_album_window_t * win) { bg_album_t * album; GtkTreeIter iter; widget->album_windows = g_list_remove(widget->album_windows, win); album = bg_gtk_album_window_get_album(win); bg_album_close(album); album_2_iter(widget, album, &iter); set_album(widget, album, &iter, 0, 0); update_menu(widget); } /* Open the current album if it isn't already open */ static void open_album(bg_gtk_tree_widget_t * widget, bg_album_t * album) { bg_album_type_t type; int result; GtkTreeIter iter; if(!album) return; type = bg_album_get_type(album); if(type == BG_ALBUM_TYPE_PLUGIN) return; /* Check, if the album is already open */ if(!album_is_open(widget, album)) { if(!bg_album_is_open(album)) { result = bg_album_open(album); bg_album_set_error(album, !result); } album_2_iter(widget, album, &iter); set_album(widget, album, &iter, 0, 1); } update_menu(widget); } void bg_gtk_tree_widget_open_incoming(bg_gtk_tree_widget_t * w) { open_album(w, bg_media_tree_get_incoming(w->tree)); } static void set_parameter_rename_album(void * data, const char * name, const bg_parameter_value_t * val) { GtkTreeIter iter; bg_gtk_tree_widget_t * w = (bg_gtk_tree_widget_t*)data; if(!name) return; if(!strcmp(name, "album_name")) { if(w->selected_album) { bg_album_rename(w->selected_album, val->val_str); album_2_iter(w, w->selected_album, &iter); set_album(w, w->selected_album, &iter, 0, 0); } } } static void rename_selected_album(bg_gtk_tree_widget_t * w) { bg_dialog_t * dialog; GtkTreeIter iter; bg_parameter_info_t info[2]; memset(info, 0, sizeof(info)); info[0].name = "album_name"; info[0].long_name = TRS("Album name"); info[0].type = BG_PARAMETER_STRING; info[0].val_default.val_str = bg_album_get_name(w->selected_album); dialog = bg_dialog_create(NULL, set_parameter_rename_album, NULL, w, info, TR("Rename album")); bg_dialog_show(dialog, w->treeview); bg_dialog_destroy(dialog); album_2_iter(w, w->selected_album, &iter); set_album(w, w->selected_album, &iter, 0, 0); } static void add_dir_callback(char * dir, int recursive, int subdirs_as_subalbums, int watch, const char * plugin, int prefer_edl, void * data) { bg_gtk_tree_widget_t * w = (bg_gtk_tree_widget_t*)data; gtk_widget_set_sensitive(w->treeview, 0); bg_media_tree_add_directory(w->tree, w->selected_album, dir, recursive, subdirs_as_subalbums, watch, plugin, prefer_edl); gtk_widget_set_sensitive(w->treeview, 1); } static void add_dir_close_notify(bg_gtk_filesel_t * s, void * data) { } static void add_directory(bg_gtk_tree_widget_t * w) { bg_gtk_filesel_t * dirsel; dirsel = bg_gtk_dirsel_create("Add directory", add_dir_callback, add_dir_close_notify, w, NULL /* parent_window */, bg_media_tree_get_plugin_registry(w->tree), BG_PLUGIN_INPUT, BG_PLUGIN_FILE); bg_gtk_filesel_set_directory(dirsel, bg_media_tree_get_add_directory_path(w->tree)); bg_gtk_filesel_run(dirsel, 1); } static void create_new_album(bg_gtk_tree_widget_t * w) { bg_album_t * new_album = bg_media_tree_append_album(w->tree, w->selected_album); if(w->selected_album) bg_album_set_expanded(w->selected_album, 1); w->selected_album = new_album; bg_gtk_tree_widget_update(w, 0); rename_selected_album(w); if(!bg_album_get_name(w->selected_album)) { bg_media_tree_remove_album(w->tree, w->selected_album); w->selected_album = NULL; bg_gtk_tree_widget_update(w, 0); } else { update_menu(w); } } static void remove_album(bg_gtk_tree_widget_t * w, bg_album_t * a) { int i, num_children; bg_gtk_album_window_t * album_window; bg_album_t * child; if(!a) return; /* Delete children as long as the parent still exists */ num_children = bg_album_get_num_children(a); for(i = 0; i < num_children; i++) { child = bg_album_get_child(a, 0); remove_album(w, child); } /* Delete parent */ album_window = album_is_open(w, a); if(album_window) { bg_gtk_album_window_destroy(album_window, 1); } if(a == w->selected_album) w->selected_album = NULL; bg_media_tree_remove_album(w->tree, a); update_menu(w); } typedef struct { char * device; char * name; bg_album_t * album; } add_device_struct; static void set_parameter_add_device(void * data, const char * name, const bg_parameter_value_t * val) { add_device_struct * s = (add_device_struct*)data; if(!name) { if(s->device) bg_album_add_device(s->album, s->device, s->name); return; } else if(!strcmp(name, "device")) { s->device = bg_strdup(s->device, val->val_str); } else if(!strcmp(name, "name")) { s->name = bg_strdup(s->name, val->val_str); } } static void add_device(bg_gtk_tree_widget_t * w) { bg_dialog_t * dialog; GtkTreeIter iter; add_device_struct s; bg_parameter_info_t info[3]; memset(info, 0, sizeof(info)); memset(&s, 0, sizeof(s)); s.album = w->selected_album; info[0].name = "device"; info[0].long_name = TRS("Device"); info[0].type = BG_PARAMETER_FILE; info[1].name = "name"; info[1].long_name = TRS("Name"); info[1].type = BG_PARAMETER_STRING; dialog = bg_dialog_create(NULL, set_parameter_add_device, NULL, &s, info, TR("Add device")); bg_dialog_show(dialog, w->treeview); bg_dialog_destroy(dialog); album_2_iter(w, w->selected_album, &iter); set_album(w, w->selected_album, &iter, 0, 0); bg_gtk_tree_widget_update(w, 0); if(s.name) free(s.name); if(s.device) free(s.device); } static void find_devices(bg_gtk_tree_widget_t * w) { int num_children, i; bg_album_t * child; bg_gtk_album_window_t * album_window; /* 1st step: Close all album windows */ num_children = bg_album_get_num_children(w->selected_album); for(i = 0; i < num_children; i++) { child = bg_album_get_child(w->selected_album, i); album_window = album_is_open(w, child); if(album_window) bg_gtk_album_window_destroy(album_window, 1); } /* 2nd step: Tell the album to scan for devices */ bg_album_find_devices(w->selected_album); /* 3rd step: Make changes visible */ bg_gtk_tree_widget_update(w, 0); } static void attach_func(gpointer data, gpointer user_data) { bg_gtk_album_window_t * win; bg_gtk_tree_widget_t * widget; win = (bg_gtk_album_window_t *)data; widget = (bg_gtk_tree_widget_t *)user_data; bg_gtk_album_window_attach(win, widget->notebook); } static void set_tabbed_mode(bg_gtk_tree_widget_t * w) { g_list_foreach(w->album_windows, attach_func, w); gtk_widget_show(w->notebook); w->tabbed_mode = 1; update_menu(w); } static void detach_func(gpointer data, gpointer user_data) { bg_gtk_album_window_t * win; bg_gtk_tree_widget_t * widget; win = (bg_gtk_album_window_t *)data; widget = (bg_gtk_tree_widget_t *)user_data; bg_gtk_album_window_detach(win); } static void set_windowed_mode(bg_gtk_tree_widget_t * w) { g_list_foreach(w->album_windows, detach_func, w); gtk_widget_hide(w->notebook); w->tabbed_mode = 0; update_menu(w); if(w->album_accel_group) { gtk_window_remove_accel_group(GTK_WINDOW(w->toplevel_window), w->album_accel_group); w->album_accel_group = NULL; } } void bg_gtk_tree_widget_goto_current(bg_gtk_tree_widget_t * w) { bg_album_t * current_album; bg_gtk_album_window_t * current_win; current_album = bg_media_tree_get_current_album(w->tree); if(w->toplevel_window) { gtk_window_present(GTK_WINDOW(w->toplevel_window)); // gtk_widget_grab_focus( } if(!current_album) return; current_win = album_is_open(w, current_album); if(!current_win) return; bg_gtk_album_window_goto_current(current_win); } static void menu_callback(GtkWidget * w, gpointer data) { bg_gtk_tree_widget_t * widget = (bg_gtk_tree_widget_t*)data; bg_gtk_album_window_t * album_window; /* Album menu */ if(widget->selected_album) { if(w == widget->menu.album_menu.open_item) { open_album(widget, widget->selected_album); } else if((w == widget->menu.album_menu.rename_item) || (w == widget->rename_button)) { rename_selected_album(widget); } else if((w == widget->menu.album_menu.remove_item) || (w == widget->remove_button)) { remove_album(widget, widget->selected_album); bg_gtk_tree_widget_update(widget, 0); } else if(w == widget->menu.album_menu.close_item) { /* Check, if album has already a window */ album_window = album_is_open(widget, widget->selected_album); if(album_window) { /* Open Album and create window */ bg_gtk_album_window_destroy(album_window, 1); } } else if(w == widget->menu.plugin_menu.find_devices_item) { find_devices(widget); } else if(w == widget->menu.plugin_menu.add_device_item) { add_device(widget); } } if(w == widget->menu.album_menu.new_from_directory_item) { add_directory(widget); } else if((w == widget->menu.album_menu.new_item) || (w == widget->new_button)) { create_new_album(widget); } else if(w == widget->menu.tree_menu.expand_item) { gtk_tree_view_expand_all(GTK_TREE_VIEW(widget->treeview)); } else if(w == widget->menu.tree_menu.collapse_item) { gtk_tree_view_collapse_all(GTK_TREE_VIEW(widget->treeview)); } else if(w == widget->menu.tree_menu.tabbed_mode_item) { set_tabbed_mode(widget); } else if(w == widget->menu.tree_menu.windowed_mode_item) { set_windowed_mode(widget); } else if((w == widget->menu.tree_menu.goto_current_item) || (w == widget->goto_current_button)) { bg_gtk_tree_widget_goto_current(widget); } } /* Menu stuff */ static GtkWidget * create_item(bg_gtk_tree_widget_t * w, const char * label) { GtkWidget * ret; ret = gtk_menu_item_new_with_label(label); g_signal_connect(G_OBJECT(ret), "activate", G_CALLBACK(menu_callback), (gpointer)w); gtk_widget_show(ret); return ret; } static void init_menu(bg_gtk_tree_widget_t * w) { /* Tree Menu */ w->menu.tree_menu.menu = gtk_menu_new(); w->menu.tree_menu.goto_current_item = create_item(w, TR("Goto current track")); gtk_menu_shell_append(GTK_MENU_SHELL(w->menu.tree_menu.menu), w->menu.tree_menu.goto_current_item); gtk_widget_add_accelerator(w->menu.tree_menu.goto_current_item, "activate", w->accel_group, GDK_g, GDK_CONTROL_MASK, GTK_ACCEL_VISIBLE); w->menu.tree_menu.expand_item = create_item(w, TR("Expand all")); gtk_menu_shell_append(GTK_MENU_SHELL(w->menu.tree_menu.menu), w->menu.tree_menu.expand_item); w->menu.tree_menu.collapse_item = create_item(w, TR("Collapse all")); gtk_menu_shell_append(GTK_MENU_SHELL(w->menu.tree_menu.menu), w->menu.tree_menu.collapse_item); w->menu.tree_menu.tabbed_mode_item = create_item(w, TR("Tabbed mode")); gtk_menu_shell_append(GTK_MENU_SHELL(w->menu.tree_menu.menu), w->menu.tree_menu.tabbed_mode_item); w->menu.tree_menu.windowed_mode_item = create_item(w, TR("Windowed mode")); gtk_menu_shell_append(GTK_MENU_SHELL(w->menu.tree_menu.menu), w->menu.tree_menu.windowed_mode_item); gtk_widget_show(w->menu.tree_menu.menu); /* Album menu */ w->menu.album_menu.menu = gtk_menu_new(); w->menu.album_menu.open_item = create_item(w, TR("Open")); gtk_menu_shell_append(GTK_MENU_SHELL(w->menu.album_menu.menu), w->menu.album_menu.open_item); w->menu.album_menu.close_item = create_item(w, TR("Close")); gtk_menu_shell_append(GTK_MENU_SHELL(w->menu.album_menu.menu), w->menu.album_menu.close_item); w->menu.album_menu.new_item = create_item(w, TR("New...")); gtk_menu_shell_append(GTK_MENU_SHELL(w->menu.album_menu.menu), w->menu.album_menu.new_item); w->menu.album_menu.new_from_directory_item = create_item(w, TR("New from directory...")); gtk_menu_shell_append(GTK_MENU_SHELL(w->menu.album_menu.menu), w->menu.album_menu.new_from_directory_item); w->menu.album_menu.rename_item = create_item(w, TR("Rename...")); gtk_menu_shell_append(GTK_MENU_SHELL(w->menu.album_menu.menu), w->menu.album_menu.rename_item); w->menu.album_menu.remove_item = create_item(w, TR("Remove")); gtk_menu_shell_append(GTK_MENU_SHELL(w->menu.album_menu.menu), w->menu.album_menu.remove_item); gtk_widget_show(w->menu.album_menu.menu); /* Plugin menu */ w->menu.plugin_menu.menu = gtk_menu_new(); w->menu.plugin_menu.find_devices_item = create_item(w, TR("Scan for devices")); gtk_menu_shell_append(GTK_MENU_SHELL(w->menu.plugin_menu.menu), w->menu.plugin_menu.find_devices_item); w->menu.plugin_menu.add_device_item = create_item(w, TR("Add device...")); gtk_menu_shell_append(GTK_MENU_SHELL(w->menu.plugin_menu.menu), w->menu.plugin_menu.add_device_item); /* Root menu */ w->menu.menu = gtk_menu_new(); w->menu.album_item = create_item(w, TR("Album...")); gtk_menu_item_set_submenu(GTK_MENU_ITEM(w->menu.album_item), w->menu.album_menu.menu); gtk_menu_shell_append(GTK_MENU_SHELL(w->menu.menu), w->menu.album_item); w->menu.plugin_item = create_item(w, TR("Plugin...")); gtk_menu_item_set_submenu(GTK_MENU_ITEM(w->menu.plugin_item), w->menu.plugin_menu.menu); gtk_menu_shell_append(GTK_MENU_SHELL(w->menu.menu), w->menu.plugin_item); w->menu.tree_item = create_item(w, TR("Tree...")); gtk_menu_item_set_submenu(GTK_MENU_ITEM(w->menu.tree_item), w->menu.tree_menu.menu); gtk_menu_shell_append(GTK_MENU_SHELL(w->menu.menu), w->menu.tree_item); } /* Buttons */ static GtkWidget * create_pixmap_button(bg_gtk_tree_widget_t * w, const char * filename, const char * tooltip) { GtkWidget * button; GtkWidget * image; char * path; path = bg_search_file_read("icons", filename); if(path) { image = gtk_image_new_from_file(path); free(path); } else image = gtk_image_new(); gtk_widget_show(image); button = gtk_button_new(); gtk_container_add(GTK_CONTAINER(button), image); g_signal_connect(G_OBJECT(button), "clicked", G_CALLBACK(menu_callback), w); gtk_widget_show(button); bg_gtk_tooltips_set_tip(button, tooltip, PACKAGE); return button; } /* */ GtkWidget * bg_gtk_tree_widget_get_widget(bg_gtk_tree_widget_t * w) { return w->widget; } /* Callbacks */ static gboolean button_press_callback(GtkWidget * w, GdkEventButton * evt, gpointer data) { GtkTreeSelection * selection; GtkTreeModel * model; GtkTreeIter clicked_iter; GtkTreePath * path; bg_gtk_tree_widget_t * tw = (bg_gtk_tree_widget_t *)data; if((evt->button == 3) && (evt->type == GDK_BUTTON_PRESS)) { if(!gtk_tree_view_get_path_at_pos(GTK_TREE_VIEW(tw->treeview), evt->x, evt->y, &path, NULL, NULL, NULL)) { path = NULL; /* Didn't click any entry, return here */ // return TRUE; } if(path) { selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(tw->treeview)); model = gtk_tree_view_get_model(GTK_TREE_VIEW(tw->treeview)); gtk_tree_model_get_iter(model, &clicked_iter, path); gtk_tree_selection_select_iter(selection, &clicked_iter); } gtk_menu_popup(GTK_MENU(tw->menu.menu), NULL, NULL, NULL, NULL, 3, evt->time); if(path) gtk_tree_path_free(path); return TRUE; } else if((evt->button == 1) && (evt->type == GDK_2BUTTON_PRESS)) { open_album(tw, tw->selected_album); return TRUE; } return FALSE; } static void select_row_callback(GtkTreeSelection * sel, gpointer data) { bg_album_type_t type; GtkTreeIter iter; GtkTreeModel * model; bg_gtk_album_window_t * album_window; bg_gtk_tree_widget_t * w = (bg_gtk_tree_widget_t *)data; if(!gtk_tree_selection_get_selected(sel, &model, &iter)) { w->selected_album = NULL; } else { w->selected_album = iter_2_album(w, &iter); } update_menu(w); if(w->selected_album) { album_window = album_is_open(w, w->selected_album); if(album_window) bg_gtk_album_window_raise(album_window); type = bg_album_get_type(w->selected_album); switch(type) { case BG_ALBUM_TYPE_PLUGIN: case BG_ALBUM_TYPE_REMOVABLE: case BG_ALBUM_TYPE_TUNER: gtk_tree_view_unset_rows_drag_source(GTK_TREE_VIEW(w->treeview)); break; case BG_ALBUM_TYPE_REGULAR: case BG_ALBUM_TYPE_INCOMING: case BG_ALBUM_TYPE_FAVOURITES: gtk_tree_view_enable_model_drag_source(GTK_TREE_VIEW(w->treeview), GDK_BUTTON1_MASK, dnd_src_entries, sizeof(dnd_src_entries)/sizeof(dnd_src_entries[0]), GDK_ACTION_COPY); break; } } else gtk_tree_view_unset_rows_drag_source(GTK_TREE_VIEW(w->treeview)); } static void row_expanded_callback(GtkTreeView *treeview, GtkTreeIter *arg1, GtkTreePath *arg2, gpointer user_data) { bg_gtk_tree_widget_t * w; bg_album_t * album; w = (bg_gtk_tree_widget_t*)user_data; album = iter_2_album(w, arg1); if(!album) return; bg_album_set_expanded(album, 1); } static void row_collapsed_callback(GtkTreeView *treeview, GtkTreeIter *arg1, GtkTreePath *arg2, gpointer user_data) { bg_gtk_tree_widget_t * w; bg_album_t * album; w = (bg_gtk_tree_widget_t*)user_data; album = iter_2_album(w, arg1); if(!album) return; bg_album_set_expanded(album, 0); } static void drag_get_callback(GtkWidget *widget, GdkDragContext *drag_context, GtkSelectionData *data, guint info, guint time, gpointer user_data) { GdkAtom type_atom; bg_gtk_tree_widget_t * w; w = (bg_gtk_tree_widget_t *)user_data; type_atom = gdk_atom_intern("INTEGER", FALSE); if(!type_atom) return; gtk_selection_data_set(data, type_atom, 8, (void*)(w->selected_album), sizeof(w->selected_album)); } static void drag_received_callback(GtkWidget *widget, GdkDragContext *drag_context, gint x, gint y, GtkSelectionData *data, guint info, guint time, gpointer d) { bg_album_t * dest_album; gchar * atom_name; GtkTreePath * path; GtkTreeViewDropPosition pos; int was_open; int do_delete = 0; bg_album_type_t type; bg_gtk_tree_widget_t * w = (bg_gtk_tree_widget_t *)d; if(!gtk_tree_view_get_dest_row_at_pos(GTK_TREE_VIEW(w->treeview), x, y, &path, &pos)) return; if(!path) return; dest_album = path_2_album(w, path); gtk_tree_path_free(path); if(!dest_album) return; atom_name = gdk_atom_name(data->target); if(!strcmp(atom_name, bg_gtk_atom_album_name)) { switch(pos) { case GTK_TREE_VIEW_DROP_INTO_OR_BEFORE: case GTK_TREE_VIEW_DROP_INTO_OR_AFTER: bg_media_tree_move_album(w->tree, w->selected_album, dest_album); break; case GTK_TREE_VIEW_DROP_AFTER: bg_media_tree_move_album_after(w->tree, w->selected_album, dest_album); break; case GTK_TREE_VIEW_DROP_BEFORE: bg_media_tree_move_album_before(w->tree, w->selected_album, dest_album); break; } } else { type = bg_album_get_type(dest_album); switch(type) { case BG_ALBUM_TYPE_PLUGIN: case BG_ALBUM_TYPE_REMOVABLE: case BG_ALBUM_TYPE_TUNER: return; case BG_ALBUM_TYPE_REGULAR: case BG_ALBUM_TYPE_INCOMING: case BG_ALBUM_TYPE_FAVOURITES: break; } /* Open album if necessary */ if(!bg_album_is_open(dest_album)) { bg_album_open(dest_album); was_open = 0; } else was_open = 1; if(!strcmp(atom_name, "text/uri-list") || !strcmp(atom_name, "text/plain")) { bg_album_insert_urilist_before(dest_album, (char*)(data->data), data->length, NULL); } else if(!strcmp(atom_name, bg_gtk_atom_entries_name)) { bg_album_insert_xml_before(dest_album, (char*)(data->data), NULL); if(drag_context->action == GDK_ACTION_MOVE) do_delete = 1; } if(!was_open) bg_album_close(dest_album); } g_free(atom_name); gtk_drag_finish(drag_context, TRUE, /* Success */ do_delete, /* Delete */ w->drop_time); bg_gtk_tree_widget_update(w, 0); } static gboolean drag_drop_callback(GtkWidget *widget, GdkDragContext *drag_context, gint x, gint y, guint time, gpointer d) { bg_gtk_tree_widget_t * w = (bg_gtk_tree_widget_t *)d; w->drop_time = time; #if 0 gtk_drag_finish(drag_context, FALSE, /* Success */ FALSE, /* Delete */ w->drop_time); return TRUE; #else return TRUE; #endif } static gboolean drag_motion_callback(GtkWidget *widget, GdkDragContext *drag_context, gint x, gint y, guint time, gpointer user_data) { GtkTreePath * path; bg_album_t * drop_album; GtkTreeViewDropPosition pos; int result = 0; bg_album_type_t type; bg_gtk_tree_widget_t * w = (bg_gtk_tree_widget_t *)user_data; if(!gtk_tree_view_get_dest_row_at_pos(GTK_TREE_VIEW(w->treeview), x, y, &path, &pos)) { return TRUE; } else { drop_album = path_2_album(w, path); if(drop_album) { type = bg_album_get_type(drop_album); switch(type) { case BG_ALBUM_TYPE_REGULAR: case BG_ALBUM_TYPE_INCOMING: case BG_ALBUM_TYPE_FAVOURITES: if(widget != gtk_drag_get_source_widget(drag_context)) { gtk_tree_view_set_drag_dest_row(GTK_TREE_VIEW(w->treeview), path, GTK_TREE_VIEW_DROP_INTO_OR_BEFORE); } else { /* Check if we can drop here */ switch(pos) { case GTK_TREE_VIEW_DROP_INTO_OR_BEFORE: case GTK_TREE_VIEW_DROP_INTO_OR_AFTER: result = bg_media_tree_check_move_album(w->tree, w->selected_album, drop_album); break; case GTK_TREE_VIEW_DROP_AFTER: result = bg_media_tree_check_move_album_after(w->tree, w->selected_album, drop_album); break; case GTK_TREE_VIEW_DROP_BEFORE: result = bg_media_tree_check_move_album_before(w->tree, w->selected_album, drop_album); break; } if(result) { gtk_tree_view_set_drag_dest_row(GTK_TREE_VIEW(w->treeview), path, pos); } } break; case BG_ALBUM_TYPE_PLUGIN: case BG_ALBUM_TYPE_REMOVABLE: case BG_ALBUM_TYPE_TUNER: break; } } gtk_tree_path_free(path); } return TRUE; } static void tree_changed_callback(bg_media_tree_t * t, void * data) { bg_gtk_tree_widget_t * w = (bg_gtk_tree_widget_t *)data; bg_gtk_tree_widget_update(w, 0); /* This is also called during loading of huge amounts of urls, so we update the GUI a bit */ while(gdk_events_pending() || gtk_events_pending()) gtk_main_iteration(); } #if GTK_CHECK_VERSION(2, 21, 6) static void notebook_change_page(GtkWidget * widget, gpointer page, int num, gpointer data) #else static void notebook_change_page(GtkWidget * widget, GtkNotebookPage *page, int num, gpointer data) #endif { bg_gtk_tree_widget_t * wid; bg_gtk_album_window_t * win; wid = (bg_gtk_tree_widget_t*)data; win = g_list_nth_data(wid->album_windows, num); // bg_gtk_tree_widget_t * wid; // wid = (bg_gtk_tree_widget_t *)data; if(wid->album_accel_group) { gtk_window_remove_accel_group(GTK_WINDOW (wid->toplevel_window), wid->album_accel_group); wid->album_accel_group = NULL; } if(win) { wid->album_accel_group = bg_gtk_album_window_get_accel_group(win); gtk_window_add_accel_group(GTK_WINDOW (wid->toplevel_window), wid->album_accel_group); } } static gboolean timeout_func(void * data) { bg_gtk_tree_widget_t * w = data; bg_media_tree_check_sync(w->tree); return TRUE; } /* Constructor */ bg_gtk_tree_widget_t * bg_gtk_tree_widget_create(bg_media_tree_t * tree, GtkAccelGroup * accel_group, GtkWidget * toplevel_window) { GtkWidget * scrolledwindow; GtkWidget * buttonbox; GtkWidget * mainbox; bg_gtk_tree_widget_t * ret; GtkTreeStore *store; GtkCellRenderer *text_renderer; GtkCellRenderer *pixmap_renderer; GtkTreeViewColumn *column; GtkTreeSelection *selection; load_pixmaps(); bg_gtk_tree_create_atoms(); ret = calloc(1, sizeof(*ret)); ret->tree = tree; ret->toplevel_window = toplevel_window; ret->accel_group = accel_group; bg_media_tree_set_change_callback(ret->tree, tree_changed_callback, ret); store = gtk_tree_store_new (NUM_COLUMNS, G_TYPE_STRING, GDK_TYPE_PIXBUF, G_TYPE_INT, G_TYPE_STRING); ret->treeview = gtk_tree_view_new_with_model(GTK_TREE_MODEL(store)); /* Set as drag destination */ gtk_drag_dest_set(ret->treeview, GTK_DEST_DEFAULT_ALL, dnd_dst_entries, sizeof(dnd_dst_entries)/sizeof(dnd_dst_entries[0]), GDK_ACTION_COPY | GDK_ACTION_MOVE); /* gtk_tree_view_enable_model_drag_dest(GTK_TREE_VIEW(ret->treeview), dnd_dst_entries, sizeof(dnd_dst_entries)/sizeof(dnd_dst_entries[0]), GDK_ACTION_COPY); */ // iface = GTK_TREE_DRAG_DEST_GET_IFACE (GTK_TREE_DRAG_DEST(store)); // iface->row_drop_possible = row_drop_possible; /* Set callbacks */ gtk_widget_set_events(ret->treeview, GDK_BUTTON_PRESS_MASK); g_signal_connect(G_OBJECT(ret->treeview), "button-press-event", G_CALLBACK(button_press_callback), (gpointer)ret); g_signal_connect(G_OBJECT(ret->treeview), "row-collapsed", G_CALLBACK(row_collapsed_callback), (gpointer)ret); g_signal_connect(G_OBJECT(ret->treeview), "row-expanded", G_CALLBACK(row_expanded_callback), (gpointer)ret); g_signal_connect(G_OBJECT(ret->treeview), "drag-data-received", G_CALLBACK(drag_received_callback), (gpointer)ret); g_signal_connect(G_OBJECT(ret->treeview), "drag-drop", G_CALLBACK(drag_drop_callback), (gpointer)ret); g_signal_connect(G_OBJECT(ret->treeview), "drag-motion", G_CALLBACK(drag_motion_callback), (gpointer)ret); g_signal_connect(G_OBJECT(ret->treeview), "drag-data-get", G_CALLBACK(drag_get_callback), (gpointer)ret); gtk_tree_view_set_headers_visible(GTK_TREE_VIEW(ret->treeview), 0); gtk_widget_set_size_request(ret->treeview, 200, 300); /* Add the columns */ text_renderer = gtk_cell_renderer_text_new(); pixmap_renderer = gtk_cell_renderer_pixbuf_new(); column = gtk_tree_view_column_new (); gtk_tree_view_column_set_title(column, "Albums"); gtk_tree_view_column_pack_start(column, pixmap_renderer, FALSE); gtk_tree_view_column_pack_end(column, text_renderer, TRUE); gtk_tree_view_column_add_attribute(column, text_renderer, "text", COLUMN_NAME); gtk_tree_view_column_add_attribute(column, text_renderer, "weight", COLUMN_WEIGHT); gtk_tree_view_column_add_attribute(column, text_renderer, "foreground", COLUMN_COLOR); gtk_tree_view_column_add_attribute(column, pixmap_renderer, "pixbuf-expander-closed", COLUMN_PIXMAP); gtk_tree_view_column_add_attribute(column, pixmap_renderer, "pixbuf-expander-open", COLUMN_PIXMAP); gtk_tree_view_column_add_attribute(column, pixmap_renderer, "pixbuf", COLUMN_PIXMAP); // gtk_tree_view_column_set_sort_column_id (column, COLUMN_DEVICE); gtk_tree_view_append_column (GTK_TREE_VIEW(ret->treeview), column); /* Set Selection mode */ selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(ret->treeview)); gtk_tree_selection_set_mode(selection, GTK_SELECTION_SINGLE); ret->select_handler_id = g_signal_connect(G_OBJECT(selection), "changed", G_CALLBACK(select_row_callback), (gpointer)ret); gtk_widget_show(ret->treeview); scrolledwindow = gtk_scrolled_window_new(gtk_tree_view_get_hadjustment(GTK_TREE_VIEW(ret->treeview)), gtk_tree_view_get_vadjustment(GTK_TREE_VIEW(ret->treeview))); gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolledwindow), GTK_POLICY_NEVER, GTK_POLICY_ALWAYS); gtk_container_add(GTK_CONTAINER(scrolledwindow), ret->treeview); gtk_widget_show(scrolledwindow); /* Create buttons */ ret->remove_button = create_pixmap_button(ret, "trash_16.png", TRS("Delete album")); ret->rename_button = create_pixmap_button(ret, "rename_16.png", TRS("Rename album")); ret->goto_current_button = create_pixmap_button(ret, "goto_current_16.png", TRS("Goto current track")); ret->new_button = create_pixmap_button(ret, "folder_new_16.png", TRS("New album")); buttonbox = gtk_hbox_new(0, 0); gtk_box_pack_start(GTK_BOX(buttonbox), ret->new_button, FALSE, FALSE, 0); gtk_box_pack_start(GTK_BOX(buttonbox), ret->remove_button, FALSE, FALSE, 0); gtk_box_pack_start(GTK_BOX(buttonbox), ret->rename_button, FALSE, FALSE, 0); gtk_box_pack_start(GTK_BOX(buttonbox), ret->goto_current_button, FALSE, FALSE, 0); gtk_widget_show(buttonbox); mainbox = gtk_vbox_new(0, 0); bg_gtk_box_pack_start_defaults(GTK_BOX(mainbox), scrolledwindow); gtk_box_pack_start(GTK_BOX(mainbox), buttonbox, FALSE, FALSE, 0); gtk_widget_show(mainbox); /* Create notebook */ ret->notebook = gtk_notebook_new(); if(ret->toplevel_window) { g_signal_connect(G_OBJECT(ret->notebook), "switch-page", G_CALLBACK(notebook_change_page), (gpointer*)ret); } gtk_notebook_set_scrollable(GTK_NOTEBOOK(ret->notebook), TRUE); gtk_notebook_popup_enable(GTK_NOTEBOOK(ret->notebook)); // gtk_widget_show(ret->notebook); /* Create paned */ ret->widget = gtk_hpaned_new(); gtk_paned_add1(GTK_PANED(ret->widget), mainbox); gtk_paned_add2(GTK_PANED(ret->widget), ret->notebook); gtk_widget_show(ret->widget); init_menu(ret); ret->cfg_section = bg_cfg_section_find_subsection(bg_media_tree_get_cfg_section(tree), "gtk_treewidget"); bg_cfg_section_apply(ret->cfg_section, parameters, set_parameter, ret); bg_gtk_tree_widget_update(ret, 1); #ifdef HAVE_INOTIFY ret->timeout_tag = g_timeout_add(500, timeout_func, (gpointer)ret); #endif return ret; } void bg_gtk_tree_widget_destroy(bg_gtk_tree_widget_t * w) { bg_gtk_album_window_t * win; bg_cfg_section_get(w->cfg_section, parameters, get_parameter, w); g_signal_handlers_block_by_func(G_OBJECT(w->notebook), notebook_change_page, w); while(w->album_windows) { win = (bg_gtk_album_window_t*)w->album_windows->data; w->album_windows = g_list_remove(w->album_windows, (gpointer)win); bg_gtk_album_window_destroy(win, 0); } if(w->timeout_tag > 0) g_source_remove(w->timeout_tag); free(w); } bg_media_tree_t * bg_gtk_tree_widget_get_tree(bg_gtk_tree_widget_t * w) { return w->tree; } gmerlin-1.2.0~dfsg/lib/gtk/cfg_dialog.c0000644000175000017500000012121511764363406017662 0ustar alessioalessio/***************************************************************** * gmerlin - a general purpose multimedia framework and applications * * Copyright (c) 2001 - 2011 Members of the Gmerlin project * gmerlin-general@lists.sourceforge.net * http://gmerlin.sourceforge.net * * 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 of the License, 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 this program. If not, see . * *****************************************************************/ #include #include #include #include "gtk_dialog.h" #include #include #include #define LOG_DOMAIN "cfg_dialog" #include enum { COLUMN_NAME, NUM_COLUMNS }; typedef struct dialog_section_s { bg_set_parameter_func_t set_param; bg_get_parameter_func_t get_param; void * callback_data; bg_gtk_widget_t * widgets; int num_widgets; const bg_parameter_info_t * infos; bg_cfg_section_t * cfg_section; /* Dialog sections can be nested */ struct dialog_section_s ** children; int num_children; struct dialog_section_s * parent; /* Index in global notebook */ int notebook_index; bg_gtk_preset_menu_t * preset_menu; bg_cfg_section_t * preset_section; int private_cfg_section; } dialog_section_t; struct bg_dialog_s { GtkWidget * ok_button; GtkWidget * apply_button; GtkWidget * close_button; GtkWidget * window; GtkWidget * mainbox; GtkWidget * action_box; dialog_section_t root_section; int visible; GtkWidget * notebook; GtkWidget * treeview; GtkWidget * scrolledwindow; guint select_handler_id; int result; bg_plugin_registry_t * plugin_reg; bg_gtk_preset_menu_t * preset_menu; bg_cfg_section_t * preset_section; }; static int parent_index(dialog_section_t * s) { int i; if(!s->parent) return -1; for(i = 0; i < s->parent->num_children; i++) { if(s->parent->children[i] == s) return i; } return -1; } static int * section_to_path(bg_dialog_t * d, dialog_section_t * s) { int * ret; int index; dialog_section_t * tmp; int depth; /* Get depth */ tmp = s; depth = 0; while(tmp->parent) { tmp = tmp->parent; depth++; } /* Allocate return value */ ret = malloc((depth+1)*sizeof(*ret)); index = depth; ret[index--] = -1; tmp = s; while(index >= 0) { ret[index--] = parent_index(tmp); tmp = tmp->parent; } return ret; } static void section_to_iter(bg_dialog_t * d, dialog_section_t * s, GtkTreeIter * iter) { int * indices; int i; GtkTreeModel *model; GtkTreePath *path; model = gtk_tree_view_get_model(GTK_TREE_VIEW(d->treeview)); indices = section_to_path(d, s); path = gtk_tree_path_new(); i = 0; while(indices[i] != -1) { gtk_tree_path_append_index(path, indices[i]); i++; } free(indices); gtk_tree_model_get_iter(model, iter, path); gtk_tree_path_free(path); } static dialog_section_t * iter_2_section(bg_dialog_t * d, GtkTreeIter * iter) { dialog_section_t * ret; int i, depth; GtkTreeModel *model; GtkTreePath *path; gint * indices; model = gtk_tree_view_get_model(GTK_TREE_VIEW(d->treeview)); path = gtk_tree_model_get_path(model, iter); indices = gtk_tree_path_get_indices(path); ret = d->root_section.children[indices[0]]; depth = gtk_tree_path_get_depth(path); for(i = 1; i < depth; i++) { ret = ret->children[indices[i]]; } gtk_tree_path_free(path); return ret; } static void reset_section(dialog_section_t * s) { int i; bg_parameter_value_t val; char * pos; bg_cfg_section_t * cfg_subsection; int set_param = 0; for(i = 0; i < s->num_widgets; i++) { if(!s->widgets[i].funcs->get_value) continue; bg_parameter_value_copy(&s->widgets[i].value, &s->widgets[i].last_value, s->widgets[i].info); s->widgets[i].funcs->get_value(&s->widgets[i]); if(s->set_param && (s->widgets[i].info->flags & BG_PARAMETER_SYNC)) { set_param = 1; if((s->widgets[i].info->type == BG_PARAMETER_DEVICE) && (s->widgets[i].value.val_str) && strchr(s->widgets[i].value.val_str, ':')) { val.val_str = bg_strdup(NULL, s->widgets[i].value.val_str); pos = strchr(val.val_str, ':'); if(pos) *pos = '\0'; s->set_param(s->callback_data, s->widgets[i].info->name, &val); free(val.val_str); } else s->set_param(s->callback_data, s->widgets[i].info->name, &s->widgets[i].value); } if(s->cfg_section) { if(s->widgets[i].info->flags & BG_PARAMETER_SYNC) bg_cfg_section_set_parameter(s->cfg_section, s->widgets[i].info, &s->widgets[i].value); /* If we have multi parameters, we'll also reset the subsection, even if BG_PARAMETER_SYNC isn't set */ if(s->widgets[i].cfg_subsection_save) { cfg_subsection = bg_cfg_section_find_subsection(s->cfg_section, s->widgets[i].info->name); bg_cfg_section_transfer(s->widgets[i].cfg_subsection_save, cfg_subsection); } if(s->widgets[i].funcs->apply_sub_params) s->widgets[i].funcs->apply_sub_params(&s->widgets[i]); } } if(set_param) s->set_param(s->callback_data, NULL, NULL); for(i = 0; i < s->num_children; i++) reset_section(s->children[i]); } static void restore_section(dialog_section_t * s, bg_cfg_section_t * cfg_section) { int i; bg_parameter_value_t val; char * pos; int set_param = 0; if(!cfg_section) return; for(i = 0; i < s->num_widgets; i++) { if(!s->widgets[i].funcs->get_value) continue; bg_cfg_section_get_parameter(cfg_section, s->widgets[i].info, &s->widgets[i].value); s->widgets[i].funcs->get_value(&s->widgets[i]); if(s->set_param && (s->widgets[i].info->flags & BG_PARAMETER_SYNC)) { set_param = 1; if((s->widgets[i].info->type == BG_PARAMETER_DEVICE) && (s->widgets[i].value.val_str) && strchr(s->widgets[i].value.val_str, ':')) { val.val_str = bg_strdup(NULL, s->widgets[i].value.val_str); pos = strchr(val.val_str, ':'); if(pos) *pos = '\0'; s->set_param(s->callback_data, s->widgets[i].info->name, &val); free(val.val_str); } else s->set_param(s->callback_data, s->widgets[i].info->name, &s->widgets[i].value); } /* Copy subsections */ if(s->widgets[i].info->multi_parameters) { bg_cfg_section_t * src1, * dst1; dst1 = bg_cfg_section_find_subsection(s->cfg_section, s->widgets[i].info->name); src1 = bg_cfg_section_find_subsection(cfg_section, s->widgets[i].info->name); if(s->widgets[i].info->type == BG_PARAMETER_MULTI_CHAIN) bg_cfg_section_delete_subsections(dst1); bg_cfg_section_transfer_children(src1, dst1); } } if(set_param) s->set_param(s->callback_data, NULL, NULL); } static void apply_section(dialog_section_t * s) { bg_parameter_value_t val; char * pos; int i; bg_cfg_section_t * cfg_subsection; for(i = 0; i < s->num_widgets; i++) { if(!s->widgets[i].funcs->set_value) continue; s->widgets[i].funcs->set_value(&s->widgets[i]); bg_parameter_value_copy(&s->widgets[i].last_value, &s->widgets[i].value, s->widgets[i].info); if(s->cfg_section) { bg_cfg_section_set_parameter(s->cfg_section, s->widgets[i].info, &s->widgets[i].value); } if(s->widgets[i].cfg_subsection_save) { bg_cfg_section_destroy(s->widgets[i].cfg_subsection_save); cfg_subsection = bg_cfg_section_find_subsection(s->cfg_section, s->widgets[i].info->name); s->widgets[i].cfg_subsection_save = bg_cfg_section_copy(cfg_subsection); } if(s->set_param) { if((s->widgets[i].info->type == BG_PARAMETER_DEVICE) && (s->widgets[i].value.val_str) && strchr(s->widgets[i].value.val_str, ':')) { val.val_str = malloc(strlen(s->widgets[i].value.val_str)+1); strcpy(val.val_str, s->widgets[i].value.val_str); pos = strchr(val.val_str, ':'); *pos = '\0'; s->set_param(s->callback_data, s->widgets[i].info->name, &val); free(val.val_str); } else s->set_param(s->callback_data, s->widgets[i].info->name, &s->widgets[i].value); } } if(s->set_param) s->set_param(s->callback_data, NULL, NULL); for(i = 0; i < s->num_children; i++) apply_section(s->children[i]); } static void apply_values(bg_dialog_t * d) { apply_section(&d->root_section); } static void reset_values(bg_dialog_t * d) { reset_section(&d->root_section); } static void button_callback(GtkWidget * w, gpointer * data) { bg_dialog_t * d = (bg_dialog_t *)data; if((w == d->close_button) || (w == d->window)) { reset_values(d); d->visible = 0; gtk_widget_hide(d->window); gtk_main_quit(); } else if(w == d->apply_button) { apply_values(d); d->result = 1; } else if(w == d->ok_button) { d->visible = 0; gtk_widget_hide(d->window); gtk_main_quit(); apply_values(d); d->result = 1; } } static gboolean delete_callback(GtkWidget * w, GdkEventAny * event, gpointer data) { button_callback(w, data); return TRUE; } static void select_row_callback(GtkTreeSelection * sel, gpointer data) { int index = 0; dialog_section_t * selected_section; GtkTreeModel * model; GtkTreeIter iter; bg_dialog_t * d = (bg_dialog_t *)data; if(!gtk_tree_selection_get_selected(sel, &model, &iter)) index = 0; else { selected_section = iter_2_section(d, &iter); index = selected_section->notebook_index; } gtk_notebook_set_current_page(GTK_NOTEBOOK(d->notebook), index); } static bg_dialog_t * create_dialog(const char * title) { bg_dialog_t * ret; GtkWidget * buttonbox; GtkWidget * label, *tab_label; GtkWidget * hbox; GtkTreeStore *store; GtkCellRenderer *text_renderer; GtkTreeViewColumn *column; GtkTreeSelection *selection; ret = calloc(1, sizeof(*ret)); ret->window = bg_gtk_window_new(GTK_WINDOW_TOPLEVEL); gtk_window_set_position(GTK_WINDOW(ret->window), GTK_WIN_POS_CENTER_ON_PARENT); gtk_window_set_title(GTK_WINDOW(ret->window), title); ret->apply_button = gtk_button_new_from_stock(GTK_STOCK_APPLY); ret->close_button = gtk_button_new_from_stock(GTK_STOCK_CLOSE); ret->ok_button = gtk_button_new_from_stock(GTK_STOCK_OK); bg_gtk_widget_set_can_default(ret->apply_button, TRUE); bg_gtk_widget_set_can_default(ret->close_button, TRUE); bg_gtk_widget_set_can_default(ret->ok_button, TRUE); gtk_window_set_modal(GTK_WINDOW(ret->window), TRUE); g_signal_connect(G_OBJECT(ret->ok_button), "clicked", G_CALLBACK(button_callback), (gpointer)ret); g_signal_connect(G_OBJECT(ret->close_button), "clicked", G_CALLBACK(button_callback), (gpointer)ret); g_signal_connect(G_OBJECT(ret->apply_button), "clicked", G_CALLBACK(button_callback), (gpointer)ret); g_signal_connect(G_OBJECT(ret->window), "delete_event", G_CALLBACK(delete_callback), (gpointer)ret); bg_gtk_widget_set_can_default(ret->close_button, TRUE); bg_gtk_widget_set_can_default(ret->apply_button, TRUE); bg_gtk_widget_set_can_default(ret->ok_button, TRUE); gtk_widget_show(ret->apply_button); gtk_widget_show(ret->close_button); gtk_widget_show(ret->ok_button); /* Create notebook */ ret->notebook = gtk_notebook_new(); label = gtk_label_new(TR("No options here, choose subcategory")); tab_label = gtk_label_new(""); gtk_widget_show(label); gtk_widget_show(tab_label); gtk_notebook_set_show_tabs(GTK_NOTEBOOK(ret->notebook), 0); gtk_notebook_append_page(GTK_NOTEBOOK(ret->notebook), label, tab_label); gtk_widget_show(ret->notebook); /* Create treeview */ store = gtk_tree_store_new (NUM_COLUMNS, G_TYPE_STRING); ret->treeview = gtk_tree_view_new_with_model(GTK_TREE_MODEL(store)); gtk_tree_view_set_headers_visible(GTK_TREE_VIEW(ret->treeview), 0); // gtk_widget_set_size_request(ret->treeview, 200, 300); text_renderer = gtk_cell_renderer_text_new(); column = gtk_tree_view_column_new (); gtk_tree_view_column_pack_start(column, text_renderer, TRUE); gtk_tree_view_column_add_attribute(column, text_renderer, "text", COLUMN_NAME); gtk_tree_view_append_column (GTK_TREE_VIEW(ret->treeview), column); selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(ret->treeview)); gtk_tree_selection_set_mode(selection, GTK_SELECTION_SINGLE); ret->select_handler_id = g_signal_connect(G_OBJECT(selection), "changed", G_CALLBACK(select_row_callback), (gpointer)ret); gtk_widget_show(ret->treeview); ret->scrolledwindow = gtk_scrolled_window_new(gtk_tree_view_get_hadjustment(GTK_TREE_VIEW(ret->treeview)), gtk_tree_view_get_vadjustment(GTK_TREE_VIEW(ret->treeview))); gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(ret->scrolledwindow), GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC); gtk_container_add(GTK_CONTAINER(ret->scrolledwindow), ret->treeview); gtk_widget_show(ret->scrolledwindow); /* Create the rest */ hbox = gtk_hpaned_new(); gtk_paned_add1(GTK_PANED(hbox), ret->scrolledwindow); gtk_paned_add2(GTK_PANED(hbox), ret->notebook); gtk_widget_show(hbox); ret->action_box = gtk_hbox_new(FALSE, 0); ret->mainbox = gtk_vbox_new(0, 5); gtk_box_pack_start(GTK_BOX(ret->mainbox), hbox, TRUE, TRUE, 0); gtk_box_pack_start(GTK_BOX(ret->mainbox), ret->action_box, FALSE, FALSE, 0); buttonbox = gtk_hbutton_box_new(); gtk_box_set_spacing(GTK_BOX(buttonbox), 10); gtk_container_set_border_width(GTK_CONTAINER(buttonbox), 10); gtk_container_add(GTK_CONTAINER(buttonbox), ret->ok_button); gtk_container_add(GTK_CONTAINER(buttonbox), ret->apply_button); gtk_container_add(GTK_CONTAINER(buttonbox), ret->close_button); gtk_widget_show(buttonbox); gtk_box_pack_end(GTK_BOX(ret->mainbox), buttonbox, FALSE, FALSE, 0); gtk_widget_show(ret->mainbox); gtk_container_add(GTK_CONTAINER(ret->window), ret->mainbox); gtk_widget_realize(ret->window); return ret; } static void restore_button_callback(GtkWidget * w, gpointer data) { dialog_section_t * section = data; bg_cfg_section_t * tmp_section; // fprintf(stderr, "Restore factory defaults %p\n", section); tmp_section = bg_cfg_section_copy(section->cfg_section); bg_cfg_section_restore_defaults(tmp_section, section->widgets[0].info); restore_section(section, tmp_section); bg_cfg_section_destroy(tmp_section); } static GtkWidget * create_restore_button(dialog_section_t * section) { GtkWidget * button; GtkWidget * image; char * path; path = bg_search_file_read("icons", "refresh_16.png"); if(path) { image = gtk_image_new_from_file(path); free(path); } else image = gtk_image_new(); gtk_widget_show(image); button = gtk_button_new(); gtk_container_add(GTK_CONTAINER(button), image); g_signal_connect(G_OBJECT(button), "clicked", G_CALLBACK(restore_button_callback), section); gtk_widget_show(button); bg_gtk_tooltips_set_tip(button, "Restore factory defaults", PACKAGE); return button; } static void preset_load_callback(void * data) { dialog_section_t * s = data; restore_section(s, s->preset_section); } static void preset_save_callback(void * data) { int i; dialog_section_t * s = data; // fprintf(stderr, "preset_save_callback %p\n", data); for(i = 0; i < s->num_widgets; i++) { if(!s->widgets[i].funcs->set_value) continue; s->widgets[i].funcs->set_value(&s->widgets[i]); bg_cfg_section_set_parameter(s->preset_section, s->widgets[i].info, &s->widgets[i].value); if(s->widgets[i].info->multi_parameters) { bg_cfg_section_t * src1; bg_cfg_section_t * dst1; src1 = bg_cfg_section_find_subsection(s->cfg_section, s->widgets[i].info->name); dst1 = bg_cfg_section_find_subsection(s->preset_section, s->widgets[i].info->name); if(s->widgets[i].info->type == BG_PARAMETER_MULTI_CHAIN) bg_cfg_section_delete_subsections(dst1); bg_cfg_section_transfer_children(src1, dst1); } } } static GtkWidget * create_section(dialog_section_t * section, const bg_parameter_info_t * info, bg_cfg_section_t * s, bg_set_parameter_func_t set_param, bg_get_parameter_func_t get_param, void * data, const char * translation_domain, bg_plugin_registry_t * plugin_reg, bg_cfg_section_t * preset_section) { int i, count, j; int row, column, num_columns; bg_cfg_section_t * cfg_subsection; GtkWidget * table; GtkWidget * label; GtkWidget * action_box; GtkWidget * vbox; GtkWidget * restore_button; /* If info == NULL, we create a label, which tell the user, that there is nothing to do */ if(!info) { table = gtk_table_new(1, 1, 0); label = gtk_label_new(TR("No options available")); gtk_widget_show(label); gtk_table_attach(GTK_TABLE(table), label, 0, 1, 0, 1, GTK_FILL|GTK_EXPAND, GTK_FILL|GTK_EXPAND, 0, 0); gtk_widget_show(table); return table; } // fprintf(stderr, "create section %p %p %p\n", section, s, preset_section); section->num_widgets = 0; i = 0; if(info[0].type == BG_PARAMETER_SECTION) i++; while(info[i].name && (info[i].type != BG_PARAMETER_SECTION)) { if(!(info[i].flags & BG_PARAMETER_HIDE_DIALOG)) section->num_widgets++; i++; } section->infos = info; if((info[0].type == BG_PARAMETER_SECTION) && (info[0].flags & BG_PARAMETER_OWN_SECTION)) section->cfg_section = bg_cfg_section_find_subsection(s, info[0].name); else section->cfg_section = s; section->callback_data = data; section->set_param = set_param; section->get_param = get_param; /* Now, create and place all widgets */ table = gtk_table_new(1, 1, 0); gtk_table_set_col_spacings(GTK_TABLE(table), 5); gtk_table_set_row_spacings(GTK_TABLE(table), 5); gtk_container_set_border_width(GTK_CONTAINER(table), 5); row = 0; column = 0; num_columns = 1; section->widgets = calloc(section->num_widgets, sizeof(bg_gtk_widget_t)); i = 0; count = 0; while(count < section->num_widgets) { if(info[i].gettext_domain) translation_domain = info[i].gettext_domain; if(info[i].gettext_directory) bg_bindtextdomain(translation_domain, info[i].gettext_directory); /* Check what to skip */ if((info[i].flags & BG_PARAMETER_HIDE_DIALOG) || ((info[i].type == BG_PARAMETER_BUTTON) && !set_param) || (info[i].type == BG_PARAMETER_SECTION)) { i++; continue; } if((info[i].flags & BG_PARAMETER_PLUGIN)) { section->widgets[count].plugin_reg = plugin_reg; if(!section->cfg_section) { section->cfg_section = bg_cfg_section_create(NULL); section->private_cfg_section = 1; } } if((info[i].flags & BG_PARAMETER_SYNC) || (info[i].type == BG_PARAMETER_BUTTON)) { section->widgets[count].change_callback = set_param; section->widgets[count].change_callback_data = data; } section->widgets[count].info = &info[i]; section->widgets[count].cfg_section = section->cfg_section; if(info[i].multi_parameters && section->cfg_section) { cfg_subsection = bg_cfg_section_find_subsection(section->cfg_section, info[i].name); /* Add references to the plugin registry */ if(section->widgets[count].plugin_reg) { j = 0; while(info[i].multi_names[j]) { bg_cfg_section_add_ref(cfg_subsection, bg_plugin_registry_get_section(section->widgets[count].plugin_reg, info[i].multi_names[j])); j++; } } section->widgets[count].cfg_subsection_save = bg_cfg_section_copy(cfg_subsection); } switch(info[i].type) { case BG_PARAMETER_BUTTON: bg_gtk_create_button(§ion->widgets[count], translation_domain); break; case BG_PARAMETER_CHECKBUTTON: bg_gtk_create_checkbutton(§ion->widgets[count], translation_domain); break; case BG_PARAMETER_INT: bg_gtk_create_int(§ion->widgets[count], translation_domain); break; case BG_PARAMETER_FLOAT: bg_gtk_create_float(§ion->widgets[count], translation_domain); break; case BG_PARAMETER_SLIDER_INT: bg_gtk_create_slider_int(§ion->widgets[count], translation_domain); break; case BG_PARAMETER_TIME: bg_gtk_create_time(§ion->widgets[count], translation_domain); break; case BG_PARAMETER_SLIDER_FLOAT: bg_gtk_create_slider_float(§ion->widgets[count], translation_domain); break; case BG_PARAMETER_STRING: case BG_PARAMETER_STRING_HIDDEN: bg_gtk_create_string(§ion->widgets[count], translation_domain); break; case BG_PARAMETER_STRINGLIST: bg_gtk_create_stringlist(§ion->widgets[count], translation_domain); break; case BG_PARAMETER_COLOR_RGB: bg_gtk_create_color_rgb(§ion->widgets[count], translation_domain); break; case BG_PARAMETER_COLOR_RGBA: bg_gtk_create_color_rgba(§ion->widgets[count], translation_domain); break; case BG_PARAMETER_FILE: bg_gtk_create_file(§ion->widgets[count], translation_domain); break; case BG_PARAMETER_DIRECTORY: bg_gtk_create_directory(§ion->widgets[count], translation_domain); break; case BG_PARAMETER_FONT: bg_gtk_create_font(§ion->widgets[count], translation_domain); break; case BG_PARAMETER_DEVICE: bg_gtk_create_device(§ion->widgets[count], translation_domain); break; case BG_PARAMETER_MULTI_MENU: bg_gtk_create_multi_menu(§ion->widgets[count], set_param, get_param, data, translation_domain); break; case BG_PARAMETER_MULTI_LIST: bg_gtk_create_multi_list(§ion->widgets[count], set_param, get_param, data, translation_domain); break; case BG_PARAMETER_MULTI_CHAIN: bg_gtk_create_multi_chain(§ion->widgets[count], set_param, get_param, data, translation_domain); break; case BG_PARAMETER_POSITION: bg_gtk_create_position(§ion->widgets[count], translation_domain); break; case BG_PARAMETER_SECTION: break; } section->widgets[count].funcs->attach(section->widgets[count].priv, table, &row, &num_columns); /* Get the value from the get_param function */ if(get_param && get_param(data, info[i].name, §ion->widgets[count].value)) ; /* .. or from the config data... */ else if(section->cfg_section) bg_cfg_section_get_parameter(section->cfg_section, &info[i], §ion->widgets[count].value); /* ... or from the parameter default */ else bg_parameter_value_copy(§ion->widgets[count].value, &info[i].val_default, &info[i]); bg_parameter_value_copy(§ion->widgets[count].last_value, §ion->widgets[count].value, &info[i]); if(section->widgets[count].info->flags & BG_PARAMETER_SYNC) bg_gtk_change_callback_block(§ion->widgets[count], 1); if(section->widgets[count].funcs->get_value) { section->widgets[count].funcs->get_value(§ion->widgets[count]); if(section->widgets[count].info->flags & BG_PARAMETER_SYNC) bg_gtk_change_callback_block(§ion->widgets[count], 0); } i++; count++; } if(section->cfg_section) { /* Create action box */ gtk_table_resize(GTK_TABLE(table), row+1, num_columns); restore_button = create_restore_button(section); action_box = gtk_hbox_new(FALSE, 0); gtk_box_pack_start(GTK_BOX(action_box), restore_button, FALSE, FALSE, 0); if(!preset_section && (info[0].preset_path || (section->num_widgets && section->widgets[0].info->preset_path))) { section->preset_section = bg_cfg_section_copy(section->cfg_section); section->preset_menu = bg_gtk_preset_menu_create(info[0].preset_path, section->preset_section, preset_load_callback, preset_save_callback, section); gtk_box_pack_start(GTK_BOX(action_box), bg_gtk_preset_menu_get_widget(section->preset_menu), FALSE, FALSE, 0); } else section->preset_section = preset_section; gtk_widget_show(action_box); vbox = gtk_vbox_new(FALSE, 0); gtk_box_pack_end(GTK_BOX(vbox), action_box, FALSE, FALSE, 0); gtk_widget_show(vbox); gtk_table_attach_defaults(GTK_TABLE(table), vbox, 0, num_columns-1, row, row+1); } gtk_widget_show(table); return table; } static int count_sections(const bg_parameter_info_t * info) { int ret = 0; int i = 0; if(!info[0].name) return 0; if(info[0].type == BG_PARAMETER_SECTION) { while(info[i].name) { if(info[i].type == BG_PARAMETER_SECTION) ret++; i++; } return ret; } return 0; } static void preset_load_callback_global(void * data) { int i; bg_dialog_t * d = data; for(i = 0; i < d->root_section.num_children; i++) preset_load_callback(d->root_section.children[i]); } static void preset_save_callback_global(void * data) { int i; bg_dialog_t * d = data; for(i = 0; i < d->root_section.num_children; i++) preset_save_callback(d->root_section.children[i]); } bg_dialog_t * bg_dialog_create(bg_cfg_section_t * section, bg_set_parameter_func_t set_param, bg_get_parameter_func_t get_param, void * callback_data, const bg_parameter_info_t * info, const char * title) { int i, index; int num_sections; GtkWidget * label; GtkWidget * table; bg_cfg_section_t * preset_subsection; GtkTreeIter root_iter; GtkTreeModel * model; const char * translation_domain = NULL; bg_dialog_t * ret = create_dialog(title); // fprintf(stderr, "bg_dialog_create\n"); num_sections = count_sections(info); model = gtk_tree_view_get_model(GTK_TREE_VIEW(ret->treeview)); if((info->flags & BG_PARAMETER_GLOBAL_PRESET) && (info->preset_path)) { ret->preset_section = bg_cfg_section_create(NULL); ret->preset_menu = bg_gtk_preset_menu_create(info->preset_path, ret->preset_section, preset_load_callback_global, preset_save_callback_global, ret); gtk_box_pack_start(GTK_BOX(ret->action_box), bg_gtk_preset_menu_get_widget(ret->preset_menu), FALSE, FALSE, 0); gtk_widget_show(ret->action_box); } if(num_sections) { ret->root_section.num_children = num_sections; ret->root_section.children = calloc(ret->root_section.num_children, sizeof(*ret->root_section.children)); index = 0; for(i = 0; i < ret->root_section.num_children; i++) { ret->root_section.children[i] = calloc(1, sizeof(*ret->root_section.children[i])); if(info[index].gettext_domain) translation_domain = info[i].gettext_domain; if(info[index].gettext_directory) bg_bindtextdomain(translation_domain, info[i].gettext_directory); label = gtk_label_new(TR_DOM(info[index].long_name)); gtk_widget_show(label); gtk_tree_store_append(GTK_TREE_STORE(model), &root_iter, NULL); gtk_tree_store_set(GTK_TREE_STORE(model), &root_iter, COLUMN_NAME, TR_DOM(info[index].long_name), -1); if(ret->preset_section) preset_subsection = bg_cfg_section_find_subsection(ret->preset_section, info[index].name); else preset_subsection = NULL; table = create_section(ret->root_section.children[i], &info[index], section, set_param, get_param, callback_data, translation_domain, ret->plugin_reg, preset_subsection); ret->root_section.children[i]->notebook_index = gtk_notebook_get_n_pages(GTK_NOTEBOOK(ret->notebook)); gtk_notebook_append_page(GTK_NOTEBOOK(ret->notebook), table, label); ret->root_section.children[i]->parent = &ret->root_section; // while(info[index].type == BG_PARAMETER_SECTION) index++; while(info[index].name && (info[index].type != BG_PARAMETER_SECTION)) index++; } } else { label = gtk_label_new(title); gtk_widget_show(label); ret->root_section.num_children = 1; ret->root_section.children = calloc(ret->root_section.num_children, sizeof(*ret->root_section.children)); ret->root_section.children[0] = calloc(1, sizeof(*ret->root_section.children[0])); table = create_section(*ret->root_section.children, info, section, set_param, get_param, callback_data, NULL, ret->plugin_reg, NULL); gtk_notebook_append_page(GTK_NOTEBOOK(ret->notebook), table, label); gtk_notebook_set_current_page(GTK_NOTEBOOK(ret->notebook), 1); gtk_widget_hide(ret->scrolledwindow); } return ret; } bg_dialog_t * bg_dialog_create_multi(const char * title) { bg_dialog_t * ret = create_dialog(title); return ret; } void bg_dialog_add_child(bg_dialog_t *d, void * _parent, const char * name, bg_cfg_section_t * section, bg_set_parameter_func_t set_param, bg_get_parameter_func_t get_param, void * callback_data, const bg_parameter_info_t * info) { GtkTreeIter iter, parent_iter; int num_items; int num_sections; GtkWidget * table; GtkWidget * tab_label; int i, item_index, section_index; GtkTreeModel *model; const char * translation_domain = NULL; dialog_section_t * parent = (dialog_section_t*)_parent; // fprintf(stderr, "bg_dialog_add_child %s %p\n", info->name, section); num_items = 0; num_sections = 0; model = gtk_tree_view_get_model(GTK_TREE_VIEW(d->treeview)); if(info) { while(info[num_items+num_sections].name) { if(info[num_items+num_sections].type == BG_PARAMETER_SECTION) num_sections++; else num_items++; } } if(!num_sections) { parent->children = realloc(parent->children, (parent->num_children+1)*sizeof(*parent->children)); parent->children[parent->num_children] = calloc(1, sizeof(*parent->children[parent->num_children])); table = create_section(parent->children[parent->num_children], info, section, set_param, get_param, callback_data, NULL, d->plugin_reg, NULL); tab_label = gtk_label_new(name); gtk_widget_show(tab_label); parent->children[parent->num_children]->notebook_index = gtk_notebook_get_n_pages(GTK_NOTEBOOK(d->notebook)); gtk_notebook_append_page(GTK_NOTEBOOK(d->notebook), table, tab_label); if(parent == &d->root_section) { gtk_tree_store_append(GTK_TREE_STORE(model), &iter, NULL); } else { section_to_iter(d, parent, &parent_iter); gtk_tree_store_append(GTK_TREE_STORE(model), &iter, &parent_iter); } gtk_tree_store_set(GTK_TREE_STORE(model), &iter, COLUMN_NAME, name, -1); parent->children[parent->num_children]->parent = parent; parent->num_children++; } else { parent->children = realloc(parent->children, (parent->num_children+num_sections)* sizeof(dialog_section_t)); item_index = 0; section_index = parent->num_children; for(i = 0; i < num_sections; i++) { parent->children[section_index] = calloc(1, sizeof(*parent->children[section_index])); if(info[item_index].gettext_domain) translation_domain = info[item_index].gettext_domain; if(info[item_index].gettext_directory) bg_bindtextdomain(translation_domain, info[item_index].gettext_directory); tab_label = gtk_label_new(TR_DOM(info[item_index].long_name)); gtk_widget_show(tab_label); if(parent == &d->root_section) { parent = (dialog_section_t*)_parent; gtk_tree_store_append(GTK_TREE_STORE(model), &iter, NULL); } else { section_to_iter(d, parent, &parent_iter); gtk_tree_store_append(GTK_TREE_STORE(model), &iter, &parent_iter); } gtk_tree_store_set(GTK_TREE_STORE(model), &iter, COLUMN_NAME, info[item_index].long_name, -1); table = create_section(parent->children[section_index], &info[item_index], section, set_param, get_param, callback_data, translation_domain, d->plugin_reg, NULL); parent->children[section_index]->parent = parent; parent->children[section_index]->notebook_index = gtk_notebook_get_n_pages(GTK_NOTEBOOK(d->notebook)); gtk_notebook_append_page(GTK_NOTEBOOK(d->notebook), table, tab_label); item_index++; while((info[item_index].name) && (info[item_index].type != BG_PARAMETER_SECTION)) item_index++; section_index++; } parent->num_children += num_sections; } } void bg_dialog_add(bg_dialog_t *d, const char * name, bg_cfg_section_t * section, bg_set_parameter_func_t set_param, bg_get_parameter_func_t get_param, void * callback_data, const bg_parameter_info_t * info) { bg_dialog_add_child(d, &d->root_section, name, section, set_param, get_param, callback_data, info); } int bg_dialog_show(bg_dialog_t * d, void * parent) { GtkWidget * parent_w; d->result = 0; if(d->visible) { gtk_window_present(GTK_WINDOW(d->window)); return 0; } if(parent) { parent_w = (GtkWidget*)parent; parent_w = bg_gtk_get_toplevel(parent_w); if(parent_w) gtk_window_set_transient_for(GTK_WINDOW(d->window), GTK_WINDOW(parent_w)); } d->visible = 1; gtk_widget_show(d->window); gtk_widget_grab_default(d->ok_button); gtk_widget_grab_focus(d->ok_button); gtk_main(); return d->result; } static void destroy_section(dialog_section_t * s) { int i; if(s->num_widgets) { for(i = 0; i < s->num_widgets; i++) { s->widgets[i].funcs->destroy(&s->widgets[i]); bg_parameter_value_free(&s->widgets[i].value, s->widgets[i].info->type); bg_parameter_value_free(&s->widgets[i].last_value, s->widgets[i].info->type); if(s->widgets[i].cfg_subsection_save) bg_cfg_section_destroy(s->widgets[i].cfg_subsection_save); } free(s->widgets); } if(s->children) { for(i = 0; i < s->num_children; i++) { destroy_section(s->children[i]); free(s->children[i]); } free(s->children); } if(s->preset_menu) { bg_gtk_preset_menu_destroy(s->preset_menu); if(s->preset_section) bg_cfg_section_destroy(s->preset_section); } if(s->private_cfg_section) bg_cfg_section_destroy(s->cfg_section); } void bg_dialog_destroy(bg_dialog_t * d) { destroy_section(&d->root_section); gtk_widget_destroy(d->window); free(d); } void bg_gtk_change_callback(GtkWidget * gw, gpointer data) { bg_gtk_widget_t * w = (bg_gtk_widget_t*)data; w->funcs->set_value(w); if(w->change_callback) { w->change_callback(w->change_callback_data, w->info->name, &w->value); if(w->funcs->apply_sub_params) w->funcs->apply_sub_params(w); w->change_callback(w->change_callback_data, NULL, NULL); } } void bg_gtk_change_callback_block(bg_gtk_widget_t * w, int block) { if(block) { if(w->callback_widget) g_signal_handler_block(w->callback_widget, w->callback_id); if(w->callback_widget_2) g_signal_handler_block(w->callback_widget_2, w->callback_id_2); } else { if(w->callback_widget) g_signal_handler_unblock(w->callback_widget, w->callback_id); if(w->callback_widget_2) g_signal_handler_unblock(w->callback_widget_2, w->callback_id_2); } } void * bg_dialog_add_parent(bg_dialog_t *d, void * _parent, const char * label) { GtkTreeIter iter, parent_iter; dialog_section_t * parent; GtkTreeModel *model; model = gtk_tree_view_get_model(GTK_TREE_VIEW(d->treeview)); if(_parent) { parent = (dialog_section_t*)_parent; section_to_iter(d, parent, &parent_iter); gtk_tree_store_append(GTK_TREE_STORE(model), &iter, &parent_iter); } else { parent = &d->root_section; gtk_tree_store_append(GTK_TREE_STORE(model), &iter, NULL); } gtk_tree_store_set(GTK_TREE_STORE(model), &iter, COLUMN_NAME, label, -1); parent->children = realloc(parent->children, sizeof(*(parent->children))*(parent->num_children+1)); parent->children[parent->num_children] = calloc(1, sizeof(*parent->children[parent->num_children])); parent->children[parent->num_children]->parent = parent; parent->num_children++; return parent->children[parent->num_children-1]; } void bg_dialog_set_plugin_registry(bg_dialog_t * d, bg_plugin_registry_t * plugin_reg) { d->plugin_reg = plugin_reg; } gmerlin-1.2.0~dfsg/lib/gtk/multiinfo.c0000644000175000017500000001135411764363406017614 0ustar alessioalessio/***************************************************************** * gmerlin - a general purpose multimedia framework and applications * * Copyright (c) 2001 - 2011 Members of the Gmerlin project * gmerlin-general@lists.sourceforge.net * http://gmerlin.sourceforge.net * * 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 of the License, 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 this program. If not, see . * *****************************************************************/ #include #include #include #include #include #include #include #include typedef struct { GtkWidget * window; GtkWidget * close_button; bg_gtk_textview_t * textview1; bg_gtk_textview_t * textview2; } multiwindow_t; static void button_callback(GtkWidget * w, gpointer data) { multiwindow_t * win; win = (multiwindow_t*)data; bg_gtk_textview_destroy(win->textview1); bg_gtk_textview_destroy(win->textview2); gtk_widget_hide(win->window); gtk_widget_destroy(win->window); free(win); } static gboolean delete_callback(GtkWidget * w, GdkEventAny * event, gpointer data) { button_callback(w, data); return TRUE; } static multiwindow_t * multiwindow_create(const char * title, const char * properties, const char * description) { GtkWidget * table; GtkWidget * frame; multiwindow_t * ret; ret = calloc(1, sizeof(*ret)); ret->window = bg_gtk_window_new(GTK_WINDOW_TOPLEVEL); gtk_window_set_position(GTK_WINDOW(ret->window), GTK_WIN_POS_CENTER_ON_PARENT); g_signal_connect(G_OBJECT(ret->window), "delete_event", G_CALLBACK(delete_callback), (gpointer)ret); gtk_window_set_title(GTK_WINDOW(ret->window), title); /* Create close button */ ret->close_button = gtk_button_new_from_stock(GTK_STOCK_CLOSE); bg_gtk_widget_set_can_default(ret->close_button, TRUE); g_signal_connect(G_OBJECT(ret->close_button), "clicked", G_CALLBACK(button_callback), (gpointer)ret); gtk_widget_show(ret->close_button); /* Create texts */ ret->textview1 = bg_gtk_textview_create(); bg_gtk_textview_update(ret->textview1, properties); ret->textview2 = bg_gtk_textview_create(); bg_gtk_textview_update(ret->textview2, description); table = gtk_table_new(3, 1, 0); gtk_table_set_row_spacings(GTK_TABLE(table), 5); gtk_table_set_col_spacings(GTK_TABLE(table), 5); gtk_container_set_border_width(GTK_CONTAINER(table), 5); frame = gtk_frame_new("Properties"); gtk_container_add(GTK_CONTAINER(frame), bg_gtk_textview_get_widget(ret->textview1)); gtk_widget_show(frame); gtk_table_attach_defaults(GTK_TABLE(table), frame, 0, 1, 0, 1); frame = gtk_frame_new("Description"); gtk_container_add(GTK_CONTAINER(frame), bg_gtk_textview_get_widget(ret->textview2)); gtk_widget_show(frame); gtk_table_attach_defaults(GTK_TABLE(table), frame, 0, 1, 1, 2); gtk_table_attach(GTK_TABLE(table), ret->close_button, 0, 1, 2, 3, GTK_SHRINK, GTK_SHRINK, 0, 0); gtk_widget_show(table); gtk_container_add(GTK_CONTAINER(ret->window), table); return ret; } static void multiwindow_show(multiwindow_t * w, int modal) { gtk_window_set_modal(GTK_WINDOW(w->window), modal); gtk_widget_grab_default(w->close_button); gtk_widget_show(w->window); } void bg_gtk_multi_info_show(const bg_parameter_info_t * info, int i, const char * translation_domain, GtkWidget * parent) { char * text; multiwindow_t * win; text = bg_sprintf(TR("Name:\t %s\nLabel:\t %s"), info->multi_names[i], (info->multi_labels?TR_DOM(info->multi_labels[i]):info->multi_names[i])); win = multiwindow_create(info->long_name, text, info->multi_descriptions ? info->multi_descriptions[i] : TR("Not available")); free(text); parent = bg_gtk_get_toplevel(parent); if(parent) gtk_window_set_transient_for(GTK_WINDOW(win->window), GTK_WINDOW(parent)); multiwindow_show(win, 1); } gmerlin-1.2.0~dfsg/lib/gtk/cfg_color.c0000644000175000017500000002742611764363406017552 0ustar alessioalessio/***************************************************************** * gmerlin - a general purpose multimedia framework and applications * * Copyright (c) 2001 - 2011 Members of the Gmerlin project * gmerlin-general@lists.sourceforge.net * http://gmerlin.sourceforge.net * * 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 of the License, 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 this program. If not, see . * *****************************************************************/ #include #include #include "gtk_dialog.h" #include typedef struct { GtkWidget * button; GtkWidget * label; GtkWidget * drawingarea; GtkWidget * colorsel; GdkDrawable * background_pixmap; GdkColor gdk_color_1; GdkColor gdk_color_2; GdkGC * gc; int has_alpha; GdkColor color; GdkColor last_color; guint16 alpha; } color_t; static void button_callback(GtkWidget * w, gpointer data); static void destroy(bg_gtk_widget_t * w) { color_t * priv = (color_t *)w->priv; if(priv->colorsel) gtk_widget_destroy(priv->colorsel); if(priv->gc) gdk_gc_unref(priv->gc); if(priv->background_pixmap) gdk_drawable_unref(priv->background_pixmap); free(priv); } static const guint16 background_color_1[3] = { 0xc0c0, 0xc0c0, 0xc0c0 }; static const guint16 background_color_2[3] = { 0x8080, 0x8080, 0x8080 }; static void set_button(color_t * c) { GdkRectangle rect; guint32 i_tmp; int depth; if(!c->drawingarea->window) return; if(c->has_alpha) { i_tmp = (c->color.red * c->alpha + background_color_1[0] * (0xffff - c->alpha)) >> 16; c->gdk_color_1.red = (guint16)(i_tmp); i_tmp = (c->color.green * c->alpha + background_color_1[1] * (0xffff - c->alpha)) >> 16; c->gdk_color_1.green = (guint16)(i_tmp); i_tmp = (c->color.blue * c->alpha + background_color_1[2] * (0xffff - c->alpha)) >> 16; c->gdk_color_1.blue = (guint16)(i_tmp); c->gdk_color_1.pixel = (c->gdk_color_1.red >> 8) << 16 | (c->gdk_color_1.green >> 8) << 8 | (c->gdk_color_1.blue >> 8); i_tmp = (c->color.red * c->alpha + background_color_2[0] * (0xffff - c->alpha)) >> 16; c->gdk_color_2.red = (guint16)(i_tmp); i_tmp = (c->color.green * c->alpha + background_color_2[1] * (0xffff - c->alpha)) >> 16; c->gdk_color_2.green = (guint16)(i_tmp); i_tmp = (c->color.blue * c->alpha + background_color_2[2] * (0xffff - c->alpha)) >> 16; c->gdk_color_2.blue = (guint16)(i_tmp); c->gdk_color_2.pixel = (c->gdk_color_2.red >> 8) << 16 | (c->gdk_color_2.green >> 8) << 8 | (c->gdk_color_2.blue >> 8); gdk_color_alloc(gdk_window_get_colormap(c->drawingarea->window), &c->gdk_color_1); gdk_color_alloc(gdk_window_get_colormap(c->drawingarea->window), &c->gdk_color_2); gdk_gc_set_foreground(c->gc, &c->gdk_color_1); gdk_draw_rectangle(c->background_pixmap, c->gc, 1, 0, 0, 16, 16); gdk_draw_rectangle(c->background_pixmap, c->gc, 1, 16, 16, 16, 16); gdk_gc_set_foreground(c->gc, &c->gdk_color_2); gdk_draw_rectangle(c->background_pixmap, c->gc, 1, 16, 0, 16, 16); gdk_draw_rectangle(c->background_pixmap, c->gc, 1, 0, 16, 16, 16); } else { gdk_color_alloc(gdk_window_get_colormap(c->drawingarea->window), &c->color); gdk_gc_set_foreground(c->gc, &c->color); gdk_draw_rectangle(c->background_pixmap, c->gc, 1, 0, 0, 32, 32); gdk_window_set_background(c->drawingarea->window, &c->color); } gdk_window_get_geometry(c->drawingarea->window, &rect.x, &rect.y, &rect.width, &rect.height, &depth); rect.x = 0; rect.y = 0; gdk_window_invalidate_rect(c->drawingarea->window, &rect, TRUE); } static void get_value(bg_gtk_widget_t * w) { color_t * priv; priv = (color_t*)(w->priv); priv->color.red = (guint16)(w->value.val_color[0]*65535.0); priv->color.green = (guint16)(w->value.val_color[1]*65535.0); priv->color.blue = (guint16)(w->value.val_color[2]*65535.0); if(priv->has_alpha) priv->alpha = (guint16)(w->value.val_color[3]*65535.0); else priv->alpha = 0xffff; set_button(priv); } static void set_value(bg_gtk_widget_t * w) { color_t * priv; priv = (color_t*)(w->priv); w->value.val_color[0] = (float)priv->color.red/65535.0; w->value.val_color[1] = (float)priv->color.green/65535.0; w->value.val_color[2] = (float)priv->color.blue/65535.0; if(priv->has_alpha) w->value.val_color[3] = (float)priv->alpha/65535.0; else w->value.val_color[3] = 1.0; } static void attach(void * priv, GtkWidget * table, int * row, int * num_columns) { color_t * c = (color_t*)priv; if(*num_columns < 2) *num_columns = 2; gtk_table_resize(GTK_TABLE(table), *row+1, *num_columns); gtk_table_attach(GTK_TABLE(table), c->label, 0, 1, *row, *row+1, GTK_FILL, GTK_FILL, 0, 0); gtk_table_attach(GTK_TABLE(table), c->button, 1, 2, *row, *row+1, GTK_FILL | GTK_EXPAND, GTK_FILL, 0, 0); (*row)++; } static const gtk_widget_funcs_t funcs = { .get_value = get_value, .set_value = set_value, .destroy = destroy, .attach = attach }; static void realize_callback(GtkWidget * _w, gpointer data) { int x, y, w, h, depth; color_t * priv = (color_t*)data; // if(priv->has_alpha) // { gdk_window_get_geometry(priv->drawingarea->window, &x, &y, &w, &h, &depth); priv->background_pixmap = gdk_pixmap_new(priv->drawingarea->window, 32, 32, depth); priv->gc = gdk_gc_new(priv->drawingarea->window); // gdk_window_set_back_pixmap(priv->drawingarea->window, // priv->background_pixmap, 0); bg_gtk_set_widget_bg_pixmap(priv->drawingarea, priv->background_pixmap); // } set_button(priv); } static void changed_callback(GtkWidget * w, gpointer data) { bg_gtk_widget_t * wid = (bg_gtk_widget_t*)data; color_t * priv = (color_t*)wid->priv; gtk_color_selection_get_current_color(GTK_COLOR_SELECTION(GTK_COLOR_SELECTION_DIALOG(priv->colorsel)->colorsel), &priv->color); priv->alpha = gtk_color_selection_get_current_alpha(GTK_COLOR_SELECTION(GTK_COLOR_SELECTION_DIALOG(priv->colorsel)->colorsel)); bg_gtk_change_callback(NULL, wid); set_button(priv); } static gboolean delete_callback(GtkWidget * w, GdkEventAny * event, gpointer data) { button_callback(w, data); return TRUE; } static void button_callback(GtkWidget * w, gpointer data) { bg_gtk_widget_t * wid = (bg_gtk_widget_t*)data; GtkWidget * toplevel; color_t * priv = (color_t*)wid->priv; if(w == priv->button) { /* Save last color */ memcpy(&priv->last_color, &priv->color, sizeof(priv->color)); if(!priv->colorsel) { priv->colorsel = gtk_color_selection_dialog_new("Select a color"); if(wid->info->flags & BG_PARAMETER_SYNC) { g_signal_connect(G_OBJECT(GTK_COLOR_SELECTION_DIALOG(priv->colorsel)->colorsel), "color-changed", G_CALLBACK(changed_callback), wid); } gtk_window_set_modal(GTK_WINDOW(priv->colorsel), TRUE); toplevel = bg_gtk_get_toplevel(priv->button); if(toplevel) gtk_window_set_transient_for(GTK_WINDOW(priv->colorsel), GTK_WINDOW(toplevel)); g_signal_connect(G_OBJECT(GTK_COLOR_SELECTION_DIALOG(priv->colorsel)->ok_button), "clicked", G_CALLBACK(button_callback), (gpointer)wid); g_signal_connect(G_OBJECT(GTK_COLOR_SELECTION_DIALOG(priv->colorsel)->cancel_button), "clicked", G_CALLBACK(button_callback), (gpointer)wid); g_signal_connect(G_OBJECT(priv->colorsel), "delete_event", G_CALLBACK(delete_callback), (gpointer)wid); gtk_widget_hide(GTK_COLOR_SELECTION_DIALOG(priv->colorsel)->help_button); if(priv->has_alpha) gtk_color_selection_set_has_opacity_control(GTK_COLOR_SELECTION(GTK_COLOR_SELECTION_DIALOG(priv->colorsel)->colorsel), TRUE); } gtk_color_selection_set_current_color(GTK_COLOR_SELECTION(GTK_COLOR_SELECTION_DIALOG(priv->colorsel)->colorsel), &priv->color); if(priv->has_alpha) gtk_color_selection_set_current_alpha(GTK_COLOR_SELECTION(GTK_COLOR_SELECTION_DIALOG(priv->colorsel)->colorsel), priv->alpha); gtk_widget_show(priv->colorsel); gtk_main(); } else if(priv->colorsel) { if(w == GTK_COLOR_SELECTION_DIALOG(priv->colorsel)->ok_button) { gtk_main_quit(); gtk_widget_hide(priv->colorsel); gtk_color_selection_get_current_color(GTK_COLOR_SELECTION(GTK_COLOR_SELECTION_DIALOG(priv->colorsel)->colorsel), &priv->color); priv->alpha = gtk_color_selection_get_current_alpha(GTK_COLOR_SELECTION(GTK_COLOR_SELECTION_DIALOG(priv->colorsel)->colorsel)); set_button(priv); } else if((w == GTK_COLOR_SELECTION_DIALOG(priv->colorsel)->cancel_button) || (w == priv->colorsel)) { gtk_main_quit(); gtk_widget_hide(priv->colorsel); if(wid->info->flags & BG_PARAMETER_SYNC) { /* Restore last color */ memcpy(&priv->color, &priv->last_color, sizeof(priv->color)); wid->funcs->set_value(wid); if(wid->change_callback) wid->change_callback(wid->change_callback_data, wid->info->name, &wid->value); set_button(priv); } } } } void bg_gtk_create_color_rgba(bg_gtk_widget_t * w, const char * translation_domain) { color_t * priv; bg_gtk_create_color_rgb(w, translation_domain); priv = (color_t*)(w->priv); priv->has_alpha = 1; } void bg_gtk_create_color_rgb(bg_gtk_widget_t * w, const char * translation_domain) { color_t * priv = calloc(1, sizeof(*priv)); w->funcs = &funcs; w->value.val_color[0] = 0.0; w->value.val_color[1] = 0.0; w->value.val_color[2] = 0.0; w->value.val_color[3] = 1.0; priv->button = gtk_button_new(); priv->drawingarea = gtk_drawing_area_new(); gtk_widget_set_size_request(priv->drawingarea, priv->drawingarea->requisition.width, 16); gtk_widget_set_events(priv->drawingarea, GDK_EXPOSURE_MASK); g_signal_connect(G_OBJECT(priv->drawingarea), "realize", G_CALLBACK(realize_callback), (gpointer)priv); g_signal_connect(G_OBJECT(priv->button), "clicked", G_CALLBACK(button_callback), (gpointer)w); gtk_widget_show(priv->drawingarea); gtk_container_add(GTK_CONTAINER(priv->button), priv->drawingarea); if(w->info->help_string) { bg_gtk_tooltips_set_tip(priv->button, w->info->help_string, translation_domain); } gtk_widget_show(priv->button); priv->label = gtk_label_new(TR_DOM(w->info->long_name)); gtk_misc_set_alignment(GTK_MISC(priv->label), 0.0, 0.5); gtk_widget_show(priv->label); w->priv = priv; } gmerlin-1.2.0~dfsg/lib/gtk/fileentry.c0000644000175000017500000001452511764363406017612 0ustar alessioalessio/***************************************************************** * gmerlin - a general purpose multimedia framework and applications * * Copyright (c) 2001 - 2011 Members of the Gmerlin project * gmerlin-general@lists.sourceforge.net * http://gmerlin.sourceforge.net * * 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 of the License, 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 this program. If not, see . * *****************************************************************/ #include #include #include #include #include #include #include struct bg_gtk_file_entry_s { GtkWidget * entry; GtkWidget * button; int is_dir; GtkWidget * fileselect; void (*name_changed_callback)(bg_gtk_file_entry_t *, void * data); void * name_changed_callback_data; }; static void filesel_callback(GtkWidget *chooser, gint response_id, gpointer data) { char * tmp_string; bg_gtk_file_entry_t * priv = (bg_gtk_file_entry_t*)data; if(response_id == GTK_RESPONSE_OK) { if(priv->is_dir) tmp_string = gtk_file_chooser_get_current_folder(GTK_FILE_CHOOSER(priv->fileselect)); else tmp_string = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(priv->fileselect)); gtk_entry_set_text(GTK_ENTRY(priv->entry), tmp_string); g_free(tmp_string); } gtk_widget_hide(priv->fileselect); gtk_main_quit(); } static gboolean delete_callback(GtkWidget * w, GdkEventAny * event, gpointer data) { filesel_callback(w, GTK_RESPONSE_CANCEL, data); return TRUE; } static void button_callback(GtkWidget * w, gpointer data) { bg_gtk_file_entry_t * priv = (bg_gtk_file_entry_t*)data; GtkWidget * toplevel; if(w == priv->button) { if(!priv->fileselect) { toplevel = bg_gtk_get_toplevel(w); if(priv->is_dir) { priv->fileselect = gtk_file_chooser_dialog_new(TR("Select a directory"), GTK_WINDOW(toplevel), GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER, GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, GTK_STOCK_OK, GTK_RESPONSE_OK, NULL); } else { priv->fileselect = gtk_file_chooser_dialog_new(TR("Select a file"), GTK_WINDOW(toplevel), GTK_FILE_CHOOSER_ACTION_SAVE, GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, GTK_STOCK_OK, GTK_RESPONSE_OK, NULL); } gtk_window_set_modal(GTK_WINDOW(priv->fileselect), TRUE); g_signal_connect(priv->fileselect, "response", G_CALLBACK(filesel_callback), (gpointer)priv); g_signal_connect(G_OBJECT(priv->fileselect), "delete_event", G_CALLBACK(delete_callback), (gpointer)priv); } if(priv->is_dir) gtk_file_chooser_set_current_folder(GTK_FILE_CHOOSER(priv->fileselect), gtk_entry_get_text(GTK_ENTRY(priv->entry))); else gtk_file_chooser_set_filename(GTK_FILE_CHOOSER(priv->fileselect), gtk_entry_get_text(GTK_ENTRY(priv->entry))); gtk_widget_show(priv->fileselect); gtk_main(); } else if(w == priv->entry) { priv->name_changed_callback(priv, priv->name_changed_callback_data); } } bg_gtk_file_entry_t * bg_gtk_file_entry_create(int is_dir, void (*name_changed_callback)(bg_gtk_file_entry_t *, void * data), void * name_changed_callback_data, const char * help_string, const char * translation_domain) { bg_gtk_file_entry_t * priv = calloc(1, sizeof(*priv)); priv->is_dir = is_dir; priv->name_changed_callback = name_changed_callback; priv->name_changed_callback_data = name_changed_callback_data; priv->entry = gtk_entry_new(); if(help_string) { bg_gtk_tooltips_set_tip(priv->entry, help_string, translation_domain); } if(priv->name_changed_callback) g_signal_connect(G_OBJECT(priv->entry), "changed", G_CALLBACK(button_callback), (gpointer)priv); gtk_widget_show(priv->entry); priv->button = gtk_button_new_with_label(TR("Browse...")); g_signal_connect(G_OBJECT(priv->button), "clicked", G_CALLBACK(button_callback), (gpointer)priv); gtk_widget_show(priv->button); return priv; } void bg_gtk_file_entry_destroy(bg_gtk_file_entry_t * f) { if(f->fileselect) gtk_widget_destroy(f->fileselect); free(f); } const char * bg_gtk_file_entry_get_filename(bg_gtk_file_entry_t * f) { return gtk_entry_get_text(GTK_ENTRY(f->entry)); } void bg_gtk_file_entry_set_filename(bg_gtk_file_entry_t * f, const char * s) { if(!s || (*s == '\0')) { gtk_entry_set_text(GTK_ENTRY(f->entry), ""); return; } gtk_entry_set_text(GTK_ENTRY(f->entry), s); } GtkWidget * bg_gtk_file_entry_get_entry(bg_gtk_file_entry_t * f) { return f->entry; } GtkWidget * bg_gtk_file_entry_get_button(bg_gtk_file_entry_t *f) { return f->button; } gmerlin-1.2.0~dfsg/lib/gtk/cfg_position.c0000644000175000017500000001175211764363406020273 0ustar alessioalessio/***************************************************************** * gmerlin - a general purpose multimedia framework and applications * * Copyright (c) 2001 - 2011 Members of the Gmerlin project * gmerlin-general@lists.sourceforge.net * http://gmerlin.sourceforge.net * * 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 of the License, 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 this program. If not, see . * *****************************************************************/ #include #include "gtk_dialog.h" #include typedef struct { GtkWidget * label; GtkWidget * box; GtkWidget * spinbutton_x; GtkWidget * spinbutton_y; GtkObject * adj_x; GtkObject * adj_y; } spinbutton_t; /* typedef enum { GTK_EXPAND = 1 << 0, GTK_SHRINK = 1 << 1, GTK_FILL = 1 << 2 } GtkAttachOptions; */ static void destroy(bg_gtk_widget_t * w) { spinbutton_t * s = w->priv; free(s); } static void get_value(bg_gtk_widget_t * w) { spinbutton_t * s = w->priv; // Need to save this because the callback of the x coordinate // will change w->value float tmp = w->value.val_pos[1]; gtk_spin_button_set_value(GTK_SPIN_BUTTON(s->spinbutton_x), w->value.val_pos[0]); gtk_spin_button_set_value(GTK_SPIN_BUTTON(s->spinbutton_y), tmp); } static void set_value(bg_gtk_widget_t * w) { spinbutton_t * s = w->priv; w->value.val_pos[0] = gtk_spin_button_get_value(GTK_SPIN_BUTTON(s->spinbutton_x)); w->value.val_pos[1] = gtk_spin_button_get_value(GTK_SPIN_BUTTON(s->spinbutton_y)); } static void attach(void * priv, GtkWidget * table, int * row, int * num_columns) { spinbutton_t * s = priv; if(*num_columns < 2) *num_columns = 2; gtk_table_resize(GTK_TABLE(table), *row + 1, *num_columns); gtk_table_attach(GTK_TABLE(table), s->label, 0, 1, *row, *row+1, GTK_FILL, GTK_SHRINK, 0, 0); gtk_table_attach(GTK_TABLE(table), s->box, 1, 2, *row, *row+1, GTK_FILL | GTK_EXPAND, GTK_SHRINK, 0, 0); *row += 1; } static const gtk_widget_funcs_t pos_funcs = { .get_value = get_value, .set_value = set_value, .destroy = destroy, .attach = attach }; void bg_gtk_create_position(bg_gtk_widget_t * w, const char * translation_domain) { GtkWidget * label; spinbutton_t * s = calloc(1, sizeof(*s)); w->funcs = &pos_funcs; s->label = gtk_label_new(TR_DOM(w->info->long_name)); gtk_widget_show(s->label); gtk_misc_set_alignment(GTK_MISC(s->label), 0.0, 0.5); s->adj_x = gtk_adjustment_new(0.0, 0.0, 1.0, 0.01, 0.0, 0.0); s->adj_y = gtk_adjustment_new(0.0, 0.0, 1.0, 0.01, 0.0, 0.0); s->spinbutton_x = gtk_spin_button_new(GTK_ADJUSTMENT(s->adj_x), 0.1, 0); s->spinbutton_y = gtk_spin_button_new(GTK_ADJUSTMENT(s->adj_y), 0.1, 0); if(w->info->flags & BG_PARAMETER_SYNC) { w->callback_id = g_signal_connect(G_OBJECT(s->spinbutton_x), "value-changed", G_CALLBACK(bg_gtk_change_callback), (gpointer)w); w->callback_widget = s->spinbutton_x; w->callback_id_2 = g_signal_connect(G_OBJECT(s->spinbutton_y), "value-changed", G_CALLBACK(bg_gtk_change_callback), (gpointer)w); w->callback_widget_2 = s->spinbutton_y; } if(w->info->help_string) { bg_gtk_tooltips_set_tip(s->spinbutton_x, w->info->help_string, translation_domain); bg_gtk_tooltips_set_tip(s->spinbutton_y, w->info->help_string, translation_domain); } gtk_widget_show(s->spinbutton_x); gtk_widget_show(s->spinbutton_y); gtk_widget_show(s->label); s->box = gtk_hbox_new(0, 5); label = gtk_label_new(TR("X")); gtk_widget_show(label); gtk_box_pack_start(GTK_BOX(s->box), label, FALSE, FALSE, 0); bg_gtk_box_pack_start_defaults(GTK_BOX(s->box), s->spinbutton_x); label = gtk_label_new(TR("Y")); gtk_widget_show(label); gtk_box_pack_start(GTK_BOX(s->box), label, FALSE, FALSE, 0); bg_gtk_box_pack_start_defaults(GTK_BOX(s->box), s->spinbutton_y); gtk_widget_show(s->box); w->priv = s; bg_gtk_change_callback_block(w, 1); gtk_spin_button_set_digits(GTK_SPIN_BUTTON(s->spinbutton_x), w->info->num_digits); gtk_spin_button_set_digits(GTK_SPIN_BUTTON(s->spinbutton_y), w->info->num_digits); bg_gtk_change_callback_block(w, 0); } gmerlin-1.2.0~dfsg/lib/gtk/plugininfo.c0000644000175000017500000001747711764363406017774 0ustar alessioalessio/***************************************************************** * gmerlin - a general purpose multimedia framework and applications * * Copyright (c) 2001 - 2011 Members of the Gmerlin project * gmerlin-general@lists.sourceforge.net * http://gmerlin.sourceforge.net * * 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 of the License, 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 this program. If not, see . * *****************************************************************/ #include #include #include #include #include #include #include #include #include typedef struct { GtkWidget * window; GtkWidget * close_button; bg_gtk_textview_t * textview1; bg_gtk_textview_t * textview2; }pluginwindow_t; static void button_callback(GtkWidget * w, gpointer data) { pluginwindow_t * win; win = (pluginwindow_t*)data; bg_gtk_textview_destroy(win->textview1); bg_gtk_textview_destroy(win->textview2); gtk_widget_hide(win->window); gtk_widget_destroy(win->window); free(win); } static gboolean delete_callback(GtkWidget * w, GdkEventAny * event, gpointer data) { button_callback(w, data); return TRUE; } static pluginwindow_t * pluginwindow_create(const char * title, const char * properties, const char * description) { GtkWidget * table; GtkWidget * frame; pluginwindow_t * ret; ret = calloc(1, sizeof(*ret)); ret->window = bg_gtk_window_new(GTK_WINDOW_TOPLEVEL); gtk_window_set_type_hint(GTK_WINDOW(ret->window), GDK_WINDOW_TYPE_HINT_DIALOG); gtk_window_set_position(GTK_WINDOW(ret->window), GTK_WIN_POS_CENTER_ON_PARENT); g_signal_connect(G_OBJECT(ret->window), "delete_event", G_CALLBACK(delete_callback), (gpointer)ret); gtk_window_set_title(GTK_WINDOW(ret->window), title); /* Create close button */ ret->close_button = gtk_button_new_from_stock(GTK_STOCK_CLOSE); bg_gtk_widget_set_can_default(ret->close_button, TRUE); g_signal_connect(G_OBJECT(ret->close_button), "clicked", G_CALLBACK(button_callback), (gpointer)ret); gtk_widget_show(ret->close_button); /* Create texts */ ret->textview1 = bg_gtk_textview_create(); bg_gtk_textview_update(ret->textview1, properties); ret->textview2 = bg_gtk_textview_create(); bg_gtk_textview_update(ret->textview2, description); table = gtk_table_new(3, 1, 0); gtk_table_set_row_spacings(GTK_TABLE(table), 5); gtk_table_set_col_spacings(GTK_TABLE(table), 5); gtk_container_set_border_width(GTK_CONTAINER(table), 5); frame = gtk_frame_new("Properties"); gtk_container_add(GTK_CONTAINER(frame), bg_gtk_textview_get_widget(ret->textview1)); gtk_widget_show(frame); gtk_table_attach_defaults(GTK_TABLE(table), frame, 0, 1, 0, 1); frame = gtk_frame_new("Description"); gtk_container_add(GTK_CONTAINER(frame), bg_gtk_textview_get_widget(ret->textview2)); gtk_widget_show(frame); gtk_table_attach_defaults(GTK_TABLE(table), frame, 0, 1, 1, 2); gtk_table_attach(GTK_TABLE(table), ret->close_button, 0, 1, 2, 3, GTK_SHRINK, GTK_SHRINK, 0, 0); gtk_widget_show(table); gtk_container_add(GTK_CONTAINER(ret->window), table); return ret; } static void pluginwindow_show(pluginwindow_t * w, int modal, GtkWidget * parent) { parent = bg_gtk_get_toplevel(parent); if(parent) gtk_window_set_transient_for(GTK_WINDOW(w->window), GTK_WINDOW(parent)); gtk_window_set_modal(GTK_WINDOW(w->window), modal); gtk_widget_grab_default(w->close_button); gtk_widget_show(w->window); } static const struct { char * name; bg_plugin_type_t type; } type_names[] = { { TRS("Input"), BG_PLUGIN_INPUT }, { TRS("Audio output"), BG_PLUGIN_OUTPUT_AUDIO }, { TRS("Video output"), BG_PLUGIN_OUTPUT_VIDEO }, { TRS("Audio recorder"), BG_PLUGIN_RECORDER_AUDIO }, { TRS("Video recorder"), BG_PLUGIN_RECORDER_VIDEO }, { TRS("Audio encoder"), BG_PLUGIN_ENCODER_AUDIO }, { TRS("Video encoder"), BG_PLUGIN_ENCODER_VIDEO }, { TRS("Text subtitle exporter"), BG_PLUGIN_ENCODER_SUBTITLE_TEXT }, { TRS("Overlay subtitle exporter"), BG_PLUGIN_ENCODER_SUBTITLE_OVERLAY }, { TRS("Audio/Video encoder"), BG_PLUGIN_ENCODER }, { TRS("Image reader"), BG_PLUGIN_IMAGE_READER }, { TRS("Image writer"), BG_PLUGIN_IMAGE_WRITER }, { TRS("Encoding postprocessor"), BG_PLUGIN_ENCODER_PP }, { TRS("Audio filter"), BG_PLUGIN_FILTER_AUDIO }, { TRS("Video filter"), BG_PLUGIN_FILTER_VIDEO }, { TRS("Visualization"), BG_PLUGIN_VISUALIZATION }, { NULL, BG_PLUGIN_NONE } }; static const struct { char * name; uint32_t flag; } flag_names[] = { { TRS("Removable Device"), BG_PLUGIN_REMOVABLE }, /* Removable media (CD, DVD etc.) */ { TRS("Recorder"), BG_PLUGIN_RECORDER }, /* Plugin can record */ { TRS("File"), BG_PLUGIN_FILE }, /* Plugin reads/writes files */ { TRS("URL"), BG_PLUGIN_URL }, /* Plugin reads URLs or streams */ { TRS("Playback"), BG_PLUGIN_PLAYBACK }, /* Output plugins for playback */ { TRS("Tuner"), BG_PLUGIN_TUNER }, /* Plugin has tuner */ { TRS("Filter with 1 input"), BG_PLUGIN_FILTER_1 }, { TRS("Renders via gmerlin"), BG_PLUGIN_VISUALIZE_FRAME }, { TRS("Renders via OpenGL"), BG_PLUGIN_VISUALIZE_GL }, { NULL, 0 }, }; static char * get_flag_string(uint32_t flags) { char * ret; int i, j, index, num_flags; uint32_t flag; ret = malloc(1024); *ret = '\0'; /* Count the flags */ num_flags = 0; for(i = 0; i < 32; i++) { flag = (1<flags); text = bg_sprintf(TR("Name:\t %s\nLong name:\t %s\nType:\t %s\nFlags:\t %s\nPriority:\t %d\nDLL Filename:\t %s"), info->name, info->long_name, get_type_string(info->type), flag_string, info->priority, info->module_filename); win = pluginwindow_create(TRD(info->long_name, info->gettext_domain), text, TRD(info->description, info->gettext_domain)); free(text); free(flag_string); pluginwindow_show(win, 1, parent); } gmerlin-1.2.0~dfsg/lib/gtk/chapterdialog.c0000644000175000017500000003270611764363406020420 0ustar alessioalessio/***************************************************************** * gmerlin - a general purpose multimedia framework and applications * * Copyright (c) 2001 - 2011 Members of the Gmerlin project * gmerlin-general@lists.sourceforge.net * http://gmerlin.sourceforge.net * * 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 of the License, 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 this program. If not, see . * *****************************************************************/ #include #include #include #include #include #include #include #include enum { COLUMN_NAME, COLUMN_TIME, NUM_COLUMNS }; typedef struct { GtkWidget * window; GtkWidget * add_button; GtkWidget * delete_button; GtkWidget * edit_button; GtkWidget * list; GtkWidget * ok_button; GtkWidget * cancel_button; bg_chapter_list_t * cl; int selected; int edited; int is_ok; guint select_id; gavl_time_t duration; } bg_gtk_chapter_dialog_t; static void select_row_callback(GtkTreeSelection * sel, gpointer data) { int i; bg_gtk_chapter_dialog_t * win; GtkTreeModel * model; GtkTreeSelection * selection; GtkTreeIter iter; win = (bg_gtk_chapter_dialog_t *)data; model = gtk_tree_view_get_model(GTK_TREE_VIEW(win->list)); selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(win->list)); win->selected = -1; if(!gtk_tree_model_get_iter_first(model, &iter)) return; for(i = 0; i < win->cl->num_chapters; i++) { if(gtk_tree_selection_iter_is_selected(selection, &iter)) { win->selected = i; break; } if(!gtk_tree_model_iter_next(model, &iter)) break; } if(win->selected < 0) { gtk_widget_set_sensitive(win->edit_button, 0); gtk_widget_set_sensitive(win->delete_button, 0); } else { gtk_widget_set_sensitive(win->edit_button, 1); gtk_widget_set_sensitive(win->delete_button, 1); } } static void update_list(bg_gtk_chapter_dialog_t * win) { int i; char time_string[GAVL_TIME_STRING_LEN]; GtkTreeModel * model; GtkTreeSelection * selection; GtkTreeIter iter; selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(win->list)); g_signal_handler_block(G_OBJECT(selection), win->select_id); model = gtk_tree_view_get_model(GTK_TREE_VIEW(win->list)); gtk_list_store_clear(GTK_LIST_STORE(model)); if(win->cl) { for(i = 0; i < win->cl->num_chapters; i++) { gtk_list_store_append(GTK_LIST_STORE(model), &iter); gavl_time_prettyprint(win->cl->chapters[i].time, time_string); gtk_list_store_set(GTK_LIST_STORE(model), &iter, COLUMN_TIME, time_string, -1); if(win->cl->chapters[i].name) gtk_list_store_set(GTK_LIST_STORE(model), &iter, COLUMN_NAME, win->cl->chapters[i].name, -1); if(win->selected == i) gtk_tree_selection_select_iter(selection, &iter); } } if((win->selected < 0) || (!win->cl)) { gtk_widget_set_sensitive(win->edit_button, 0); gtk_widget_set_sensitive(win->delete_button, 0); } else { gtk_widget_set_sensitive(win->edit_button, 1); gtk_widget_set_sensitive(win->delete_button, 1); } g_signal_handler_unblock(G_OBJECT(selection), win->select_id); } static void set_parameter(void * data, const char * name, const bg_parameter_value_t * val) { bg_gtk_chapter_dialog_t * win; win = (bg_gtk_chapter_dialog_t*)data; if(!name) { win->is_ok = 1; return; } else if(!strcmp(name, "name")) win->cl->chapters[win->edited].name = bg_strdup(win->cl->chapters[win->edited].name, val->val_str); else if(!strcmp(name, "time")) win->cl->chapters[win->edited].time = gavl_time_scale(win->cl->timescale, val->val_time); } static int edit_chapter(bg_gtk_chapter_dialog_t * win) { bg_dialog_t * dialog; bg_parameter_info_t chapter_parameters[3]; /* Set up parameters */ memset(chapter_parameters, 0, sizeof(chapter_parameters)); chapter_parameters[0].name = "name"; chapter_parameters[0].long_name = TRS("Name"); chapter_parameters[0].type = BG_PARAMETER_STRING; chapter_parameters[0].val_default.val_str = win->cl->chapters[win->edited].name; /* Time can only be changed if this isn't the first chapter */ if(win->edited) { chapter_parameters[1].name = "time"; chapter_parameters[1].long_name = TRS("Time"); chapter_parameters[1].type = BG_PARAMETER_TIME; chapter_parameters[1].val_default.val_time = win->cl->chapters[win->edited].time; /* We set the min-max values of the time such that the resulting list will always be ordered */ chapter_parameters[1].val_min.val_time = win->cl->chapters[win->edited-1].time + GAVL_TIME_SCALE / 1000; if(win->edited == win->cl->num_chapters - 1) chapter_parameters[1].val_max.val_time = win->duration - GAVL_TIME_SCALE / 1000; else chapter_parameters[1].val_max.val_time = win->cl->chapters[win->edited+1].time - GAVL_TIME_SCALE / 1000; if(chapter_parameters[1].val_default.val_time < chapter_parameters[1].val_min.val_time) chapter_parameters[1].val_default.val_time = chapter_parameters[1].val_min.val_time; } dialog = bg_dialog_create(NULL, set_parameter, NULL, win, chapter_parameters, TR("Edit chapter")); bg_dialog_show(dialog, win->window); bg_dialog_destroy(dialog); return 1; } static void button_callback(GtkWidget * w, gpointer data) { bg_gtk_chapter_dialog_t * win; win = (bg_gtk_chapter_dialog_t*)data; if(w == win->ok_button) { win->is_ok = 1; gtk_main_quit(); gtk_widget_hide(win->window); } else if((w == win->cancel_button) || (w == win->window)) { gtk_main_quit(); gtk_widget_hide(win->window); win->is_ok = 0; } else if(w == win->add_button) { if(!win->cl) { win->cl = bg_chapter_list_create(0); win->selected = 0; win->edited = 0; win->cl->timescale = GAVL_TIME_SCALE; } else win->edited = win->selected + 1; bg_chapter_list_insert(win->cl, win->edited, 0,NULL); win->is_ok = 0; edit_chapter(win); if(!win->is_ok) bg_chapter_list_delete(win->cl, win->edited); else { win->selected = win->edited; update_list(win); } } else if(w == win->delete_button) { bg_chapter_list_delete(win->cl, win->selected); update_list(win); } else if(w == win->edit_button) { win->edited = win->selected; edit_chapter(win); update_list(win); } } static gboolean delete_callback(GtkWidget * w, GdkEventAny * evt, gpointer data) { button_callback(w, data); return TRUE; } static GtkWidget * create_window_pixmap_button(bg_gtk_chapter_dialog_t * win, const char * filename, const char * tooltip) { GtkWidget * button; GtkWidget * image; char * path; path = bg_search_file_read("icons", filename); if(path) { image = gtk_image_new_from_file(path); free(path); } else image = gtk_image_new(); gtk_widget_show(image); button = gtk_button_new(); gtk_container_add(GTK_CONTAINER(button), image); g_signal_connect(G_OBJECT(button), "clicked", G_CALLBACK(button_callback), win); gtk_widget_show(button); bg_gtk_tooltips_set_tip(button, tooltip, PACKAGE); return button; } static bg_gtk_chapter_dialog_t * create_dialog(bg_chapter_list_t * list, gavl_time_t duration) { GtkListStore *store; GtkCellRenderer *renderer; GtkTreeViewColumn *column; GtkTreeSelection * selection; GtkWidget * scrolled; GtkWidget * table; GtkWidget * box; bg_gtk_chapter_dialog_t * ret; ret = calloc(1, sizeof(*ret)); ret->cl = bg_chapter_list_copy(list); ret->duration = duration; /* Create objects */ ret->window = bg_gtk_window_new(GTK_WINDOW_TOPLEVEL); gtk_window_set_position(GTK_WINDOW(ret->window), GTK_WIN_POS_CENTER_ON_PARENT); gtk_window_set_modal(GTK_WINDOW(ret->window), 1); gtk_window_set_title(GTK_WINDOW(ret->window), TR("Edit chapters")); g_signal_connect(G_OBJECT(ret->window), "delete_event", G_CALLBACK(delete_callback), ret); ret->ok_button = gtk_button_new_from_stock(GTK_STOCK_OK); ret->cancel_button = gtk_button_new_from_stock(GTK_STOCK_CANCEL); g_signal_connect(G_OBJECT(ret->ok_button), "clicked", G_CALLBACK(button_callback), ret); g_signal_connect(G_OBJECT(ret->cancel_button), "clicked", G_CALLBACK(button_callback), ret); gtk_widget_show(ret->ok_button); gtk_widget_show(ret->cancel_button); ret->add_button = create_window_pixmap_button(ret, "add_16.png", TRS("Add new chapter")); ret->edit_button = create_window_pixmap_button(ret, "config_16.png", TRS("Edit chapter")); ret->delete_button = create_window_pixmap_button(ret, "trash_16.png", TRS("Delete chapter")); /* Create treeview */ store = gtk_list_store_new(NUM_COLUMNS, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING); ret->list = gtk_tree_view_new_with_model(GTK_TREE_MODEL(store)); selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(ret->list)); ret->select_id = g_signal_connect(G_OBJECT(selection), "changed", G_CALLBACK(select_row_callback), (gpointer)ret); renderer = gtk_cell_renderer_text_new (); column = gtk_tree_view_column_new_with_attributes ("Name", renderer, "text", COLUMN_NAME, NULL); gtk_tree_view_append_column (GTK_TREE_VIEW(ret->list), column); renderer = gtk_cell_renderer_text_new (); column = gtk_tree_view_column_new_with_attributes ("Time", renderer, "text", COLUMN_TIME, NULL); gtk_tree_view_append_column (GTK_TREE_VIEW(ret->list), column); gtk_widget_show(ret->list); /* Pack objects */ table = gtk_table_new(4, 2, 0); gtk_table_set_row_spacings(GTK_TABLE(table), 5); gtk_table_set_col_spacings(GTK_TABLE(table), 5); gtk_container_set_border_width(GTK_CONTAINER(table), 5); scrolled = gtk_scrolled_window_new(gtk_tree_view_get_hadjustment(GTK_TREE_VIEW(ret->list)), gtk_tree_view_get_vadjustment(GTK_TREE_VIEW(ret->list))); gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled), GTK_POLICY_NEVER, GTK_POLICY_ALWAYS); gtk_container_add(GTK_CONTAINER(scrolled), ret->list); gtk_widget_show(scrolled); gtk_table_attach_defaults(GTK_TABLE(table), scrolled, 0, 1, 0, 3); gtk_table_attach(GTK_TABLE(table), ret->add_button, 1, 2, 0, 1, GTK_FILL, GTK_SHRINK, 0, 0); gtk_table_attach(GTK_TABLE(table), ret->edit_button, 1, 2, 1, 2, GTK_FILL, GTK_SHRINK, 0, 0); gtk_table_attach(GTK_TABLE(table), ret->delete_button, 1, 2, 2, 3, GTK_FILL, GTK_SHRINK, 0, 0); box = gtk_hbutton_box_new(); gtk_box_set_spacing(GTK_BOX(box), 5); gtk_container_add(GTK_CONTAINER(box), ret->ok_button); gtk_container_add(GTK_CONTAINER(box), ret->cancel_button); gtk_widget_show(box); gtk_table_attach(GTK_TABLE(table), box, 0, 2, 3, 4, GTK_FILL, GTK_FILL, 0, 0); gtk_widget_show(table); gtk_container_add(GTK_CONTAINER(ret->window), table); update_list(ret); return ret; } static void destroy_dialog(bg_gtk_chapter_dialog_t * dlg) { gtk_widget_destroy(dlg->window); if(dlg->cl) bg_chapter_list_destroy(dlg->cl); free(dlg); } void bg_gtk_chapter_dialog_show(bg_chapter_list_t ** list, gavl_time_t duration, GtkWidget * parent) { bg_gtk_chapter_dialog_t * dlg; dlg = create_dialog(*list, duration); parent = bg_gtk_get_toplevel(parent); if(parent) gtk_window_set_transient_for(GTK_WINDOW(dlg->window), GTK_WINDOW(parent)); gtk_widget_show(dlg->window); gtk_main(); if(dlg->is_ok) { if(*list) bg_chapter_list_destroy(*list); *list = bg_chapter_list_copy(dlg->cl); } destroy_dialog(dlg); } gmerlin-1.2.0~dfsg/lib/gtk/button.c0000644000175000017500000002145411764363406017123 0ustar alessioalessio/***************************************************************** * gmerlin - a general purpose multimedia framework and applications * * Copyright (c) 2001 - 2011 Members of the Gmerlin project * gmerlin-general@lists.sourceforge.net * http://gmerlin.sourceforge.net * * 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 of the License, 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 this program. If not, see . * *****************************************************************/ #include #include #include #include #include #include #include #include struct bg_gtk_button_s { int x, y; /* Coordinates relative to parent window */ /* Pixbufs */ GdkPixbuf * pixbuf_normal; GdkPixbuf * pixbuf_highlight; GdkPixbuf * pixbuf_pressed; /* Widget */ GtkWidget * widget; GtkWidget * image; /* Callback stuff */ void (*callback)(bg_gtk_button_t*, void*); void * callback_data; void (*callback_2)(bg_gtk_button_t*, void*); void * callback_2_data; GtkWidget * menu; int mouse_inside; }; static gboolean button_press_callback(GtkWidget * w, GdkEventButton * evt, gpointer data) { bg_gtk_button_t * b; b = (bg_gtk_button_t *)data; gtk_image_set_from_pixbuf(GTK_IMAGE(b->image), b->pixbuf_pressed); if(b->menu) { gtk_menu_popup(GTK_MENU(b->menu), NULL, NULL, NULL, NULL, evt->button, evt->time); } return TRUE; } //static void static gboolean button_release_callback(GtkWidget * w, GdkEventButton * evt, gpointer data) { bg_gtk_button_t * b; b = (bg_gtk_button_t *)data; if(b->mouse_inside) { gtk_image_set_from_pixbuf(GTK_IMAGE(b->image), b->pixbuf_highlight); if(b->callback_2 && (evt->button == 3)) b->callback_2(b, b->callback_2_data); else if(b->callback) b->callback(b, b->callback_data); } return TRUE; } static gboolean motion_callback(GtkWidget * w, GdkEventMotion * evt, gpointer data) { bg_gtk_button_t * b; b = (bg_gtk_button_t *)data; // gtk_image_set_from_pixbuf(GTK_IMAGE(b->image), b->pixbuf_normal); return TRUE; } static gboolean enter_notify_callback(GtkWidget *widget, GdkEventCrossing *event, gpointer data) { bg_gtk_button_t * b; b = (bg_gtk_button_t *)data; gtk_image_set_from_pixbuf(GTK_IMAGE(b->image), b->pixbuf_highlight); b->mouse_inside = 1; return TRUE; } static gboolean leave_notify_callback(GtkWidget *widget, GdkEventCrossing *event, gpointer data) { bg_gtk_button_t * b; b = (bg_gtk_button_t *)data; gtk_image_set_from_pixbuf(GTK_IMAGE(b->image), b->pixbuf_normal); b->mouse_inside = 0; return TRUE; } static void set_shape(bg_gtk_button_t * b) { GdkBitmap * mask = NULL; bg_gdk_pixbuf_render_pixmap_and_mask(b->pixbuf_normal, NULL, &mask); gtk_widget_shape_combine_mask(b->widget, mask, 0, 0); if(mask) { g_object_unref(G_OBJECT(mask)); } } static void realize_callback(GtkWidget * w, gpointer data) { bg_gtk_button_t * b; b = (bg_gtk_button_t *)data; if(b->pixbuf_normal) set_shape(b); } bg_gtk_button_t * bg_gtk_button_create() { bg_gtk_button_t * ret; ret = calloc(1, sizeof(*ret)); /* Create objects */ ret->widget = gtk_event_box_new(); ret->image = gtk_image_new_from_pixbuf(NULL); /* Set attributes */ gtk_widget_set_events(ret->widget, GDK_BUTTON1_MOTION_MASK| GDK_BUTTON2_MOTION_MASK| GDK_BUTTON3_MOTION_MASK| GDK_BUTTON_PRESS_MASK); /* Set callbacks */ g_signal_connect(G_OBJECT(ret->widget), "button_press_event", G_CALLBACK (button_press_callback), ret); g_signal_connect(G_OBJECT(ret->widget), "button_release_event", G_CALLBACK (button_release_callback), ret); g_signal_connect(G_OBJECT(ret->widget), "enter_notify_event", G_CALLBACK (enter_notify_callback), ret); g_signal_connect(G_OBJECT(ret->widget), "leave_notify_event", G_CALLBACK (leave_notify_callback), ret); g_signal_connect(G_OBJECT(ret->widget), "motion_notify_event", G_CALLBACK (motion_callback), ret); g_signal_connect(G_OBJECT(ret->widget), "realize", G_CALLBACK (realize_callback), ret); /* Pack everything */ gtk_container_add(GTK_CONTAINER(ret->widget), ret->image); gtk_widget_show(ret->image); gtk_widget_show(ret->widget); return ret; } void bg_gtk_button_destroy(bg_gtk_button_t * b) { } /* Set Attributes */ static GdkPixbuf * make_pixbuf(GdkPixbuf * old, const char * filename) { GdkPixbuf * ret; if(old) g_object_unref(G_OBJECT(old)); ret = gdk_pixbuf_new_from_file(filename, NULL); return ret; } void bg_gtk_button_set_skin(bg_gtk_button_t * b, bg_gtk_button_skin_t * s, const char * directory) { char * tmp_string = NULL; b->x = s->x; b->y = s->y; tmp_string = bg_sprintf("%s/%s", directory, s->pixmap_normal); b->pixbuf_normal = make_pixbuf(b->pixbuf_normal, tmp_string); free(tmp_string); tmp_string = bg_sprintf("%s/%s", directory, s->pixmap_highlight); b->pixbuf_highlight = make_pixbuf(b->pixbuf_highlight, tmp_string); free(tmp_string); tmp_string = bg_sprintf("%s/%s", directory, s->pixmap_pressed); b->pixbuf_pressed = make_pixbuf(b->pixbuf_pressed, tmp_string); free(tmp_string); gtk_image_set_from_pixbuf(GTK_IMAGE(b->image), b->pixbuf_normal); if(b->widget->window) set_shape(b); } /* A button can have either a callback or a menu */ void bg_gtk_button_set_callback(bg_gtk_button_t * b, void (*callback)(bg_gtk_button_t *, void *), void * callback_data) { b->callback = callback; b->callback_data = callback_data; } void bg_gtk_button_set_callback_2(bg_gtk_button_t * b, void (*callback_2)(bg_gtk_button_t *, void *), void * callback_2_data) { b->callback_2 = callback_2; b->callback_2_data = callback_2_data; } void bg_gtk_button_set_menu(bg_gtk_button_t * b, GtkWidget * menu) { b->menu = menu; } /* Get Stuff */ void bg_gtk_button_get_coords(bg_gtk_button_t * b, int * x, int * y) { *x = b->x; *y = b->y; } GtkWidget * bg_gtk_button_get_widget(bg_gtk_button_t * b) { return b->widget; } #define FREE(ptr) if(ptr)free(ptr); void bg_gtk_button_skin_free(bg_gtk_button_skin_t * s) { FREE(s->pixmap_normal); FREE(s->pixmap_highlight); FREE(s->pixmap_pressed); } void bg_gtk_button_skin_load(bg_gtk_button_skin_t * s, xmlDocPtr doc, xmlNodePtr node) { char * tmp_string; node = node->children; while(node) { if(!node->name) { node = node->next; continue; } tmp_string = (char*)xmlNodeListGetString(doc, node->children, 1); if(!BG_XML_STRCMP(node->name, "X")) s->x = atoi(tmp_string); else if(!BG_XML_STRCMP(node->name, "Y")) s->y = atoi(tmp_string); else if(!BG_XML_STRCMP(node->name, "NORMAL")) s->pixmap_normal = bg_strdup(s->pixmap_normal, tmp_string); else if(!BG_XML_STRCMP(node->name, "HIGHLIGHT")) s->pixmap_highlight = bg_strdup(s->pixmap_highlight, tmp_string); else if(!BG_XML_STRCMP(node->name, "PRESSED")) s->pixmap_pressed = bg_strdup(s->pixmap_pressed, tmp_string); node = node->next; xmlFree(tmp_string); } } gmerlin-1.2.0~dfsg/lib/gtk/plugin_single.c0000644000175000017500000004667611764363406020464 0ustar alessioalessio/***************************************************************** * gmerlin - a general purpose multimedia framework and applications * * Copyright (c) 2001 - 2011 Members of the Gmerlin project * gmerlin-general@lists.sourceforge.net * http://gmerlin.sourceforge.net * * 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 of the License, 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 this program. If not, see . * *****************************************************************/ #include #include #include #include #include #include #include #include #include struct bg_gtk_plugin_widget_single_s { GtkWidget * label; GtkWidget * combo; GtkWidget * config_button; GtkWidget * info_button; GtkWidget * audio_button; GtkWidget * video_button; bg_plugin_registry_t * reg; const bg_plugin_info_t * info; bg_plugin_handle_t * handle; bg_cfg_section_t * section; bg_cfg_section_t * audio_section; bg_cfg_section_t * video_section; bg_cfg_section_t * subtitle_text_section; bg_cfg_section_t * subtitle_overlay_section; int section_priv; int audio_section_priv; int video_section_priv; int subtitle_text_section_priv; int subtitle_overlay_section_priv; int32_t type_mask; int32_t flag_mask; void (*set_plugin)(const bg_plugin_info_t *, void*); void * set_plugin_data; bg_set_parameter_func_t set_parameter; bg_get_parameter_func_t get_parameter; void * set_parameter_data; }; static void set_parameter(void * data, const char * name, const bg_parameter_value_t * v) { bg_gtk_plugin_widget_single_t * widget; widget = (bg_gtk_plugin_widget_single_t *)data; if(widget->handle && widget->handle->plugin->set_parameter) { bg_plugin_lock(widget->handle); widget->handle->plugin->set_parameter(widget->handle->priv, name, v); bg_plugin_unlock(widget->handle); } if(widget->set_parameter) { widget->set_parameter(widget->set_parameter_data, name, v); } } static int get_parameter(void * data, const char * name, bg_parameter_value_t * v) { int ret = 0; bg_gtk_plugin_widget_single_t * widget; widget = (bg_gtk_plugin_widget_single_t *)data; if(widget->handle && widget->handle->plugin->get_parameter) { bg_plugin_lock(widget->handle); ret = widget->handle->plugin->get_parameter(widget->handle->priv, name, v); bg_plugin_unlock(widget->handle); } return ret; } static void button_callback(GtkWidget * w, gpointer data) { const bg_parameter_info_t * parameters; bg_gtk_plugin_widget_single_t * widget; bg_dialog_t * dialog; widget = (bg_gtk_plugin_widget_single_t *)data; if(w == widget->info_button) { bg_gtk_plugin_info_show(widget->info, widget->info_button); } else if(w == widget->config_button) { if(widget->handle) parameters = widget->handle->plugin->get_parameters(widget->handle->priv); else parameters = widget->info->parameters; if(widget->handle && widget->handle->plugin->get_parameter) bg_cfg_section_get(widget->section, parameters, widget->handle->plugin->get_parameter, widget->handle->priv); dialog = bg_dialog_create(widget->section, set_parameter, get_parameter, (void*)widget, parameters, TRD(widget->info->long_name, widget->info->gettext_domain)); bg_dialog_show(dialog, widget->config_button); bg_dialog_destroy(dialog); } else if(w == widget->audio_button) { dialog = bg_dialog_create(widget->audio_section, NULL, NULL, NULL, widget->info->audio_parameters, TRD(widget->info->long_name, widget->info->gettext_domain)); bg_dialog_show(dialog, widget->audio_button); bg_dialog_destroy(dialog); } else if(w == widget->video_button) { dialog = bg_dialog_create(widget->video_section, NULL, NULL, NULL, widget->info->video_parameters, TRD(widget->info->long_name, widget->info->gettext_domain)); bg_dialog_show(dialog, widget->video_button); bg_dialog_destroy(dialog); } } static GtkWidget * create_pixmap_button(bg_gtk_plugin_widget_single_t * w, const char * filename, const char * tooltip) { GtkWidget * button; GtkWidget * image; char * path; path = bg_search_file_read("icons", filename); if(path) { image = gtk_image_new_from_file(path); free(path); } else image = gtk_image_new(); gtk_widget_show(image); button = gtk_button_new(); gtk_container_add(GTK_CONTAINER(button), image); bg_gtk_tooltips_set_tip(button, tooltip, PACKAGE); g_signal_connect(G_OBJECT(button), "clicked", G_CALLBACK(button_callback), (gpointer)w); gtk_widget_show(button); return button; } static void update_sensitive(bg_gtk_plugin_widget_single_t * widget) { if(!widget->info) return; if(widget->info->parameters) gtk_widget_set_sensitive(widget->config_button, 1); else gtk_widget_set_sensitive(widget->config_button, 0); if(widget->info->type & (BG_PLUGIN_ENCODER_AUDIO| BG_PLUGIN_ENCODER_VIDEO| BG_PLUGIN_ENCODER)) { if(widget->audio_button) { if(widget->info->audio_parameters) gtk_widget_set_sensitive(widget->audio_button, 1); else gtk_widget_set_sensitive(widget->audio_button, 0); } if(widget->video_button) { if(widget->info->video_parameters) gtk_widget_set_sensitive(widget->video_button, 1); else gtk_widget_set_sensitive(widget->video_button, 0); } } } static void change_callback(GtkWidget * w, gpointer data) { bg_gtk_plugin_widget_single_t * widget; widget = (bg_gtk_plugin_widget_single_t *)data; widget->info = bg_plugin_find_by_index(widget->reg, gtk_combo_box_get_active(GTK_COMBO_BOX(widget->combo)), widget->type_mask, widget->flag_mask); if(widget->handle) { bg_plugin_unref(widget->handle); widget->handle = NULL; } update_sensitive(widget); if(widget->section_priv) { bg_cfg_section_destroy(widget->section); widget->section_priv = 0; } widget->section = bg_plugin_registry_get_section(widget->reg, widget->info->name); if(widget->info->type & (BG_PLUGIN_ENCODER_AUDIO| BG_PLUGIN_ENCODER_VIDEO| BG_PLUGIN_ENCODER_SUBTITLE_TEXT| BG_PLUGIN_ENCODER_SUBTITLE_OVERLAY| BG_PLUGIN_ENCODER)) { if(widget->audio_section_priv) { bg_cfg_section_destroy(widget->audio_section); widget->audio_section_priv = 0; } if(widget->info->audio_parameters) widget->audio_section = bg_cfg_section_find_subsection(widget->section, "$audio"); else widget->audio_section = NULL; if(widget->video_section_priv) { bg_cfg_section_destroy(widget->video_section); widget->video_section_priv = 0; } if(widget->info->video_parameters) widget->video_section = bg_cfg_section_find_subsection(widget->section, "$video"); else widget->video_section = NULL; if(widget->subtitle_text_section_priv) { bg_cfg_section_destroy(widget->subtitle_text_section); widget->subtitle_text_section_priv = 0; } if(widget->info->subtitle_text_parameters) widget->subtitle_text_section = bg_cfg_section_find_subsection(widget->section, "$subtitle_text"); else widget->subtitle_text_section = NULL; if(widget->subtitle_overlay_section_priv) { bg_cfg_section_destroy(widget->subtitle_overlay_section); widget->subtitle_overlay_section_priv = 0; } if(widget->info->subtitle_overlay_parameters) widget->subtitle_overlay_section = bg_cfg_section_find_subsection(widget->section, "$subtitle_overlay"); else widget->subtitle_overlay_section = NULL; } if(widget->set_plugin) widget->set_plugin(widget->info, widget->set_plugin_data); } void bg_gtk_plugin_widget_single_set_change_callback(bg_gtk_plugin_widget_single_t * w, void (*set_plugin)(const bg_plugin_info_t * plugin, void * data), void * set_plugin_data) { w->set_plugin = set_plugin; w->set_plugin_data = set_plugin_data; } void bg_gtk_plugin_widget_single_set_parameter_callback(bg_gtk_plugin_widget_single_t * w, bg_set_parameter_func_t func, void * priv) { w->set_parameter = func; w->set_parameter_data = priv; } bg_gtk_plugin_widget_single_t * bg_gtk_plugin_widget_single_create(char * label, bg_plugin_registry_t * reg, uint32_t type_mask, uint32_t flag_mask) { int default_index; int num_plugins, i; bg_gtk_plugin_widget_single_t * ret; const bg_plugin_info_t * info; const bg_plugin_info_t * default_info; ret = calloc(1, sizeof(*ret)); ret->reg = reg; ret->type_mask = type_mask; ret->flag_mask = flag_mask; /* Make label */ ret->label = gtk_label_new(label); gtk_misc_set_alignment(GTK_MISC(ret->label), 0.0, 0.5); gtk_widget_show(ret->label); /* Make buttons */ /* Config */ ret->config_button = create_pixmap_button(ret, "config_16.png", TRS("Plugin options")); /* Info */ ret->info_button = create_pixmap_button(ret, "info_16.png", TRS("Plugin info")); /* Audio */ if(type_mask & (BG_PLUGIN_ENCODER_AUDIO | BG_PLUGIN_ENCODER)) { ret->audio_button = create_pixmap_button(ret, "audio_16.png", TRS("Audio options")); } /* Video */ if(type_mask & (BG_PLUGIN_ENCODER_VIDEO | BG_PLUGIN_ENCODER)) { ret->video_button = create_pixmap_button(ret, "video_16.png", TRS("Video options")); } /* Create combo */ num_plugins = bg_plugin_registry_get_num_plugins(reg, type_mask, flag_mask); default_info = bg_plugin_registry_get_default(reg, type_mask, flag_mask); /* Make combo */ default_index = -1; ret->combo = bg_gtk_combo_box_new_text(); g_signal_connect(G_OBJECT(ret->combo), "changed", G_CALLBACK(change_callback), (gpointer)ret); for(i = 0; i < num_plugins; i++) { info = bg_plugin_find_by_index(reg, i, type_mask, flag_mask); bg_gtk_combo_box_append_text(ret->combo, info->long_name); if(info == default_info) default_index = i; } if(default_index >= 0) gtk_combo_box_set_active(GTK_COMBO_BOX(ret->combo), default_index); /* Show */ gtk_widget_show(ret->combo); return ret; } void bg_gtk_plugin_widget_single_destroy(bg_gtk_plugin_widget_single_t * w) { if(w->handle) bg_plugin_unref(w->handle); if(w->section_priv) bg_cfg_section_destroy(w->section); if(w->audio_section_priv) bg_cfg_section_destroy(w->audio_section); if(w->video_section_priv) bg_cfg_section_destroy(w->video_section); if(w->subtitle_text_section_priv) bg_cfg_section_destroy(w->subtitle_text_section); if(w->subtitle_overlay_section_priv) bg_cfg_section_destroy(w->subtitle_overlay_section); free(w); } void bg_gtk_plugin_widget_single_attach(bg_gtk_plugin_widget_single_t * w, GtkWidget * table, int * row, int * num_columns) { int columns_needed = 4; int col; if(w->audio_button) columns_needed++; if(w->video_button) columns_needed++; if(*num_columns < columns_needed) *num_columns = columns_needed; gtk_table_resize(GTK_TABLE(table), *row+1, *num_columns); gtk_table_attach(GTK_TABLE(table), w->label, 0, 1, *row, *row+1, GTK_FILL, GTK_SHRINK, 0, 0); gtk_table_attach(GTK_TABLE(table), w->combo, 1, 2, *row, *row+1, GTK_FILL | GTK_EXPAND, GTK_SHRINK, 0, 0); gtk_table_attach(GTK_TABLE(table), w->info_button, 2, 3, *row, *row+1, GTK_FILL, GTK_SHRINK, 0, 0); gtk_table_attach(GTK_TABLE(table), w->config_button, 3, 4, *row, *row+1, GTK_FILL, GTK_SHRINK, 0, 0); col = 4; if(w->audio_button) { gtk_table_attach(GTK_TABLE(table), w->audio_button, col, col+1, *row, *row+1, GTK_FILL, GTK_SHRINK, 0, 0); col++; } if(w->video_button) { gtk_table_attach(GTK_TABLE(table), w->video_button, col, col+1, *row, *row+1, GTK_FILL, GTK_SHRINK, 0, 0); } (*row)++; } void bg_gtk_plugin_widget_single_set_sensitive(bg_gtk_plugin_widget_single_t * w, int sensitive) { gtk_widget_set_sensitive(w->combo, sensitive); gtk_widget_set_sensitive(w->info_button, sensitive); gtk_widget_set_sensitive(w->config_button, sensitive); if(w->audio_button) gtk_widget_set_sensitive(w->audio_button, sensitive); if(w->video_button) gtk_widget_set_sensitive(w->video_button, sensitive); if(sensitive) update_sensitive(w); } const bg_plugin_info_t * bg_gtk_plugin_widget_single_get_plugin(bg_gtk_plugin_widget_single_t * w) { return w->info; } void bg_gtk_plugin_widget_single_set_plugin(bg_gtk_plugin_widget_single_t * w, const bg_plugin_info_t * info) { int index; int num_plugins; int i; const bg_plugin_info_t * test_info; index = -1; num_plugins = bg_plugin_registry_get_num_plugins(w->reg, w->type_mask, w->flag_mask); for(i = 0; i < num_plugins; i++) { test_info = bg_plugin_find_by_index(w->reg, i, w->type_mask, w->flag_mask); if(info == test_info) { index = i; break; } } if(index >= 0) gtk_combo_box_set_active(GTK_COMBO_BOX(w->combo), index); } bg_plugin_handle_t * bg_gtk_plugin_widget_single_load_plugin(bg_gtk_plugin_widget_single_t * w) { if(w->handle) bg_plugin_unref(w->handle); w->handle = bg_plugin_load(w->reg, w->info); return w->handle; } bg_cfg_section_t * bg_gtk_plugin_widget_single_get_section(bg_gtk_plugin_widget_single_t * w) { return w->section; } bg_cfg_section_t * bg_gtk_plugin_widget_single_get_audio_section(bg_gtk_plugin_widget_single_t * w) { return w->audio_section; } bg_cfg_section_t * bg_gtk_plugin_widget_single_get_video_section(bg_gtk_plugin_widget_single_t * w) { return w->video_section; } bg_cfg_section_t * bg_gtk_plugin_widget_single_get_subtitle_text_section(bg_gtk_plugin_widget_single_t * w) { return w->subtitle_text_section; } bg_cfg_section_t * bg_gtk_plugin_widget_single_get_subtitle_overlay_section(bg_gtk_plugin_widget_single_t * w) { return w->subtitle_overlay_section; } void bg_gtk_plugin_widget_single_set_section(bg_gtk_plugin_widget_single_t * w, bg_cfg_section_t * s, int copy) { if(w->section_priv) bg_cfg_section_destroy(w->section); if(copy) { if(s) { w->section_priv = 1; w->section = bg_cfg_section_copy(s); } else w->section_priv = 0; } else { w->section = s; w->section_priv = 0; } } void bg_gtk_plugin_widget_single_set_audio_section(bg_gtk_plugin_widget_single_t * w, bg_cfg_section_t * s, int copy) { if(w->audio_section_priv) bg_cfg_section_destroy(w->audio_section); if(copy) { if(s) { w->audio_section_priv = 1; w->audio_section = bg_cfg_section_copy(s); } else w->audio_section_priv = 0; } else { w->audio_section = s; w->audio_section_priv = 0; } } void bg_gtk_plugin_widget_single_set_video_section(bg_gtk_plugin_widget_single_t * w, bg_cfg_section_t * s, int copy) { if(w->video_section_priv) bg_cfg_section_destroy(w->video_section); if(copy) { if(s) { w->video_section_priv = 1; w->video_section = bg_cfg_section_copy(s); } else w->video_section_priv = 0; } else { w->video_section = s; w->video_section_priv = 0; } } void bg_gtk_plugin_widget_single_set_subtitle_text_section(bg_gtk_plugin_widget_single_t * w, bg_cfg_section_t * s, int copy) { if(w->subtitle_text_section_priv) bg_cfg_section_destroy(w->subtitle_text_section); if(copy) { if(s) { w->subtitle_text_section_priv = 1; w->subtitle_text_section = bg_cfg_section_copy(s); } else w->subtitle_text_section_priv = 0; } else { w->subtitle_text_section = s; w->subtitle_text_section_priv = 0; } } void bg_gtk_plugin_widget_single_set_subtitle_overlay_section(bg_gtk_plugin_widget_single_t * w, bg_cfg_section_t * s, int copy) { if(w->subtitle_overlay_section_priv) bg_cfg_section_destroy(w->subtitle_overlay_section); if(copy) { if(s) { w->subtitle_overlay_section_priv = 1; w->subtitle_overlay_section = bg_cfg_section_copy(s); } else w->subtitle_overlay_section_priv = 0; } else { w->subtitle_overlay_section = s; w->subtitle_overlay_section_priv = 0; } } void bg_gtk_plugin_widget_single_show_buttons(bg_gtk_plugin_widget_single_t * w, int show) { if(show) { gtk_widget_show(w->config_button); gtk_widget_show(w->info_button); if(w->audio_button) gtk_widget_show(w->audio_button); if(w->video_button) gtk_widget_show(w->video_button); } else { gtk_widget_hide(w->config_button); gtk_widget_hide(w->info_button); if(w->audio_button) gtk_widget_hide(w->audio_button); if(w->video_button) gtk_widget_hide(w->video_button); } } gmerlin-1.2.0~dfsg/lib/gtk/albumwindow.c0000644000175000017500000002607011764363406020137 0ustar alessioalessio/***************************************************************** * gmerlin - a general purpose multimedia framework and applications * * Copyright (c) 2001 - 2011 Members of the Gmerlin project * gmerlin-general@lists.sourceforge.net * http://gmerlin.sourceforge.net * * 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 of the License, 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 this program. If not, see . * *****************************************************************/ #include #include #include #include #include #include #include /* This is missing in the gtk headers */ extern void gtk_decorated_window_move_resize_window(GtkWindow*, int, int, int, int); struct bg_gtk_album_window_s { bg_gtk_album_widget_t * widget; bg_gtk_tree_widget_t * tree_widget; GtkWidget * window; int x, y, width, height; bg_cfg_section_t * cfg_section; /* Notebook stuff */ GtkWidget * tab_close_button; GtkWidget * tab_label; GtkWidget * tab_widget; GtkWidget * notebook; int name_len; GtkAccelGroup * accel_group; }; /* Configuration stuff */ static const bg_parameter_info_t parameters[] = { { .name = "x", .long_name = "X", .type = BG_PARAMETER_INT, .val_default = { .val_i = 100 } }, { .name = "y", .long_name = "Y", .type = BG_PARAMETER_INT, .val_default = { .val_i = 100 } }, { .name = "width", .long_name = "Width", .type = BG_PARAMETER_INT, .val_default = { .val_i = 200 } }, { .name = "height", .long_name = "Height", .type = BG_PARAMETER_INT, .val_default = { .val_i = 300 } }, { /* End of parameters */ } }; static void set_parameter(void * data, const char * name, const bg_parameter_value_t * val) { bg_gtk_album_window_t * win; win = (bg_gtk_album_window_t*)data; if(!name) return; else if(!strcmp(name, "x")) { win->x = val->val_i; } else if(!strcmp(name, "y")) { win->y = val->val_i; } else if(!strcmp(name, "width")) { win->width = val->val_i; } else if(!strcmp(name, "height")) { win->height = val->val_i; } } static int get_parameter(void * data, const char * name, bg_parameter_value_t * val) { bg_gtk_album_window_t * win; win = (bg_gtk_album_window_t*)data; if(!name) return 1; else if(!strcmp(name, "x")) { val->val_i = win->x; return 1; } else if(!strcmp(name, "y")) { val->val_i = win->y; return 1; } else if(!strcmp(name, "width")) { val->val_i = win->width; return 1; } else if(!strcmp(name, "height")) { val->val_i = win->height; return 1; } return 0; } static gboolean delete_callback(GtkWidget * w, GdkEventAny * event, gpointer data) { bg_gtk_album_window_t * win; win = (bg_gtk_album_window_t*)data; bg_gtk_album_window_destroy(win, 1); return TRUE; } static void close_callback(GtkWidget * w, gpointer data) { bg_gtk_album_window_t * win; win = (bg_gtk_album_window_t*)data; bg_gtk_album_window_destroy(win, 1); } static void widget_close_callback(bg_gtk_album_widget_t * w, gpointer data) { bg_gtk_album_window_t * win; win = (bg_gtk_album_window_t*)data; bg_gtk_album_window_destroy(win, 1); } static void name_change_callback(bg_album_t * a, const char * name, void * data) { bg_gtk_album_window_t * win = (bg_gtk_album_window_t *)data; win->name_len = strlen(name); if(win->notebook) { gtk_label_set_text(GTK_LABEL(win->tab_label), name); } else if(win->window) { gtk_window_set_title(GTK_WINDOW(win->window), name); } } bg_gtk_album_window_t * bg_gtk_album_window_create(bg_album_t * album, bg_gtk_tree_widget_t * tree_widget, GtkAccelGroup * accel_group) { bg_gtk_album_window_t * ret; ret = calloc(1, sizeof(*ret)); ret->tree_widget = tree_widget; ret->accel_group = accel_group; bg_album_set_name_change_callback(album, name_change_callback, ret); ret->widget = bg_gtk_album_widget_create(album, ret->window); bg_gtk_album_widget_set_close_callback(ret->widget, widget_close_callback, ret); g_object_ref(G_OBJECT(bg_gtk_album_widget_get_widget(ret->widget))); /* Set config stuff */ ret->cfg_section = bg_cfg_section_find_subsection(bg_album_get_cfg_section(album), "gtk_albumwindow"); bg_cfg_section_apply(ret->cfg_section, parameters, set_parameter, ret); return ret; } void bg_gtk_album_window_destroy(bg_gtk_album_window_t * w, int notify) { int page_num; /* Get the window coordinates */ if(w->window && w->window->window) { gdk_window_get_geometry(w->window->window, NULL, NULL, &w->width, &w->height, NULL); gdk_window_get_root_origin(w->window->window, &w->x, &w->y); bg_cfg_section_get(w->cfg_section, parameters, get_parameter, w); } bg_gtk_album_widget_put_config(w->widget); if(w->tree_widget && notify) { bg_gtk_tree_widget_close_album(w->tree_widget, w); } if(w->window) gtk_widget_destroy(w->window); if(w->notebook) { page_num = gtk_notebook_page_num(GTK_NOTEBOOK(w->notebook), bg_gtk_album_widget_get_widget(w->widget)); gtk_notebook_remove_page(GTK_NOTEBOOK(w->notebook), page_num); } if(w->widget) { bg_album_set_name_change_callback(bg_gtk_album_widget_get_album(w->widget), NULL, NULL); g_object_unref(G_OBJECT(bg_gtk_album_widget_get_widget(w->widget))); bg_gtk_album_widget_destroy(w->widget); } free(w); } bg_album_t * bg_gtk_album_window_get_album(bg_gtk_album_window_t*w) { return bg_gtk_album_widget_get_album(w->widget); } void bg_gtk_album_window_raise(bg_gtk_album_window_t* w) { int page_num; if(w->window && w->window->window) gtk_window_present(GTK_WINDOW(w->window)); else if(w->notebook) { page_num = gtk_notebook_page_num(GTK_NOTEBOOK(w->notebook), bg_gtk_album_widget_get_widget(w->widget)); gtk_notebook_set_current_page(GTK_NOTEBOOK(w->notebook), page_num); } } static GtkWidget * create_close_button(bg_gtk_album_window_t * w) { GtkWidget * button; GtkWidget * image; char * path; path = bg_search_file_read("icons", "tab_close.png"); if(path) { image = gtk_image_new_from_file(path); free(path); } else image = gtk_image_new(); gtk_widget_show(image); button = gtk_button_new(); gtk_container_add(GTK_CONTAINER(button), image); g_signal_connect(G_OBJECT(button), "clicked", G_CALLBACK(close_callback), w); gtk_widget_show(button); return button; } void bg_gtk_album_window_attach(bg_gtk_album_window_t * w, GtkWidget * notebook) { const char * name; int page_num; bg_album_t * album; /* Remove widget from container and delete window */ if(w->window) { gtk_container_remove(GTK_CONTAINER(w->window), bg_gtk_album_widget_get_widget(w->widget)); gtk_widget_destroy(w->window); w->window = NULL; } /* Attach stuff to notebook */ album = bg_gtk_album_widget_get_album(w->widget); name = bg_album_get_label(album); w->tab_label = gtk_label_new(name); w->name_len = strlen(name); gtk_widget_show(w->tab_label); w->tab_close_button = create_close_button(w); w->tab_widget = gtk_hbox_new(0, 2); bg_gtk_box_pack_start_defaults(GTK_BOX(w->tab_widget), w->tab_label); gtk_box_pack_start(GTK_BOX(w->tab_widget), w->tab_close_button, FALSE, FALSE, 0); gtk_widget_show(w->tab_widget); page_num = gtk_notebook_get_n_pages(GTK_NOTEBOOK(notebook)); gtk_notebook_append_page(GTK_NOTEBOOK(notebook), bg_gtk_album_widget_get_widget(w->widget), w->tab_widget); gtk_notebook_set_current_page(GTK_NOTEBOOK(notebook), page_num); #if 0 #if GTK_CHECK_VERSION(2,20,0) g_object_set(notebook, "tab-fill", FALSE, NULL); #else gtk_notebook_set_tab_label_packing(GTK_NOTEBOOK(notebook), bg_gtk_album_widget_get_widget(w->widget), FALSE, FALSE, GTK_PACK_START); #endif #endif gtk_notebook_set_menu_label_text(GTK_NOTEBOOK(notebook), bg_gtk_album_widget_get_widget(w->widget), bg_album_get_label(album)); w->notebook = notebook; if(bg_album_is_current(album)) bg_gtk_album_window_set_current(w, 1); } void bg_gtk_album_window_detach(bg_gtk_album_window_t * w) { int page_num; bg_album_t * album; album = bg_gtk_album_widget_get_album(w->widget); if(w->notebook) { page_num = gtk_notebook_page_num(GTK_NOTEBOOK(w->notebook), bg_gtk_album_widget_get_widget(w->widget)); gtk_notebook_remove_page(GTK_NOTEBOOK(w->notebook), page_num); w->notebook = NULL; } w->window = bg_gtk_window_new(GTK_WINDOW_TOPLEVEL); gtk_window_add_accel_group(GTK_WINDOW (w->window), w->accel_group); gtk_window_add_accel_group(GTK_WINDOW (w->window), bg_gtk_album_widget_get_accel_group(w->widget)); g_signal_connect(G_OBJECT(w->window), "delete-event", G_CALLBACK(delete_callback), w); gtk_window_set_title(GTK_WINDOW(w->window), bg_album_get_label(album)); gtk_container_add(GTK_CONTAINER(w->window), bg_gtk_album_widget_get_widget(w->widget)); gtk_widget_show(w->window); gtk_decorated_window_move_resize_window(GTK_WINDOW(w->window), w->x, w->y, w->width, w->height); } void bg_gtk_album_window_set_current(bg_gtk_album_window_t * w, int current) { PangoAttribute *attr; PangoAttrList *attr_list; if(!w->notebook) return; attr_list = pango_attr_list_new(); attr = pango_attr_weight_new(current ? PANGO_WEIGHT_BOLD: PANGO_WEIGHT_NORMAL); attr->start_index = 0; attr->end_index = w->name_len; pango_attr_list_insert(attr_list,attr); gtk_label_set_attributes(GTK_LABEL(w->tab_label), attr_list); pango_attr_list_unref(attr_list); } void bg_gtk_album_window_goto_current(bg_gtk_album_window_t * w) { bg_gtk_album_window_raise(w); bg_gtk_album_widget_goto_current(w->widget); } GtkAccelGroup * bg_gtk_album_window_get_accel_group(bg_gtk_album_window_t * w) { return bg_gtk_album_widget_get_accel_group(w->widget); } gmerlin-1.2.0~dfsg/lib/gtk/cfg_time.c0000644000175000017500000001705111764363406017363 0ustar alessioalessio/***************************************************************** * gmerlin - a general purpose multimedia framework and applications * * Copyright (c) 2001 - 2011 Members of the Gmerlin project * gmerlin-general@lists.sourceforge.net * http://gmerlin.sourceforge.net * * 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 of the License, 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 this program. If not, see . * *****************************************************************/ #include #include #include "gtk_dialog.h" #include #include typedef struct { GtkWidget * label; GtkWidget * spinbutton_h; /* Hours */ GtkWidget * spinbutton_m; /* Minutes */ GtkWidget * spinbutton_s; /* Seconds */ GtkWidget * spinbutton_ms; /* Milleseconds */ GtkWidget * box; int no_change_callback; } spinbutton_t; /* typedef enum { GTK_EXPAND = 1 << 0, GTK_SHRINK = 1 << 1, GTK_FILL = 1 << 2 } GtkAttachOptions; */ static void destroy(bg_gtk_widget_t * w) { spinbutton_t * s = (spinbutton_t*)(w->priv); free(s); } static void set_time(spinbutton_t * s, gavl_time_t t) { int i; /* Fraction of a second */ i = t % GAVL_TIME_SCALE; i /= (GAVL_TIME_SCALE / 1000); gtk_spin_button_set_value(GTK_SPIN_BUTTON(s->spinbutton_ms), (gdouble)(i)); /* Seconds */ t /= GAVL_TIME_SCALE; i = t % 60; gtk_spin_button_set_value(GTK_SPIN_BUTTON(s->spinbutton_s), (gdouble)(i)); /* Minutes */ t /= 60; i = t % 60; gtk_spin_button_set_value(GTK_SPIN_BUTTON(s->spinbutton_m), (gdouble)(i)); /* Hours */ t /= 60; gtk_spin_button_set_value(GTK_SPIN_BUTTON(s->spinbutton_h), (gdouble)(t)); } static void get_value(bg_gtk_widget_t * w) { spinbutton_t * s = (spinbutton_t*)(w->priv); set_time(s, w->value.val_time); } static gavl_time_t get_time(spinbutton_t * s) { gavl_time_t ret; int hours, minutes, seconds, milliseconds; milliseconds = gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(s->spinbutton_ms)); seconds = gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(s->spinbutton_s)); minutes = gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(s->spinbutton_m)); hours = gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(s->spinbutton_h)); ret = hours; ret *= 60; ret += minutes; ret *= 60; ret += seconds; ret *= GAVL_TIME_SCALE; ret += milliseconds * (GAVL_TIME_SCALE / 1000); return ret; } static void set_value(bg_gtk_widget_t * w) { spinbutton_t * s = (spinbutton_t*)(w->priv); w->value.val_time = get_time(s); } static void change_callback(GtkWidget * w, gpointer data) { bg_gtk_widget_t * wid = (bg_gtk_widget_t *)data; spinbutton_t * s = (spinbutton_t*)(wid->priv); gavl_time_t t; int do_change = 0; if(s->no_change_callback) return; t = get_time(s); if(wid->info->val_max.val_time > wid->info->val_min.val_time) { if(t > wid->info->val_max.val_time) { do_change = 1; t = wid->info->val_max.val_time; } if(t < wid->info->val_min.val_time) { do_change = 1; t = wid->info->val_min.val_time; } } if(do_change) { s->no_change_callback = 1; set_time(s, t); s->no_change_callback = 0; } } static void attach(void * priv, GtkWidget * table, int * row, int * num_columns) { spinbutton_t * s = (spinbutton_t*)priv; if(*num_columns < 2) *num_columns = 2; gtk_table_resize(GTK_TABLE(table), *row + 1, *num_columns); gtk_table_attach(GTK_TABLE(table), s->label, 0, 1, *row, *row+1, GTK_FILL, GTK_SHRINK, 0, 0); gtk_table_attach(GTK_TABLE(table), s->box, 1, 2, *row, *row+1, GTK_FILL | GTK_EXPAND, GTK_SHRINK, 0, 0); *row += 1; } static const gtk_widget_funcs_t funcs = { .get_value = get_value, .set_value = set_value, .destroy = destroy, .attach = attach }; void bg_gtk_create_time(bg_gtk_widget_t * w, const char * translation_domain) { char * tooltip; GtkWidget * label; spinbutton_t * s = calloc(1, sizeof(*s)); s->label = gtk_label_new(TR_DOM(w->info->long_name)); gtk_widget_show(s->label); gtk_misc_set_alignment(GTK_MISC(s->label), 0.0, 0.5); s->spinbutton_ms = gtk_spin_button_new_with_range(0.0, 999.0, 1.0); s->spinbutton_s = gtk_spin_button_new_with_range(0.0, 59.0, 1.0); s->spinbutton_m = gtk_spin_button_new_with_range(0.0, 59.0, 1.0); s->spinbutton_h = gtk_spin_button_new_with_range(0.0, 1000000.0, 1.0); gtk_spin_button_set_digits(GTK_SPIN_BUTTON(s->spinbutton_ms), 0); gtk_spin_button_set_digits(GTK_SPIN_BUTTON(s->spinbutton_s), 0); gtk_spin_button_set_digits(GTK_SPIN_BUTTON(s->spinbutton_m), 0); gtk_spin_button_set_digits(GTK_SPIN_BUTTON(s->spinbutton_h), 0); if(w->info->help_string) { tooltip = bg_sprintf(TR("%s (Hours)"), TR_DOM(w->info->help_string)); bg_gtk_tooltips_set_tip(s->spinbutton_h, tooltip, PACKAGE); free(tooltip); tooltip = bg_sprintf(TR("%s (Minutes)"), TR_DOM(w->info->help_string)); bg_gtk_tooltips_set_tip(s->spinbutton_m, tooltip, PACKAGE); free(tooltip); tooltip = bg_sprintf(TR("%s (Seconds)"), TR_DOM(w->info->help_string)); bg_gtk_tooltips_set_tip(s->spinbutton_s, tooltip, PACKAGE); free(tooltip); tooltip = bg_sprintf(TR("%s (Milliseconds)"), TR_DOM(w->info->help_string)); bg_gtk_tooltips_set_tip(s->spinbutton_ms, tooltip, PACKAGE); free(tooltip); } g_signal_connect(G_OBJECT(s->spinbutton_ms), "value-changed", G_CALLBACK(change_callback), w); g_signal_connect(G_OBJECT(s->spinbutton_s), "value-changed", G_CALLBACK(change_callback), w); g_signal_connect(G_OBJECT(s->spinbutton_m), "value-changed", G_CALLBACK(change_callback), w); g_signal_connect(G_OBJECT(s->spinbutton_h), "value-changed", G_CALLBACK(change_callback), w); gtk_widget_show(s->spinbutton_ms); gtk_widget_show(s->spinbutton_s); gtk_widget_show(s->spinbutton_m); gtk_widget_show(s->spinbutton_h); s->box = gtk_hbox_new(0, 2); label = gtk_label_new(TR("h:")); gtk_widget_show(label); gtk_box_pack_start(GTK_BOX(s->box), label, FALSE, FALSE, 0); gtk_box_pack_start(GTK_BOX(s->box), s->spinbutton_h, FALSE, FALSE, 0); label = gtk_label_new(TR("m:")); gtk_widget_show(label); gtk_box_pack_start(GTK_BOX(s->box), label, FALSE, FALSE, 0); gtk_box_pack_start(GTK_BOX(s->box), s->spinbutton_m, FALSE, FALSE, 0); label = gtk_label_new(TR("s:")); gtk_widget_show(label); gtk_box_pack_start(GTK_BOX(s->box), label, FALSE, FALSE, 0); gtk_box_pack_start(GTK_BOX(s->box), s->spinbutton_s, FALSE, FALSE, 0); label = gtk_label_new(TR("ms:")); gtk_widget_show(label); gtk_box_pack_start(GTK_BOX(s->box), label, FALSE, FALSE, 0); bg_gtk_box_pack_start_defaults(GTK_BOX(s->box), s->spinbutton_ms); gtk_widget_show(s->box); gtk_widget_show(s->label); w->priv = s; w->funcs = &funcs; } gmerlin-1.2.0~dfsg/lib/gtk/albumwidget.c0000644000175000017500000027251211764363406020117 0ustar alessioalessio/***************************************************************** * gmerlin - a general purpose multimedia framework and applications * * Copyright (c) 2001 - 2011 Members of the Gmerlin project * gmerlin-general@lists.sourceforge.net * http://gmerlin.sourceforge.net * * 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 of the License, 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 this program. If not, see . * *****************************************************************/ #include #include #include #include #include #include #include #include #include #include #define LOG_DOMAIN "gtk_albumwidget" #include #include #include #include #include #include #include /* Since the gtk part is single threaded, we can load the pixbufs globally */ static GdkPixbuf * has_audio_pixbuf = NULL; static GdkPixbuf * has_video_pixbuf = NULL; static GdkPixbuf * has_still_pixbuf = NULL; static GdkPixbuf * dnd_pixbuf = NULL; #if GTK_MINOR_VERSION >= 12 #define gtk_tree_view_tree_to_widget_coords \ gtk_tree_view_convert_bin_window_to_widget_coords #endif int num_album_widgets = 0; /* Static stuff for deleting drag data */ // static bg_gtk_album_widget_t * drag_source = NULL; // static int drag_do_delete = 0; static GtkTargetList * target_list = NULL; static GtkTargetList * target_list_r = NULL; /* Drag & Drop struff */ /* 0 means unset */ #define DND_GMERLIN_TRACKS 1 #define DND_GMERLIN_TRACKS_R 2 #define DND_TEXT_URI_LIST 3 #define DND_TEXT_PLAIN 4 static const GtkTargetEntry dnd_src_entries[] = { { bg_gtk_atom_entries_name, 0, DND_GMERLIN_TRACKS }, { "STRING", 0, DND_TEXT_PLAIN }, { "text/plain", 0, DND_TEXT_PLAIN }, }; static const GtkTargetEntry dnd_src_entries_r[] = { { bg_gtk_atom_entries_name_r, 0, DND_GMERLIN_TRACKS_R }, {"STRING", 0, DND_TEXT_PLAIN }, }; static const GtkTargetEntry dnd_dst_entries[] = { {bg_gtk_atom_entries_name, 0, DND_GMERLIN_TRACKS }, {"text/uri-list", 0, DND_TEXT_URI_LIST }, {"STRING", 0, DND_TEXT_PLAIN }, {"text/plain", 0, DND_TEXT_URI_LIST }, }; static const GtkTargetEntry dnd_dst_entries_r[] = { { bg_gtk_atom_entries_name_r, GTK_TARGET_SAME_WIDGET, DND_GMERLIN_TRACKS_R }, }; static const GtkTargetEntry copy_paste_entries[] = { { bg_gtk_atom_entries_name, 0, DND_GMERLIN_TRACKS }, { "STRING", 0, DND_TEXT_PLAIN }, }; static void load_pixmaps() { char * filename; if(num_album_widgets) { num_album_widgets++; return; } num_album_widgets++; filename = bg_search_file_read("icons", "audio_16.png"); if(filename) { has_audio_pixbuf = gdk_pixbuf_new_from_file(filename, NULL); free(filename); } filename = bg_search_file_read("icons", "video_16.png"); if(filename) { has_video_pixbuf = gdk_pixbuf_new_from_file(filename, NULL); free(filename); } filename = bg_search_file_read("icons", "image_16.png"); if(filename) { has_still_pixbuf = gdk_pixbuf_new_from_file(filename, NULL); free(filename); } filename = bg_search_file_read("icons", "tracks_dnd_32.png"); if(filename) { dnd_pixbuf = gdk_pixbuf_new_from_file(filename, NULL); free(filename); } } static void unload_pixmaps() { num_album_widgets--; if(!num_album_widgets) { g_object_unref(has_audio_pixbuf); g_object_unref(has_video_pixbuf); g_object_unref(has_still_pixbuf); g_object_unref(dnd_pixbuf); has_audio_pixbuf = NULL; has_video_pixbuf = NULL; has_still_pixbuf = NULL; dnd_pixbuf = NULL; } } enum { COLUMN_INDEX, COLUMN_NAME, COLUMN_AUDIO, COLUMN_VIDEO, COLUMN_DURATION, COLUMN_WEIGHT, COLUMN_FG_COLOR, NUM_COLUMNS }; typedef struct { GtkWidget * files_item; GtkWidget * albums_item; GtkWidget * urls_item; GtkWidget * menu; } add_menu_t; typedef struct { GtkWidget * cut_item; GtkWidget * copy_item; GtkWidget * paste_item; GtkWidget * move_up_item; GtkWidget * move_down_item; GtkWidget * copy_to_favourites_item; GtkWidget * remove_item; GtkWidget * find_item; GtkWidget * menu; } edit_menu_t; typedef struct { GtkWidget * transcode_item; GtkWidget * rename_item; GtkWidget * refresh_item; GtkWidget * export_edl_item; GtkWidget * info_item; GtkWidget * menu; } selected_menu_t; typedef struct { GtkWidget * save_item; GtkWidget * sort_item; GtkWidget * menu; } album_menu_t; typedef struct { GtkWidget * add_item; add_menu_t add_menu; GtkWidget * edit_item; edit_menu_t edit_menu; GtkWidget * selected_item; selected_menu_t selected_menu; GtkWidget * album_item; album_menu_t album_menu; GtkWidget * select_error_item; GtkWidget * show_toolbar_item; GtkWidget * menu; } menu_t; typedef struct { GtkWidget * entry; GtkWidget * close_button; GtkWidget * up_button; GtkWidget * down_button; GtkWidget * match_case_button; GtkWidget * exact_button; GtkWidget * box; int visible; bg_album_seek_data_t * sd; bg_album_entry_t * last_match; } find_widget_t; struct bg_gtk_album_widget_s { GtkWidget * treeview; GtkWidget * widget; bg_album_t * album; const bg_album_entry_t * selected_entry; const bg_album_entry_t * current_entry; GtkTreeViewColumn * col_duration; GtkTreeViewColumn * col_name; // gulong select_handler_id; void (*close_callback)(bg_gtk_album_widget_t *, void*); void * close_callback_data; menu_t menu; guint drop_time; /* File selectors */ bg_gtk_filesel_t * add_files_filesel; bg_gtk_filesel_t * add_albums_filesel; bg_gtk_urlsel_t * add_urls_urlsel; GtkWidget * parent; guint modifier_mask; GdkDragAction drag_action; int num_entries; int last_clicked_row; int mouse_x, mouse_y; /* Buttons */ GtkWidget * add_files_button; GtkWidget * add_urls_button; GtkWidget * rename_selected_button; GtkWidget * info_button; GtkWidget * copy_to_favourites_button; GtkWidget * copy_button; GtkWidget * cut_button; GtkWidget * paste_button; GtkWidget * eject_button; GtkWidget * find_button; /* Display */ bg_gtk_time_display_t * total_time; /* Toolbar (can be hidden) */ GtkWidget * toolbar; GtkWidget * drag_dest; GtkWidget * drag_dest_current; /* Open path */ char * open_path; int release_updates_selection; /* For inserting */ int cursor_pos; /* xml string as clipboard */ char * clipboard; GtkAccelGroup * accel_group; int drag_delete; find_widget_t find_widget; }; static void find_widget_init(bg_gtk_album_widget_t * w); static void find_widget_run(bg_gtk_album_widget_t * w); static void find_widget_reset(bg_gtk_album_widget_t * w); /* Utilities */ static void display_selected(bg_gtk_album_widget_t * w) { GtkTreeModel * model; GtkTreeSelection * selection; int i; GtkTreeIter iter; model = gtk_tree_view_get_model(GTK_TREE_VIEW(w->treeview)); selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(w->treeview)); w->selected_entry = NULL; if(!gtk_tree_model_get_iter_first(model, &iter)) return; for(i = 0; i < w->num_entries; i++) { if(bg_album_entry_is_selected(w->album, i)) { gtk_tree_selection_select_iter(selection, &iter); if(!w->selected_entry) w->selected_entry = bg_album_get_entry(w->album, i); } else gtk_tree_selection_unselect_iter(selection, &iter); if(!gtk_tree_model_iter_next(model, &iter)) return; } } static bg_album_entry_t * path_2_entry(bg_gtk_album_widget_t * w, GtkTreePath * path) { int * indices; int index; indices = gtk_tree_path_get_indices(path); index = indices[0]; return (bg_album_get_entry(w->album, index)); } static int entry_2_iter(bg_gtk_album_widget_t * w, const bg_album_entry_t * entry, GtkTreeIter * iter) { int index; GtkTreeModel * model; index = bg_album_get_index(w->album, entry); if(index < 0) return 0; model = gtk_tree_view_get_model(GTK_TREE_VIEW(w->treeview)); return gtk_tree_model_iter_nth_child(model, iter, NULL, index); } /* Configuration stuff */ static const bg_parameter_info_t parameters[] = { { .name = "open_path", .long_name = "Open path", .type = BG_PARAMETER_DIRECTORY, .flags = BG_PARAMETER_HIDE_DIALOG, .val_default = { .val_str = "." }, }, { .name = "show_toolbar", .long_name = "Show toolbar", .type = BG_PARAMETER_CHECKBUTTON, .flags = BG_PARAMETER_HIDE_DIALOG, .val_default = { .val_i = 1 }, }, { /* End of parameters */ } }; static void set_parameter(void * data, const char * name, const bg_parameter_value_t * val) { bg_gtk_album_widget_t * w; w = (bg_gtk_album_widget_t *)data; if(!name) return; if(!strcmp(name, "open_path")) { w->open_path = bg_strdup(w->open_path, val->val_str); } else if(!strcmp(name, "show_toolbar")) { gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(w->menu.show_toolbar_item), val->val_i); } } static int get_parameter(void * data, const char * name, bg_parameter_value_t * val) { bg_gtk_album_widget_t * w; w = (bg_gtk_album_widget_t *)data; if(!name) return 1; if(!strcmp(name, "open_path")) { val->val_str = bg_strdup(val->val_str, w->open_path); return 1; } else if(!strcmp(name, "show_toolbar")) { val->val_i = gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(w->menu.show_toolbar_item)); } return 0; } static void do_set_sensitive(GtkWidget * w, int sensitive) { if(w) gtk_widget_set_sensitive(w, sensitive); } static void set_sensitive(bg_gtk_album_widget_t * w) { int num_selected; GtkTreeSelection * selection; selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(w->treeview)); num_selected = bg_album_num_selected(w->album); if(!num_selected) { do_set_sensitive(w->menu.selected_menu.rename_item, 0); do_set_sensitive(w->menu.selected_menu.info_item, 0); do_set_sensitive(w->menu.edit_menu.cut_item, 0); do_set_sensitive(w->menu.edit_menu.copy_item, 0); do_set_sensitive(w->info_button, 0); do_set_sensitive(w->menu.edit_menu.remove_item, 0); do_set_sensitive(w->menu.edit_menu.cut_item, 0); do_set_sensitive(w->menu.edit_menu.copy_item, 0); do_set_sensitive(w->rename_selected_button, 0); do_set_sensitive(w->menu.selected_menu.refresh_item, 0); do_set_sensitive(w->menu.selected_menu.export_edl_item, 0); do_set_sensitive(w->menu.selected_menu.transcode_item, 0); do_set_sensitive(w->menu.edit_menu.copy_to_favourites_item, 0); do_set_sensitive(w->copy_to_favourites_button, 0); do_set_sensitive(w->cut_button, 0); do_set_sensitive(w->copy_button, 0); do_set_sensitive(w->menu.edit_menu.move_up_item, 0); do_set_sensitive(w->menu.edit_menu.move_down_item, 0); w->selected_entry = NULL; } else if(num_selected == 1) { do_set_sensitive(w->menu.edit_menu.cut_item, 1); do_set_sensitive(w->menu.edit_menu.copy_item, 1); do_set_sensitive(w->menu.selected_menu.rename_item, 1); do_set_sensitive(w->menu.selected_menu.info_item, 1); do_set_sensitive(w->info_button, 1); do_set_sensitive(w->menu.edit_menu.remove_item, 1); do_set_sensitive(w->rename_selected_button, 1); do_set_sensitive(w->cut_button, 1); do_set_sensitive(w->copy_button, 1); do_set_sensitive(w->menu.selected_menu.refresh_item, 1); do_set_sensitive(w->menu.selected_menu.export_edl_item, 1); do_set_sensitive(w->menu.edit_menu.copy_to_favourites_item, 1); do_set_sensitive(w->menu.selected_menu.transcode_item, 1); do_set_sensitive(w->copy_to_favourites_button, 1); do_set_sensitive(w->cut_button, 1); do_set_sensitive(w->copy_button, 1); do_set_sensitive(w->menu.edit_menu.move_up_item, 1); do_set_sensitive(w->menu.edit_menu.move_down_item, 1); } else { do_set_sensitive(w->menu.edit_menu.cut_item, 1); do_set_sensitive(w->menu.edit_menu.copy_item, 1); do_set_sensitive(w->menu.selected_menu.rename_item, 0); do_set_sensitive(w->menu.selected_menu.info_item, 0); do_set_sensitive(w->info_button, 0); do_set_sensitive(w->menu.edit_menu.remove_item, 1); do_set_sensitive(w->rename_selected_button, 0); do_set_sensitive(w->cut_button, 1); do_set_sensitive(w->copy_button, 1); do_set_sensitive(w->menu.selected_menu.refresh_item, 1); do_set_sensitive(w->menu.selected_menu.export_edl_item, 1); do_set_sensitive(w->menu.edit_menu.copy_to_favourites_item, 1); do_set_sensitive(w->copy_to_favourites_button, 1); do_set_sensitive(w->cut_button, 1); do_set_sensitive(w->copy_button, 1); do_set_sensitive(w->menu.selected_menu.transcode_item, 1); do_set_sensitive(w->menu.edit_menu.move_up_item, 1); do_set_sensitive(w->menu.edit_menu.move_down_item, 1); w->selected_entry = NULL; } } static void update_cursor_pos(bg_gtk_album_widget_t * w) { GtkTreePath *path; if(!w->num_entries) { w->cursor_pos = 0; path = gtk_tree_path_new_from_indices(w->cursor_pos, -1); gtk_tree_view_set_drag_dest_row(GTK_TREE_VIEW(w->treeview), path, GTK_TREE_VIEW_DROP_BEFORE); gtk_tree_path_free(path); } else if(w->cursor_pos < w->num_entries) { if(w->cursor_pos < 0) w->cursor_pos = 0; path = gtk_tree_path_new_from_indices(w->cursor_pos, -1); gtk_tree_view_set_drag_dest_row(GTK_TREE_VIEW(w->treeview), path, GTK_TREE_VIEW_DROP_BEFORE); gtk_tree_path_free(path); } else { w->cursor_pos = w->num_entries; path = gtk_tree_path_new_from_indices(w->cursor_pos-1, -1); gtk_tree_view_set_drag_dest_row(GTK_TREE_VIEW(w->treeview), path, GTK_TREE_VIEW_DROP_AFTER); gtk_tree_path_free(path); } gtk_widget_queue_draw(w->treeview); // while(gdk_events_pending() || gtk_events_pending()) // gtk_main_iteration(); } static int get_visible_range(bg_gtk_album_widget_t * w, int * start_index, int * end_index) { int y1, y2; int x_dummy; GdkRectangle visible_rect; GtkTreePath * start_path, *end_path; int * start_indices, * end_indices; gtk_tree_view_get_visible_rect(GTK_TREE_VIEW(w->treeview), &visible_rect); gtk_tree_view_tree_to_widget_coords(GTK_TREE_VIEW(w->treeview), 0, visible_rect.y, &x_dummy, &y1); gtk_tree_view_tree_to_widget_coords(GTK_TREE_VIEW(w->treeview), 0, visible_rect.y + visible_rect.height, &x_dummy, &y2); if(!gtk_tree_view_get_path_at_pos(GTK_TREE_VIEW(w->treeview), 0, y1, &start_path, NULL, NULL, NULL)) return 0; if(!gtk_tree_view_get_path_at_pos(GTK_TREE_VIEW(w->treeview), 0, y2, &end_path, NULL, NULL, NULL)) { end_path = gtk_tree_path_new_from_indices(w->num_entries - 1, -1); } start_indices = gtk_tree_path_get_indices(start_path); end_indices = gtk_tree_path_get_indices(end_path); *start_index = *start_indices; *end_index = *end_indices; gtk_tree_path_free(start_path); gtk_tree_path_free(end_path); return 1; } static void scroll_to_cursor(bg_gtk_album_widget_t * w) { GtkTreePath * dst_path; int start_index, end_index; if(!get_visible_range(w, &start_index, &end_index)) return; if((w->cursor_pos <= start_index) || (w->cursor_pos >= end_index)) { if((w->cursor_pos && (w->cursor_pos <= start_index)) || (w->cursor_pos == w->num_entries)) dst_path = gtk_tree_path_new_from_indices(w->cursor_pos-1, -1); else dst_path = gtk_tree_path_new_from_indices(w->cursor_pos, -1); gtk_tree_view_scroll_to_cell(GTK_TREE_VIEW(w->treeview), dst_path, NULL, 0, 0.0, 0.0); gtk_tree_path_free(dst_path); } } static gboolean setup_drag_dest(gpointer data) { bg_gtk_album_widget_t * w; const GtkTargetEntry * dst_targets; int num_dst_targets; w = data; if(bg_album_get_type(w->album) == BG_ALBUM_TYPE_REMOVABLE) { dst_targets = dnd_dst_entries_r; num_dst_targets = sizeof(dnd_dst_entries_r)/sizeof(dnd_dst_entries_r[0]); } else { dst_targets = dnd_dst_entries; num_dst_targets = sizeof(dnd_dst_entries)/sizeof(dnd_dst_entries[0]); } if(!w->num_entries) { if(w->drag_dest_current == w->drag_dest) return FALSE; gtk_drag_dest_unset(w->treeview); gtk_drag_dest_set(w->drag_dest, GTK_DEST_DEFAULT_HIGHLIGHT | GTK_DEST_DEFAULT_DROP | GTK_DEST_DEFAULT_MOTION, dst_targets, num_dst_targets, GDK_ACTION_COPY | GDK_ACTION_MOVE); w->drag_dest_current = w->drag_dest; } else { if(w->drag_dest_current == w->treeview) return FALSE; gtk_drag_dest_unset(w->drag_dest); gtk_drag_dest_set(w->treeview, GTK_DEST_DEFAULT_HIGHLIGHT | GTK_DEST_DEFAULT_DROP | GTK_DEST_DEFAULT_MOTION, dst_targets, num_dst_targets, GDK_ACTION_COPY | GDK_ACTION_MOVE); w->drag_dest_current = w->treeview; } return FALSE; } static void update_entry(bg_gtk_album_widget_t * w, const bg_album_entry_t * entry, GtkTreeIter * iter, int current) { char string_buffer[GAVL_TIME_STRING_LEN + 32]; GtkTreeModel * model; model = gtk_tree_view_get_model(GTK_TREE_VIEW(w->treeview)); /* Color */ if(entry->flags & BG_ALBUM_ENTRY_ERROR) gtk_list_store_set(GTK_LIST_STORE(model), iter, COLUMN_FG_COLOR, "#FF0000", -1); else gtk_list_store_set(GTK_LIST_STORE(model), iter, COLUMN_FG_COLOR, "#000000", -1); if(current) gtk_list_store_set(GTK_LIST_STORE(model), iter, COLUMN_WEIGHT, PANGO_WEIGHT_BOLD, -1); else gtk_list_store_set(GTK_LIST_STORE(model), iter, COLUMN_WEIGHT, PANGO_WEIGHT_NORMAL, -1); /* Set index */ sprintf(string_buffer, "%d.", bg_album_get_index(w->album, entry) + 1); gtk_list_store_set(GTK_LIST_STORE(model), iter, COLUMN_INDEX, string_buffer, -1); /* Set name */ gtk_list_store_set(GTK_LIST_STORE(model), iter, COLUMN_NAME, entry->name, -1); /* Audio */ if(entry->num_audio_streams) gtk_list_store_set(GTK_LIST_STORE(model), iter, COLUMN_AUDIO, has_audio_pixbuf, -1); else gtk_list_store_set(GTK_LIST_STORE(model), iter, COLUMN_AUDIO, NULL, -1); /* Video */ if(entry->num_video_streams) gtk_list_store_set(GTK_LIST_STORE(model), iter, COLUMN_VIDEO, has_video_pixbuf, -1); else if(entry->num_still_streams) gtk_list_store_set(GTK_LIST_STORE(model), iter, COLUMN_VIDEO, has_still_pixbuf, -1); else gtk_list_store_set(GTK_LIST_STORE(model), iter, COLUMN_VIDEO, NULL, -1); /* Set time */ gavl_time_prettyprint(entry->duration, string_buffer); gtk_list_store_set(GTK_LIST_STORE(model), iter, COLUMN_DURATION, string_buffer, -1); } static void update_indices(bg_gtk_album_widget_t * w, int start) { int i; char string_buffer[32]; GtkTreeIter iter; GtkTreeModel * model; model = gtk_tree_view_get_model(GTK_TREE_VIEW(w->treeview)); gtk_tree_model_iter_nth_child (model, &iter, NULL, start); for(i = start; i < w->num_entries; i++) { sprintf(string_buffer, "%d.", i + 1); gtk_list_store_set(GTK_LIST_STORE(model), &iter, COLUMN_INDEX, string_buffer, -1); gtk_tree_model_iter_next(model, &iter); } // while(gdk_events_pending() || gtk_events_pending()) // gtk_main_iteration(); } static void bg_gtk_album_widget_update_entry(bg_gtk_album_widget_t * w, const bg_album_entry_t * entry, GtkTreeIter * iter) { bg_album_entry_t * current_entry; current_entry = bg_album_get_current_entry(w->album); update_entry(w, entry, iter, (current_entry == entry)); bg_gtk_time_display_update(w->total_time, bg_album_get_duration(w->album), BG_GTK_DISPLAY_MODE_HMS); } static void bg_gtk_album_widget_update(bg_gtk_album_widget_t * w) { GtkTreeModel * model; int i; const bg_album_entry_t * entry; GtkTreeIter iter; GtkTreeSelection * selection; gavl_time_t total_time = 0; w->current_entry = NULL; selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(w->treeview)); // g_signal_handler_block(G_OBJECT(selection), w->select_handler_id); model = gtk_tree_view_get_model(GTK_TREE_VIEW(w->treeview)); gtk_list_store_clear(GTK_LIST_STORE(model)); w->num_entries = bg_album_get_num_entries(w->album); w->current_entry = bg_album_get_current_entry(w->album); for(i = 0; i < w->num_entries; i++) { entry = bg_album_get_entry(w->album, i); gtk_list_store_append(GTK_LIST_STORE(model), &iter); update_entry(w, entry, &iter, entry == w->current_entry); if(total_time != GAVL_TIME_UNDEFINED) { if(entry->duration != GAVL_TIME_UNDEFINED) total_time += entry->duration; else total_time = GAVL_TIME_UNDEFINED; } #if 0 /* Set current track */ if(entry == current_entry) { gtk_list_store_set(GTK_LIST_STORE(model), &iter, COLUMN_WEIGHT, PANGO_WEIGHT_BOLD, -1); w->current_entry = entry; } else gtk_list_store_set(GTK_LIST_STORE(model), &iter, COLUMN_WEIGHT, PANGO_WEIGHT_NORMAL, -1); #endif /* Select entry */ if(entry->flags & BG_ALBUM_ENTRY_SELECTED) { gtk_tree_selection_select_iter(selection, &iter); w->selected_entry = entry; } } bg_gtk_time_display_update(w->total_time, bg_album_get_duration(w->album), BG_GTK_DISPLAY_MODE_HMS); set_sensitive(w); /* Set up drag destination */ /* Ok, since this function is called from within drag-data-received, we cannot touch the drag behaviour here. Therefore we'll set up an idle callback, to let things done when back in gtk_main() */ g_idle_add(setup_drag_dest, (gpointer)w); // g_signal_handler_unblock(G_OBJECT(selection), w->select_handler_id); w->last_clicked_row = -1; update_cursor_pos(w); display_selected(w); find_widget_reset(w); } /* Callback functions for the clipboard */ static void clipboard_get_func(GtkClipboard *clipboard, GtkSelectionData *selection_data, guint info, gpointer data) { GdkAtom type_atom; bg_gtk_album_widget_t * w = data; type_atom = gdk_atom_intern("STRING", FALSE); // type_atom = gdk_atom_intern(bg_gtk_atom_entries_name, FALSE); if(!type_atom) return; gtk_selection_data_set(selection_data, type_atom, 8, (uint8_t*)w->clipboard, strlen(w->clipboard)+1); } static void clipboard_clear_func(GtkClipboard *clipboard, gpointer data) { bg_gtk_album_widget_t * w = data; if(w->clipboard) { free(w->clipboard); w->clipboard = NULL; } } static void clipboard_received_func(GtkClipboard *clipboard, GtkSelectionData *selection_data, gpointer data) { bg_album_entry_t * entry; bg_gtk_album_widget_t * w = data; if(selection_data->length <= 0) { return; } entry = bg_album_get_entry(w->album, w->cursor_pos); bg_album_insert_xml_before(w->album, (char*)(selection_data->data), entry); } static void do_copy(bg_gtk_album_widget_t * w) { GtkClipboard *clipboard; GdkAtom clipboard_atom; clipboard_atom = gdk_atom_intern ("CLIPBOARD", FALSE); clipboard = gtk_clipboard_get(clipboard_atom); gtk_clipboard_set_with_data(clipboard, copy_paste_entries, sizeof(copy_paste_entries)/ sizeof(copy_paste_entries[0]), clipboard_get_func, clipboard_clear_func, (gpointer)w); if(w->clipboard) free(w->clipboard); w->clipboard = bg_album_save_selected_to_memory(w->album, 0); } static void do_cut(bg_gtk_album_widget_t * w) { do_copy(w); bg_album_delete_selected(w->album); } static void do_paste(bg_gtk_album_widget_t * w) { GtkClipboard *clipboard; GdkAtom clipboard_atom; GdkAtom target; // clipboard_atom = gdk_atom_intern ("PRIMARY", FALSE); clipboard_atom = gdk_atom_intern ("CLIPBOARD", FALSE); clipboard = gtk_clipboard_get(clipboard_atom); target = gdk_atom_intern(bg_gtk_atom_entries_name, FALSE); gtk_clipboard_request_contents(clipboard, target, clipboard_received_func, w); } static void add_file_callback(char ** files, const char * plugin, int prefer_edl, void * data) { bg_album_entry_t * entry; bg_gtk_album_widget_t * widget = data; gtk_widget_set_sensitive(widget->treeview, 0); entry = bg_album_get_entry(widget->album, widget->cursor_pos); bg_album_insert_urls_before(widget->album, files, plugin, prefer_edl, entry); gtk_widget_set_sensitive(widget->treeview, 1); widget->open_path = bg_strdup(widget->open_path, bg_gtk_filesel_get_directory(widget->add_files_filesel)); } static void add_urls_callback(char ** urls, const char * plugin, int prefer_edl, void * data) { bg_album_entry_t * entry; bg_gtk_album_widget_t * widget = data; gtk_widget_set_sensitive(widget->treeview, 0); entry = bg_album_get_entry(widget->album, widget->cursor_pos); bg_album_insert_urls_before(widget->album, urls, plugin, prefer_edl, entry); gtk_widget_set_sensitive(widget->treeview, 1); } static void add_albums_callback(char ** files, const char * plugin, int prefer_edl, void * data) { bg_album_entry_t * entry; bg_gtk_album_widget_t * widget = data; entry = bg_album_get_entry(widget->album, widget->cursor_pos); bg_album_insert_albums_before(widget->album, files, entry); } static void filesel_close_callback(bg_gtk_filesel_t * f, void * data) { bg_gtk_album_widget_t * widget = data; if(f == widget->add_albums_filesel) { widget->add_albums_filesel = NULL; } else if(f == widget->add_files_filesel) { widget->add_files_filesel = NULL; } gtk_widget_set_sensitive(widget->add_files_button, 1); gtk_widget_set_sensitive(widget->menu.add_menu.files_item, 1); } static void urlsel_close_callback(bg_gtk_urlsel_t * f, void * data) { bg_gtk_album_widget_t * widget = data; widget->add_urls_urlsel = NULL; gtk_widget_set_sensitive(widget->add_urls_button, 1); gtk_widget_set_sensitive(widget->menu.add_menu.urls_item, 1); } static void set_name(void * data, const char * name, const bg_parameter_value_t * val) { bg_gtk_album_widget_t * w; if(!name) return; w = data; if(!strcmp(name, "track_name") && w->selected_entry) { bg_album_rename_track(w->album, w->selected_entry, val->val_str); } } static void rename_current_entry(bg_gtk_album_widget_t * w) { bg_dialog_t * dialog; bg_parameter_info_t info[2]; if(!w->selected_entry) return; /* Set up parameter info */ memset(info, 0, sizeof(info)); info[0].name = "track_name"; info[0].long_name = TRS("Track name"); info[0].type = BG_PARAMETER_STRING; info[0].val_default.val_str = w->selected_entry->name; /* Create and run dialog */ dialog = bg_dialog_create(NULL, set_name, NULL, w, info, TR("Rename entry")); bg_dialog_show(dialog, w->treeview); bg_dialog_destroy(dialog); } static void add_files(bg_gtk_album_widget_t * widget) { char * tmp_string; tmp_string = bg_sprintf(TR("Add files to album %s"), bg_album_get_name(widget->album)); widget->add_files_filesel = bg_gtk_filesel_create(tmp_string, add_file_callback, filesel_close_callback, widget, widget->parent, bg_album_get_plugin_registry(widget->album), BG_PLUGIN_INPUT, BG_PLUGIN_FILE); free(tmp_string); bg_gtk_filesel_set_directory(widget->add_files_filesel, widget->open_path); gtk_widget_set_sensitive(widget->add_files_button, 0); gtk_widget_set_sensitive(widget->menu.add_menu.files_item, 0); bg_gtk_filesel_run(widget->add_files_filesel, 0); } static void add_urls(bg_gtk_album_widget_t * widget) { char * tmp_string; tmp_string = bg_sprintf(TR("Add URLS to album %s"), bg_album_get_name(widget->album)); widget->add_urls_urlsel = bg_gtk_urlsel_create(tmp_string, add_urls_callback, urlsel_close_callback, widget, widget->parent, bg_album_get_plugin_registry(widget->album), BG_PLUGIN_INPUT, BG_PLUGIN_URL); free(tmp_string); gtk_widget_set_sensitive(widget->add_urls_button, 0); gtk_widget_set_sensitive(widget->menu.add_menu.urls_item, 0); bg_gtk_urlsel_run(widget->add_urls_urlsel, 0, widget->add_urls_button); } static void remove_selected(bg_gtk_album_widget_t * widget) { bg_album_delete_selected(widget->album); } static void move_selected_up(bg_gtk_album_widget_t * widget) { bg_album_move_selected_up(widget->album); } static void move_selected_down(bg_gtk_album_widget_t * widget) { bg_album_move_selected_down(widget->album); } static void transcode_selected(bg_gtk_album_widget_t * w) { FILE * file; char * filename; char * str; char * command; str = bg_album_save_selected_to_memory(w->album, 0); filename = bg_create_unique_filename("/tmp/gmerlin-%08x.xml"); file = fopen(filename, "w"); if(!file) { free(filename); return; } fwrite(str, 1, strlen(str), file); fclose(file); command = bg_sprintf("gmerlin_transcoder_remote -launch -addalbum %s", filename); bg_system(command); remove(filename); free(filename); free(str); free(command); } static void menu_callback(GtkWidget * w, gpointer data) { char * tmp_string; bg_gtk_album_widget_t * widget = data; /* Add files */ if(w == widget->menu.add_menu.files_item) { add_files(widget); } /* Add URLS */ else if(w == widget->menu.add_menu.urls_item) { add_urls(widget); } /* Add Albums */ else if(w == widget->menu.add_menu.albums_item) { tmp_string = bg_sprintf(TR("Add albums to %s"), bg_album_get_name(widget->album)); widget->add_files_filesel = bg_gtk_filesel_create(tmp_string, add_albums_callback, filesel_close_callback, widget, widget->parent, NULL, 0, 0); free(tmp_string); bg_gtk_filesel_run(widget->add_files_filesel, 0); } /* Remove selected */ else if(w == widget->menu.edit_menu.remove_item) remove_selected(widget); /* Transcode selected */ else if(w == widget->menu.selected_menu.transcode_item) transcode_selected(widget); /* Select error tracks */ else if(w == widget->menu.select_error_item) { bg_album_select_error_tracks(widget->album); } /* Copy to favourites */ else if(w == widget->menu.edit_menu.copy_to_favourites_item) bg_album_copy_selected_to_favourites(widget->album); /* Move up/down */ else if(w == widget->menu.edit_menu.move_up_item) move_selected_up(widget); else if(w == widget->menu.edit_menu.move_down_item) move_selected_down(widget); /* Rename */ else if(w == widget->menu.selected_menu.rename_item) { rename_current_entry(widget); } /* Info */ else if(w == widget->menu.selected_menu.info_item) { bg_gtk_album_entry_show(widget->selected_entry, widget->treeview); } /* Cut */ else if(w == widget->menu.edit_menu.cut_item) { do_cut(widget); } /* Copy */ else if(w == widget->menu.edit_menu.copy_item) { do_copy(widget); } /* Paste */ else if(w == widget->menu.edit_menu.paste_item) { do_paste(widget); } /* Find */ else if(w == widget->menu.edit_menu.find_item) { find_widget_run(widget); } /* Refresh */ else if(w == widget->menu.selected_menu.refresh_item) { bg_album_refresh_selected(widget->album); } else if(w == widget->menu.selected_menu.export_edl_item) { bg_edl_t * edl; tmp_string = bg_gtk_get_filename_write("Export edl", NULL, 1, widget->treeview); if(tmp_string) { edl = bg_album_selected_to_edl(widget->album); if(edl) { bg_edl_save(edl, tmp_string); bg_edl_destroy(edl); } free(tmp_string); } } /* Sort */ else if(w == widget->menu.album_menu.sort_item) { bg_album_sort_entries(widget->album); } /* Save */ else if(w == widget->menu.album_menu.save_item) { tmp_string = bg_gtk_get_filename_write("Save album as", NULL, 1, widget->treeview); if(tmp_string) { bg_album_save(widget->album, tmp_string); free(tmp_string); } } /* Show toolbar */ else if(w == widget->menu.show_toolbar_item) { if(gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(widget->menu.show_toolbar_item))) gtk_widget_show(widget->toolbar); else gtk_widget_hide(widget->toolbar); } } static GtkWidget * create_item(bg_gtk_album_widget_t * w, GtkWidget * parent, const char * label, const char * pixmap) { GtkWidget * ret, *image; char * path; if(pixmap) { path = bg_search_file_read("icons", pixmap); if(path) { image = gtk_image_new_from_file(path); free(path); } else image = gtk_image_new(); gtk_widget_show(image); ret = gtk_image_menu_item_new_with_label(label); gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(ret), image); } else { ret = gtk_menu_item_new_with_label(label); } g_signal_connect(G_OBJECT(ret), "activate", G_CALLBACK(menu_callback), (gpointer)w); gtk_widget_show(ret); gtk_menu_shell_append(GTK_MENU_SHELL(parent), ret); return ret; } static GtkWidget * create_toggle_item(bg_gtk_album_widget_t * w, GtkWidget * parent, const char * label) { GtkWidget * ret; ret = gtk_check_menu_item_new_with_label(label); g_signal_connect(G_OBJECT(ret), "toggled", G_CALLBACK(menu_callback), (gpointer)w); gtk_widget_show(ret); gtk_menu_shell_append(GTK_MENU_SHELL(parent), ret); return ret; } static void init_menu(bg_gtk_album_widget_t * w) { bg_album_type_t type; type = bg_album_get_type(w->album); /* Add... */ if((type == BG_ALBUM_TYPE_REGULAR) || (type == BG_ALBUM_TYPE_INCOMING) || (type == BG_ALBUM_TYPE_FAVOURITES)) { w->menu.add_menu.menu = gtk_menu_new(); w->menu.add_menu.files_item = create_item(w, w->menu.add_menu.menu, TR("Files..."), "folder_open_16.png"); w->menu.add_menu.urls_item = create_item(w, w->menu.add_menu.menu, TR("URLs..."), "earth_16.png"); w->menu.add_menu.albums_item = create_item(w, w->menu.add_menu.menu, TR("Albums..."), NULL); gtk_widget_show(w->menu.add_menu.menu); } /* Edit */ w->menu.edit_menu.menu = gtk_menu_new(); if((type == BG_ALBUM_TYPE_REGULAR) || (type == BG_ALBUM_TYPE_INCOMING)) { w->menu.edit_menu.copy_to_favourites_item = create_item(w, w->menu.edit_menu.menu, TR("Copy to favourites"), "favourites_16.png"); gtk_widget_add_accelerator(w->menu.edit_menu.copy_to_favourites_item, "activate", w->accel_group, GDK_F10, 0, GTK_ACCEL_VISIBLE); } w->menu.edit_menu.move_up_item = create_item(w, w->menu.edit_menu.menu, TR("Move to top"), "top_16.png"); gtk_widget_add_accelerator(w->menu.edit_menu.move_up_item, "activate", w->accel_group, GDK_Home, GDK_MOD1_MASK, GTK_ACCEL_VISIBLE); w->menu.edit_menu.move_down_item = create_item(w, w->menu.edit_menu.menu, TR("Move to bottom"), "bottom_16.png"); gtk_widget_add_accelerator(w->menu.edit_menu.move_down_item, "activate", w->accel_group, GDK_End, GDK_MOD1_MASK, GTK_ACCEL_VISIBLE); w->menu.edit_menu.remove_item = create_item(w, w->menu.edit_menu.menu, TR("Remove"), "trash_16.png"); gtk_widget_add_accelerator(w->menu.edit_menu.remove_item, "activate", w->accel_group, GDK_Delete, GDK_CONTROL_MASK, GTK_ACCEL_VISIBLE); w->menu.edit_menu.cut_item = create_item(w, w->menu.edit_menu.menu, TR("Cut"), "cut_16.png"); gtk_widget_add_accelerator(w->menu.edit_menu.cut_item, "activate", w->accel_group, GDK_x, GDK_CONTROL_MASK, GTK_ACCEL_VISIBLE); w->menu.edit_menu.copy_item = create_item(w, w->menu.edit_menu.menu, TR("Copy"), "copy_16.png"); gtk_widget_add_accelerator(w->menu.edit_menu.copy_item, "activate", w->accel_group, GDK_c, GDK_CONTROL_MASK, GTK_ACCEL_VISIBLE); w->menu.edit_menu.paste_item = create_item(w, w->menu.edit_menu.menu, TR("Paste"), "paste_16.png"); gtk_widget_add_accelerator(w->menu.edit_menu.paste_item, "activate", w->accel_group, GDK_v, GDK_CONTROL_MASK, GTK_ACCEL_VISIBLE); w->menu.edit_menu.find_item = create_item(w, w->menu.edit_menu.menu, TR("Find..."), "find_16.png"); gtk_widget_add_accelerator(w->menu.edit_menu.find_item, "activate", w->accel_group, GDK_f, GDK_CONTROL_MASK, GTK_ACCEL_VISIBLE); /* Selected */ w->menu.selected_menu.menu = gtk_menu_new(); w->menu.selected_menu.rename_item = create_item(w, w->menu.selected_menu.menu, TR("Rename..."), "rename_16.png"); w->menu.selected_menu.info_item = create_item(w, w->menu.selected_menu.menu, TR("Info..."), "info_16.png"); gtk_widget_add_accelerator(w->menu.selected_menu.info_item, "activate", w->accel_group, GDK_i, GDK_CONTROL_MASK, GTK_ACCEL_VISIBLE); if(bg_search_file_exec("gmerlin_transcoder_remote", NULL)) w->menu.selected_menu.transcode_item = create_item(w, w->menu.selected_menu.menu, TR("Transcode"), NULL); if((type == BG_ALBUM_TYPE_REGULAR) || (type == BG_ALBUM_TYPE_FAVOURITES) || (type == BG_ALBUM_TYPE_INCOMING)) { w->menu.selected_menu.refresh_item = create_item(w, w->menu.selected_menu.menu, TR("Refresh"), "refresh_16.png"); w->menu.selected_menu.export_edl_item = create_item(w, w->menu.selected_menu.menu, TR("Export as EDL"), NULL); } gtk_widget_set_sensitive(w->menu.selected_menu.rename_item, 0); /* Album */ w->menu.album_menu.menu = gtk_menu_new(); if(type == BG_ALBUM_TYPE_REGULAR) { w->menu.album_menu.save_item = create_item(w, w->menu.album_menu.menu, TR("Save as..."), "save_16.png"); } w->menu.album_menu.sort_item = create_item(w, w->menu.album_menu.menu, TR("Sort"), "sort_16.png"); /* Root menu */ w->menu.menu = gtk_menu_new(); if((type == BG_ALBUM_TYPE_REGULAR) || (type == BG_ALBUM_TYPE_INCOMING) || (type == BG_ALBUM_TYPE_FAVOURITES)) { w->menu.add_item = create_item(w, w->menu.menu, TR("Add..."), NULL); gtk_menu_item_set_submenu(GTK_MENU_ITEM(w->menu.add_item), w->menu.add_menu.menu); } w->menu.edit_item = create_item(w, w->menu.menu, TR("Edit..."), NULL); gtk_menu_item_set_submenu(GTK_MENU_ITEM(w->menu.edit_item), w->menu.edit_menu.menu); w->menu.selected_item = create_item(w, w->menu.menu, TR("Selected..."), NULL); gtk_menu_item_set_submenu(GTK_MENU_ITEM(w->menu.selected_item), w->menu.selected_menu.menu); w->menu.album_item = create_item(w, w->menu.menu, TR("Album..."), NULL); gtk_menu_item_set_submenu(GTK_MENU_ITEM(w->menu.album_item), w->menu.album_menu.menu); w->menu.select_error_item = create_item(w, w->menu.menu, TR("Select error tracks"), NULL); w->menu.show_toolbar_item = create_toggle_item(w, w->menu.menu, TR("Show toolbar")); } #if 0 static void select_row_callback(GtkTreeSelection * sel, gpointer data) { int i; GtkTreeIter iter; GtkTreeModel * model; GtkTreeSelection * selection; bg_album_entry_t * album_entry; bg_gtk_album_widget_t * w = (bg_gtk_album_widget_t *)data; model = gtk_tree_view_get_model(GTK_TREE_VIEW(w->treeview)); if(!gtk_tree_model_get_iter_first(model, &iter)) return; selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(w->treeview)); for(i = 0; i < w->num_entries; i++) { album_entry = bg_album_get_entry(w->album, i); if(gtk_tree_selection_iter_is_selected(selection, &iter)) { album_entry->flags |= BG_ALBUM_ENTRY_SELECTED; w->selected_entry = album_entry; } else album_entry->flags &= ~BG_ALBUM_ENTRY_SELECTED; if(!gtk_tree_model_iter_next(model, &iter)) break; } set_sensitive(w); } #endif static void update_last_clicked(bg_gtk_album_widget_t * w, int clicked_row) { GtkTreePath * p; w->last_clicked_row = clicked_row; if(w->last_clicked_row >= 0) p = gtk_tree_path_new_from_indices(w->last_clicked_row, -1); else p = gtk_tree_path_new_from_indices(0, -1); #if 0 gtk_tree_view_set_cursor(GTK_TREE_VIEW(w->treeview), // NULL, p, NULL, FALSE); // #else gtk_tree_view_row_activated(GTK_TREE_VIEW(w->treeview), p, NULL); #endif gtk_tree_path_free(p); } static void update_selected(bg_gtk_album_widget_t * w, GtkTreePath * path, guint state, int force) { int num_selected; gint * indices; int clicked_row = -1; indices = gtk_tree_path_get_indices(path); clicked_row = indices[0]; num_selected = bg_album_num_selected(w->album); /* Get the clicked iter */ if(!force) /* Called by button press callback */ { if(bg_album_entry_is_selected(w->album, clicked_row) && (num_selected > 1)) { w->release_updates_selection = 1; return; } } gtk_tree_view_set_cursor(GTK_TREE_VIEW(w->treeview), // NULL, path, NULL, FALSE); if(state & GDK_CONTROL_MASK) { bg_album_toggle_select_entry(w->album, clicked_row); } else if(state & GDK_SHIFT_MASK) { /* Select anything between the last clicked row and here */ if(w->last_clicked_row >= 0) { bg_album_select_entries(w->album, w->last_clicked_row, clicked_row); } else { bg_album_unselect_all(w->album); bg_album_select_entry(w->album, clicked_row); } } else { bg_album_unselect_all(w->album); bg_album_select_entry(w->album, clicked_row); } if(w->last_clicked_row > clicked_row) { w->cursor_pos = clicked_row; } else /* Also for aw->last_clicked_row < 0 */ { w->cursor_pos = clicked_row+1; } update_cursor_pos(w); update_last_clicked(w, clicked_row); display_selected(w); set_sensitive(w); } static gboolean button_release_callback(GtkWidget * w, GdkEventButton * evt, gpointer data) { GtkTreePath * path; bg_gtk_album_widget_t * aw = (bg_gtk_album_widget_t *)data; if(!aw->release_updates_selection) return TRUE; if(!gtk_tree_view_get_path_at_pos(GTK_TREE_VIEW(aw->treeview), evt->x, evt->y, &path, NULL, NULL, NULL)) { /* Didn't click any entry, return here */ return TRUE; } update_selected(aw, path, evt->state, 1); aw->release_updates_selection = 0; gtk_tree_path_free(path); return TRUE; } static gboolean button_press_callback(GtkWidget * w, GdkEventButton * evt, gpointer data) { gint * indices; GtkTreePath * path; bg_gtk_album_widget_t * aw = (bg_gtk_album_widget_t *)data; if(!gtk_tree_view_get_path_at_pos(GTK_TREE_VIEW(aw->treeview), evt->x, evt->y, &path, NULL, NULL, NULL)) { path = NULL; /* Didn't click any entry, return here */ // return TRUE; } /* No matter which button was clicked, we must update the selection if the current track isn't already selected */ if((evt->type == GDK_BUTTON_PRESS) && path) { indices = gtk_tree_path_get_indices(path); aw->cursor_pos = *indices; gtk_widget_grab_focus(aw->treeview); update_selected(aw, path, evt->state, 0); } if(evt->button == 3) { gtk_menu_popup(GTK_MENU(aw->menu.menu), NULL, NULL, NULL, NULL, 3, evt->time); } else if((evt->button == 1) || (evt->button == 2)) { if((evt->type == GDK_2BUTTON_PRESS) && path) { if(aw->selected_entry) { /* Play that track */ bg_album_set_current(aw->album, aw->selected_entry); bg_album_play(aw->album); } } } if(evt->button == 1) { aw->mouse_x = (int)evt->x; aw->mouse_y = (int)evt->y; // if(path) // gtk_tree_view_row_activated(GTK_TREE_VIEW(aw->treeview), // path, NULL); } if(path) gtk_tree_path_free(path); return TRUE; } static int is_urilist(GtkSelectionData * data) { int ret; char * target_name; target_name = gdk_atom_name(data->target); if(!target_name) return 0; if(!strcmp(target_name, "text/uri-list") || !strcmp(target_name, "STRING") || !strcmp(target_name, "text/plain")) ret = 1; else ret = 0; g_free(target_name); return ret; } static int is_entries(GtkSelectionData * data) { int ret; char * target_name; target_name = gdk_atom_name(data->target); if(!target_name) return 0; if(!strcmp(target_name, bg_gtk_atom_entries_name)) ret = 1; else ret = 0; g_free(target_name); return ret; } static int is_entries_r(GtkSelectionData * data) { int ret; char * target_name; target_name = gdk_atom_name(data->target); if(!target_name) return 0; if(!strcmp(target_name, bg_gtk_atom_entries_name_r)) ret = 1; else ret = 0; g_free(target_name); return ret; } static void drag_received_callback(GtkWidget *widget, GdkDragContext *drag_context, gint x, gint y, GtkSelectionData *data, guint info, guint time, gpointer d) { GtkTreePath * path; GtkTreeViewDropPosition pos; bg_album_entry_t * entry; GtkTreeModel * model; bg_gtk_album_widget_t * aw; int do_delete = 0; int source_type = 0; aw = (bg_gtk_album_widget_t *)d; model = gtk_tree_view_get_model(GTK_TREE_VIEW(aw->treeview)); gtk_tree_view_get_dest_row_at_pos(GTK_TREE_VIEW(aw->treeview), x, y, &path, &pos); if(is_entries(data)) { source_type = DND_GMERLIN_TRACKS; if(drag_context->action == GDK_ACTION_MOVE) do_delete = 1; } else if(is_entries_r(data)) { source_type = DND_GMERLIN_TRACKS_R; if(drag_context->action == GDK_ACTION_MOVE) do_delete = 1; } else if(is_urilist(data)) { source_type = DND_TEXT_URI_LIST; } else { source_type = DND_TEXT_PLAIN; } if(path) { entry = path_2_entry(aw, path); gtk_tree_path_free(path); if(!entry) return; if(!source_type) return; switch(pos) { case GTK_TREE_VIEW_DROP_INTO_OR_BEFORE: case GTK_TREE_VIEW_DROP_BEFORE: switch(source_type) { case DND_GMERLIN_TRACKS: case DND_GMERLIN_TRACKS_R: bg_album_insert_xml_before(aw->album, (char*)(data->data), entry); break; case DND_TEXT_URI_LIST: gtk_widget_set_sensitive(aw->treeview, 0); bg_album_insert_urilist_before(aw->album, (char*)(data->data), data->length, entry); gtk_widget_set_sensitive(aw->treeview, 1); break; } break; case GTK_TREE_VIEW_DROP_AFTER: case GTK_TREE_VIEW_DROP_INTO_OR_AFTER: switch(source_type) { case DND_GMERLIN_TRACKS: case DND_GMERLIN_TRACKS_R: bg_album_insert_xml_after(aw->album, (char*)(data->data), entry); break; case DND_TEXT_URI_LIST: gtk_widget_set_sensitive(aw->treeview, 0); bg_album_insert_urilist_after(aw->album, (char*)(data->data), data->length, entry); gtk_widget_set_sensitive(aw->treeview, 1); break; } break; } } else { switch(source_type) { case DND_GMERLIN_TRACKS: bg_album_insert_xml_before(aw->album, (char*)(data->data), NULL); break; case DND_TEXT_URI_LIST: bg_album_insert_urilist_before(aw->album, (char*)(data->data), data->length, NULL); break; } } /* Tell source we are ready */ gtk_drag_finish(drag_context, TRUE, /* Success */ do_delete, /* Delete */ aw->drop_time); } static gboolean drag_drop_callback(GtkWidget *widget, GdkDragContext *drag_context, gint x, gint y, guint time, gpointer d) { bg_gtk_album_widget_t * aw = (bg_gtk_album_widget_t *)d; aw->drop_time = time; #if 0 gtk_drag_finish(drag_context, FALSE, /* Success */ FALSE, /* Delete */ aw->drop_time); return TRUE; #else return TRUE; #endif } static void drag_get_callback(GtkWidget *widget, GdkDragContext *drag_context, GtkSelectionData *data, guint info, guint time, gpointer user_data) { char * str; GdkAtom type_atom; GdkAtom target_atom; bg_gtk_album_widget_t * w; w = (bg_gtk_album_widget_t *)user_data; str = bg_album_save_selected_to_memory(w->album, 1); type_atom = gdk_atom_intern("STRING", FALSE); if(!type_atom) return; target_atom = gdk_atom_intern(bg_gtk_atom_entries_name, FALSE); if(target_atom == data->target) { str = bg_album_save_selected_to_memory(w->album, 1); gtk_selection_data_set(data, type_atom, 8, (uint8_t*)str, strlen(str)+1); free(str); w->drag_delete = 1; return; } target_atom = gdk_atom_intern(bg_gtk_atom_entries_name_r, FALSE); if(target_atom == data->target) { str = bg_album_save_selected_to_memory(w->album, 1); gtk_selection_data_set(data, type_atom, 8, (uint8_t*)str, strlen(str)+1); free(str); w->drag_delete = 1; return; } target_atom = gdk_atom_intern("STRING", FALSE); if(target_atom == data->target) { str = bg_album_selected_to_string(w->album); gtk_selection_data_set(data, type_atom, 8, (uint8_t*)str, strlen(str)); free(str); w->drag_delete = 0; return; } target_atom = gdk_atom_intern("text/plain", FALSE); if(target_atom == data->target) { str = bg_album_selected_to_string(w->album); gtk_selection_data_set(data, type_atom, 8, (uint8_t*)str, strlen(str)); free(str); w->drag_delete = 0; return; } } static gboolean drag_motion_callback(GtkWidget *widget, GdkDragContext *drag_context, gint x, gint y, guint time, gpointer user_data) { GtkTreePath * path; GtkTreeViewDropPosition pos; gint * indices; bg_gtk_album_widget_t * w = (bg_gtk_album_widget_t *)user_data; gdk_drag_status(drag_context, drag_context->suggested_action, time); if(gtk_tree_view_get_dest_row_at_pos(GTK_TREE_VIEW(w->treeview), x, y, &path, &pos)) { if(pos == GTK_TREE_VIEW_DROP_INTO_OR_BEFORE) pos = GTK_TREE_VIEW_DROP_BEFORE; else if(pos == GTK_TREE_VIEW_DROP_INTO_OR_AFTER) pos = GTK_TREE_VIEW_DROP_AFTER; indices = gtk_tree_path_get_indices(path); if(pos == GTK_TREE_VIEW_DROP_BEFORE) w->cursor_pos = *indices; else w->cursor_pos = *indices+1; gtk_tree_view_set_drag_dest_row(GTK_TREE_VIEW(w->treeview), path, pos); gtk_tree_path_free(path); } else if(path) gtk_tree_path_free(path); return TRUE; } static void drag_delete_callback(GtkWidget *widget, GdkDragContext *drag_context, gpointer user_data) { bg_gtk_album_widget_t * w = (bg_gtk_album_widget_t *)user_data; if(w->drag_delete) { bg_album_delete_selected(w->album); } } static gboolean motion_callback(GtkWidget * w, GdkEventMotion * evt, gpointer user_data) { GdkDragContext* ctx; bg_gtk_album_widget_t * wid = (bg_gtk_album_widget_t *)user_data; GtkTargetList * tl; GtkTreeSelection * selection; int num_selected; selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(wid->treeview)); num_selected = gtk_tree_selection_count_selected_rows(selection); if(bg_album_get_type(wid->album) == BG_ALBUM_TYPE_REMOVABLE) tl = target_list_r; else tl = target_list; if(evt->state & GDK_BUTTON1_MASK) { if((abs((int)(evt->x) - wid->mouse_x) + abs((int)(evt->y) - wid->mouse_y) < 10) || (!num_selected)) return FALSE; if(evt->state & GDK_CONTROL_MASK) { ctx = gtk_drag_begin(w, tl, GDK_ACTION_COPY, 1, (GdkEvent*)(evt)); gtk_drag_set_icon_pixbuf(ctx, dnd_pixbuf, 0, 0); wid->release_updates_selection = 0; } else { ctx = gtk_drag_begin(w, tl, GDK_ACTION_MOVE, 1, (GdkEvent*)(evt)); gtk_drag_set_icon_pixbuf(ctx, dnd_pixbuf, 0, 0); wid->release_updates_selection = 0; } } return TRUE; } static gboolean key_press_callback(GtkWidget * w, GdkEventKey * evt, gpointer user_data) { int i; GtkTreeIter iter; GtkTreeModel *tree_model; GtkTreeSelection * selection; gint start_index, end_index; bg_gtk_album_widget_t * wid = (bg_gtk_album_widget_t *)user_data; int old_cursor_pos; switch(evt->keyval) { case GDK_Up: if(wid->cursor_pos) { selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(wid->treeview)); tree_model = gtk_tree_view_get_model(GTK_TREE_VIEW(wid->treeview)); wid->cursor_pos--; if(evt->state & (GDK_SHIFT_MASK|GDK_CONTROL_MASK)) { selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(wid->treeview)); tree_model = gtk_tree_view_get_model(GTK_TREE_VIEW(wid->treeview)); gtk_tree_model_iter_nth_child(tree_model, &iter, NULL, wid->cursor_pos); if(evt->state & (GDK_SHIFT_MASK)) { gtk_tree_selection_select_iter(selection, &iter); bg_album_select_entry(wid->album, wid->cursor_pos); if(!wid->selected_entry) wid->selected_entry = bg_album_get_entry(wid->album, wid->cursor_pos); } else { gtk_tree_selection_unselect_iter(selection, &iter); bg_album_unselect_entry(wid->album, wid->cursor_pos); } set_sensitive(wid); } update_cursor_pos(wid); scroll_to_cursor(wid); } break; case GDK_Down: if(wid->cursor_pos < wid->num_entries) { if(evt->state & (GDK_SHIFT_MASK|GDK_CONTROL_MASK)) { selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(wid->treeview)); tree_model = gtk_tree_view_get_model(GTK_TREE_VIEW(wid->treeview)); gtk_tree_model_iter_nth_child(tree_model, &iter, NULL, wid->cursor_pos); if(evt->state & (GDK_SHIFT_MASK)) { gtk_tree_selection_select_iter(selection, &iter); bg_album_select_entry(wid->album, wid->cursor_pos); if(!wid->selected_entry) wid->selected_entry = bg_album_get_entry(wid->album, wid->cursor_pos); } else { gtk_tree_selection_unselect_iter(selection, &iter); bg_album_unselect_entry(wid->album, wid->cursor_pos); } set_sensitive(wid); } wid->cursor_pos++; update_cursor_pos(wid); scroll_to_cursor(wid); } break; case GDK_Page_Up: selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(wid->treeview)); tree_model = gtk_tree_view_get_model(GTK_TREE_VIEW(wid->treeview)); old_cursor_pos = wid->cursor_pos; get_visible_range(wid, &start_index, &end_index); wid->cursor_pos -= end_index - start_index; if(wid->cursor_pos < 0) wid->cursor_pos = 0; update_cursor_pos(wid); scroll_to_cursor(wid); if(wid->cursor_pos < old_cursor_pos) { selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(wid->treeview)); tree_model = gtk_tree_view_get_model(GTK_TREE_VIEW(wid->treeview)); gtk_tree_model_iter_nth_child(tree_model, &iter, NULL, wid->cursor_pos); for(i = wid->cursor_pos; i < old_cursor_pos; i++) { if(evt->state & (GDK_SHIFT_MASK)) { gtk_tree_selection_select_iter(selection, &iter); bg_album_select_entry(wid->album, i); if(!wid->selected_entry) wid->selected_entry = bg_album_get_entry(wid->album, i); } else gtk_tree_selection_unselect_iter(selection, &iter); gtk_tree_model_iter_next(tree_model, &iter); } if(evt->state & (GDK_SHIFT_MASK)) set_sensitive(wid); } break; case GDK_Page_Down: selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(wid->treeview)); tree_model = gtk_tree_view_get_model(GTK_TREE_VIEW(wid->treeview)); get_visible_range(wid, &start_index, &end_index); old_cursor_pos = wid->cursor_pos; wid->cursor_pos+=end_index - start_index; if(wid->cursor_pos > wid->num_entries) wid->cursor_pos = wid->num_entries; update_cursor_pos(wid); scroll_to_cursor(wid); if(wid->cursor_pos > old_cursor_pos) { selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(wid->treeview)); tree_model = gtk_tree_view_get_model(GTK_TREE_VIEW(wid->treeview)); gtk_tree_model_iter_nth_child(tree_model, &iter, NULL, old_cursor_pos); for(i = old_cursor_pos; i < wid->cursor_pos; i++) { if(evt->state & (GDK_SHIFT_MASK)) { gtk_tree_selection_select_iter(selection, &iter); bg_album_select_entry(wid->album, i); if(!wid->selected_entry) wid->selected_entry = bg_album_get_entry(wid->album, i); } else gtk_tree_selection_unselect_iter(selection, &iter); gtk_tree_model_iter_next(tree_model, &iter); } if(evt->state & (GDK_SHIFT_MASK)) set_sensitive(wid); } break; } return TRUE; } static gboolean album_changed_foreach(GtkTreeModel *model, GtkTreePath *path, GtkTreeIter *iter, gpointer data) { gtk_tree_model_row_changed(model, path, iter); return FALSE; } static void column_resize_callback(GtkTreeViewColumn * col, gint * width_val, gpointer data) { GtkTreeModel * model; int width_needed; int name_width; int width; bg_gtk_album_widget_t * w = (bg_gtk_album_widget_t *)data; width = col->width; if(col == w->col_duration) { gtk_tree_view_column_cell_get_size(col, NULL, NULL, NULL, &width_needed, NULL); name_width = gtk_tree_view_column_get_fixed_width (w->col_name); if(width > width_needed) { name_width += width - width_needed; gtk_tree_view_column_set_fixed_width (w->col_name, name_width); } else if(width < width_needed) { name_width -= width_needed - width; gtk_tree_view_column_set_fixed_width (w->col_name, name_width); } } model = gtk_tree_view_get_model(GTK_TREE_VIEW(w->treeview)); gtk_tree_model_foreach (GTK_TREE_MODEL(model), album_changed_foreach, NULL); } /* Callbacks called from the album */ static void change_callback(bg_album_t * a, void * data) { bg_gtk_album_widget_t * w = data; bg_gtk_album_widget_update(w); /* This is also called during loading of huge amounts of urls, so we update the GUI a bit */ while(gdk_events_pending() || gtk_events_pending()) gtk_main_iteration(); } static void entry_change_callback(bg_album_t * a, const bg_album_entry_t * e, void * data) { GtkTreeIter iter; bg_gtk_album_widget_t * w = data; if(entry_2_iter(w, e, &iter)) { bg_gtk_album_widget_update_entry(w, e, &iter); } /* This is also called during loading of huge amounts of urls, so we update the GUI a bit */ // while(gdk_events_pending() || gtk_events_pending()) // gtk_main_iteration(); } static void current_change_callback(bg_album_t * a, const bg_album_entry_t * current_entry, void * data) { bg_gtk_album_widget_t * w = data; GtkTreeIter iter; GtkTreeModel * model; model = gtk_tree_view_get_model(GTK_TREE_VIEW(w->treeview)); if(a == w->album) { if(w->current_entry != current_entry) { if(entry_2_iter(w, w->current_entry, &iter)) gtk_list_store_set(GTK_LIST_STORE(model), &iter, COLUMN_WEIGHT, PANGO_WEIGHT_NORMAL, -1); if(entry_2_iter(w, current_entry, &iter)) { gtk_list_store_set(GTK_LIST_STORE(model), &iter, COLUMN_WEIGHT, PANGO_WEIGHT_BOLD, -1); w->current_entry = current_entry; } } /* else do nothing */ } else { if(entry_2_iter(w, w->current_entry, &iter)) { gtk_list_store_set(GTK_LIST_STORE(model), &iter, COLUMN_WEIGHT, PANGO_WEIGHT_NORMAL, -1); } w->current_entry = NULL; } } static void delete_callback(bg_album_t * a, int * indices, void * data) { int i; bg_gtk_album_widget_t * w = data; GtkTreeIter iter; GtkTreeSelection * selection; GtkTreeModel * model; int cursor_diff = 0; model = gtk_tree_view_get_model(GTK_TREE_VIEW(w->treeview)); selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(w->treeview)); // g_signal_handler_block(G_OBJECT(selection), w->select_handler_id); i = 0; while(indices[i] >= 0) { /* The following works only if the incides grow monotonous */ if(!gtk_tree_model_iter_nth_child(model, &iter, NULL, indices[i] - i)) { // g_signal_handler_unblock(G_OBJECT(selection), // w->select_handler_id); return; } /* Decrease num_entries right now, because it will be used by a callback envoked by the following call */ w->num_entries--; if(indices[i] < w->cursor_pos) cursor_diff++; gtk_list_store_remove(GTK_LIST_STORE(model), &iter); i++; } update_last_clicked(w, -1); // g_signal_handler_unblock(G_OBJECT(selection), w->select_handler_id); w->cursor_pos -= cursor_diff; update_indices(w, indices[0]); update_cursor_pos(w); bg_gtk_time_display_update(w->total_time, bg_album_get_duration(w->album), BG_GTK_DISPLAY_MODE_HMS); set_sensitive(w); find_widget_reset(w); } static void insert_callback(bg_album_t * a, int start, int num, void * data) { int i; bg_album_entry_t * e; GtkTreeIter iter; // GtkTreeSelection * selection; GtkTreeModel * model; bg_gtk_album_widget_t * w = data; model = gtk_tree_view_get_model(GTK_TREE_VIEW(w->treeview)); update_last_clicked(w, -1); for(i = start; i < start + num; i++) { e = bg_album_get_entry(w->album, i); gtk_list_store_insert(GTK_LIST_STORE(model), &iter, i); w->num_entries++; bg_gtk_album_widget_update_entry(w, e, &iter); } update_indices(w, start + num); if(start <= w->cursor_pos) w->cursor_pos += num; update_cursor_pos(w); find_widget_reset(w); } /* */ static void button_callback(GtkWidget * wid, gpointer data) { bg_gtk_album_widget_t * w = data; if(wid == w->add_files_button) { add_files(w); } else if(wid == w->add_urls_button) { add_urls(w); } else if(wid == w->rename_selected_button) { rename_current_entry(w); } else if(wid == w->info_button) { bg_gtk_album_entry_show(w->selected_entry, w->info_button); } else if(wid == w->copy_to_favourites_button) { bg_album_copy_selected_to_favourites(w->album); } else if(wid == w->copy_button) { do_copy(w); } else if(wid == w->cut_button) { do_cut(w); } else if(wid == w->paste_button) { do_paste(w); } else if(wid == w->eject_button) { if(w->close_callback) w->close_callback(w, w->close_callback_data); bg_album_eject(w->album); } else if(wid == w->find_button) { find_widget_run(w); } } static GtkWidget * create_pixmap_button(bg_gtk_album_widget_t * w, const char * filename, const char * tooltip) { GtkWidget * button; GtkWidget * image; char * path; path = bg_search_file_read("icons", filename); if(path) { image = gtk_image_new_from_file(path); free(path); } else image = gtk_image_new(); gtk_widget_show(image); button = gtk_button_new(); gtk_container_add(GTK_CONTAINER(button), image); g_signal_connect(G_OBJECT(button), "clicked", G_CALLBACK(button_callback), w); gtk_widget_show(button); bg_gtk_tooltips_set_tip(button, tooltip, PACKAGE); return button; } bg_gtk_album_widget_t * bg_gtk_album_widget_create(bg_album_t * album, GtkWidget * parent) { bg_gtk_album_widget_t * ret; GtkTreeViewColumn * col; GtkListStore *store; GtkCellRenderer *renderer; GtkTreeSelection * selection; GtkWidget * scrolledwin; bg_cfg_section_t * section, * subsection; bg_album_type_t type; type = bg_album_get_type(album); load_pixmaps(); bg_gtk_tree_create_atoms(); if(!target_list) { target_list = gtk_target_list_new(dnd_src_entries, sizeof(dnd_src_entries)/sizeof(dnd_src_entries[0])); target_list_r = gtk_target_list_new(dnd_src_entries_r, sizeof(dnd_src_entries_r)/sizeof(dnd_src_entries_r[0])); } ret = calloc(1, sizeof(*ret)); ret->album = album; ret->parent = parent; ret->accel_group = gtk_accel_group_new(); bg_album_set_change_callback(album, change_callback, ret); bg_album_set_current_change_callback(album, current_change_callback, ret); bg_album_set_entry_change_callback(album, entry_change_callback, ret); bg_album_set_delete_callback(album, delete_callback, ret); bg_album_set_insert_callback(album, insert_callback, ret); /* Create list */ store = gtk_list_store_new(NUM_COLUMNS, G_TYPE_STRING, // Index G_TYPE_STRING, // Name GDK_TYPE_PIXBUF, // Has audio GDK_TYPE_PIXBUF, // Has video G_TYPE_STRING, // Duration G_TYPE_INT, // Weight G_TYPE_STRING); // Foreground ret->treeview = gtk_tree_view_new_with_model(GTK_TREE_MODEL(store)); gtk_widget_set_size_request(ret->treeview, 200, 100); gtk_tree_view_set_rules_hint(GTK_TREE_VIEW(ret->treeview), TRUE); selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(ret->treeview)); gtk_tree_selection_set_mode(selection, GTK_SELECTION_MULTIPLE); #if 0 ret->select_handler_id = g_signal_connect(G_OBJECT(selection), "changed", G_CALLBACK(select_row_callback), (gpointer)ret); #endif gtk_tree_view_set_headers_visible(GTK_TREE_VIEW(ret->treeview), 0); /* Set list callbacks */ gtk_widget_set_events(ret->treeview, GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | GDK_KEY_PRESS_MASK | GDK_BUTTON1_MOTION_MASK ); g_signal_connect(G_OBJECT(ret->treeview), "button-press-event", G_CALLBACK(button_press_callback), (gpointer)ret); g_signal_connect(G_OBJECT(ret->treeview), "button-release-event", G_CALLBACK(button_release_callback), (gpointer)ret); g_signal_connect(G_OBJECT(ret->treeview), "key-press-event", G_CALLBACK(key_press_callback), (gpointer)ret); g_signal_connect(G_OBJECT(ret->treeview), "motion-notify-event", G_CALLBACK(motion_callback), (gpointer)ret); g_signal_connect(G_OBJECT(ret->treeview), "drag-data-delete", G_CALLBACK(drag_delete_callback), (gpointer)ret); g_signal_connect(G_OBJECT(ret->treeview), "drag-data-received", G_CALLBACK(drag_received_callback), (gpointer)ret); g_signal_connect(G_OBJECT(ret->treeview), "drag-drop", G_CALLBACK(drag_drop_callback), (gpointer)ret); g_signal_connect(G_OBJECT(ret->treeview), "drag-data-get", G_CALLBACK(drag_get_callback), (gpointer)ret); g_signal_connect(G_OBJECT(ret->treeview), "drag-motion", G_CALLBACK(drag_motion_callback), (gpointer)ret); /* Create columns */ /* Index */ renderer = gtk_cell_renderer_text_new(); g_object_set(G_OBJECT(renderer), "xalign", 1.0, NULL); col = gtk_tree_view_column_new (); gtk_tree_view_column_set_title(col, "I"); gtk_tree_view_column_pack_start(col, renderer, FALSE); gtk_tree_view_column_add_attribute(col, renderer, "text", COLUMN_INDEX); gtk_tree_view_column_add_attribute(col, renderer, "weight", COLUMN_WEIGHT); gtk_tree_view_column_add_attribute(col, renderer, "foreground", COLUMN_FG_COLOR); gtk_tree_view_column_set_sizing(col, GTK_TREE_VIEW_COLUMN_GROW_ONLY); gtk_tree_view_append_column (GTK_TREE_VIEW(ret->treeview), col); /* Name */ renderer = gtk_cell_renderer_text_new(); g_object_set(G_OBJECT(renderer), "xalign", 0.0, NULL); col = gtk_tree_view_column_new (); gtk_tree_view_column_pack_start(col, renderer, TRUE); gtk_tree_view_column_add_attribute(col, renderer, "text", COLUMN_NAME); gtk_tree_view_column_add_attribute(col, renderer, "weight", COLUMN_WEIGHT); gtk_tree_view_column_add_attribute(col, renderer, "foreground", COLUMN_FG_COLOR); gtk_tree_view_column_set_sizing(col, GTK_TREE_VIEW_COLUMN_FIXED); gtk_tree_view_append_column (GTK_TREE_VIEW(ret->treeview), col); ret->col_name = col; /* Audio */ renderer = gtk_cell_renderer_pixbuf_new(); col = gtk_tree_view_column_new (); gtk_tree_view_column_pack_start(col, renderer, FALSE); gtk_tree_view_column_add_attribute(col, renderer, "pixbuf", COLUMN_AUDIO); gtk_tree_view_column_set_sizing(col, GTK_TREE_VIEW_COLUMN_GROW_ONLY); gtk_tree_view_append_column (GTK_TREE_VIEW(ret->treeview), col); /* Video */ renderer = gtk_cell_renderer_pixbuf_new(); col = gtk_tree_view_column_new (); gtk_tree_view_column_pack_start(col, renderer, FALSE); gtk_tree_view_column_add_attribute(col, renderer, "pixbuf", COLUMN_VIDEO); gtk_tree_view_column_set_sizing(col, GTK_TREE_VIEW_COLUMN_GROW_ONLY); gtk_tree_view_append_column (GTK_TREE_VIEW(ret->treeview), col); /* Duration */ renderer = gtk_cell_renderer_text_new(); g_object_set(G_OBJECT(renderer), "xalign", 1.0, NULL); col = gtk_tree_view_column_new (); g_signal_connect(G_OBJECT(col), "notify::width", G_CALLBACK(column_resize_callback), (gpointer)ret); gtk_tree_view_column_set_title(col, "T"); gtk_tree_view_column_pack_start(col, renderer, FALSE); gtk_tree_view_column_add_attribute(col, renderer, "text", COLUMN_DURATION); gtk_tree_view_column_add_attribute(col, renderer, "weight", COLUMN_WEIGHT); gtk_tree_view_column_add_attribute(col, renderer, "foreground", COLUMN_FG_COLOR); gtk_tree_view_column_set_sizing(col, GTK_TREE_VIEW_COLUMN_FIXED); gtk_tree_view_append_column (GTK_TREE_VIEW(ret->treeview), col); ret->col_duration = col; /* Done with columns */ gtk_widget_show(ret->treeview); scrolledwin = gtk_scrolled_window_new(gtk_tree_view_get_hadjustment(GTK_TREE_VIEW(ret->treeview)), gtk_tree_view_get_vadjustment(GTK_TREE_VIEW(ret->treeview))); ret->drag_dest = scrolledwin; g_signal_connect(G_OBJECT(ret->drag_dest), "drag-data-received", G_CALLBACK(drag_received_callback), (gpointer)ret); gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolledwin), GTK_POLICY_NEVER, GTK_POLICY_ALWAYS); gtk_container_add(GTK_CONTAINER(scrolledwin), ret->treeview); gtk_widget_show(scrolledwin); /* Create toolbar */ if((type == BG_ALBUM_TYPE_REGULAR) || (type == BG_ALBUM_TYPE_INCOMING) || (type == BG_ALBUM_TYPE_FAVOURITES)) { ret->add_files_button = create_pixmap_button(ret, "folder_open_16.png", TRS("Add files")); ret->add_urls_button = create_pixmap_button(ret, "earth_16.png", TRS("Add URLs")); ret->cut_button = create_pixmap_button(ret, "cut_16.png", TRS("Cut")); ret->copy_button = create_pixmap_button(ret, "copy_16.png", TRS("Copy")); ret->paste_button = create_pixmap_button(ret, "paste_16.png", TRS("Paste")); } if(type == BG_ALBUM_TYPE_REMOVABLE && bg_album_can_eject(ret->album)) { ret->eject_button = create_pixmap_button(ret, "eject_16.png", TRS("Close album and eject disc")); } if((type == BG_ALBUM_TYPE_REGULAR) || (type == BG_ALBUM_TYPE_INCOMING)) ret->copy_to_favourites_button = create_pixmap_button(ret, "favourites_16.png", TRS("Copy selected tracks to favourites")); ret->rename_selected_button = create_pixmap_button(ret, "rename_16.png", TRS("Rename selected track")); ret->info_button = create_pixmap_button(ret, "info_16.png", TRS("Show track info")); ret->find_button = create_pixmap_button(ret, "find_16.png", TRS("Find tracks")); ret->total_time = bg_gtk_time_display_create(BG_GTK_DISPLAY_SIZE_SMALL, 4, BG_GTK_DISPLAY_MODE_HMS); bg_gtk_tooltips_set_tip(bg_gtk_time_display_get_widget(ret->total_time), TRS("Total playback time"), PACKAGE); find_widget_init(ret); ret->toolbar = gtk_hbox_new(0, 0); #define PACK_BUTTON(but) if(ret->but) gtk_box_pack_start(GTK_BOX(ret->toolbar), ret->but, FALSE, FALSE, 0); PACK_BUTTON(add_files_button); PACK_BUTTON(add_urls_button); PACK_BUTTON(info_button); PACK_BUTTON(rename_selected_button); PACK_BUTTON(cut_button); PACK_BUTTON(copy_button); PACK_BUTTON(paste_button); PACK_BUTTON(find_button); PACK_BUTTON(copy_to_favourites_button); PACK_BUTTON(eject_button); #undef PACK_BUTTON gtk_box_pack_end(GTK_BOX(ret->toolbar), bg_gtk_time_display_get_widget(ret->total_time), FALSE, FALSE, 0); // gtk_widget_show(ret->toolbar); ret->widget = gtk_vbox_new(0, 0); bg_gtk_box_pack_start_defaults(GTK_BOX(ret->widget), scrolledwin); gtk_box_pack_start(GTK_BOX(ret->widget), ret->find_widget.box, FALSE, FALSE, 0); gtk_box_pack_start(GTK_BOX(ret->widget), ret->toolbar, FALSE, FALSE, 0); init_menu(ret); /* Get config params from the album */ section = bg_album_get_cfg_section(album); subsection = bg_cfg_section_find_subsection(section, "gtk_albumwidget"); bg_cfg_section_apply(subsection, parameters, set_parameter, ret); bg_gtk_album_widget_update(ret); gtk_widget_show(ret->widget); update_last_clicked(ret, -1); return ret; } void bg_gtk_album_widget_put_config(bg_gtk_album_widget_t * w) { bg_cfg_section_t * section, * subsection; section = bg_album_get_cfg_section(w->album); subsection = bg_cfg_section_find_subsection(section, "gtk_albumwidget"); bg_cfg_section_get(subsection, parameters, get_parameter, w); } void bg_gtk_album_widget_destroy(bg_gtk_album_widget_t * w) { if(w->open_path) free(w->open_path); if(w->clipboard) free(w->clipboard); bg_gtk_time_display_destroy(w->total_time); bg_album_set_change_callback(w->album, NULL, NULL); bg_album_set_current_change_callback(w->album, NULL, NULL); bg_album_set_entry_change_callback(w->album, NULL, NULL); bg_album_set_delete_callback(w->album, NULL, NULL); bg_album_set_insert_callback(w->album, NULL, NULL); g_object_unref(w->accel_group); if(w->find_widget.sd) bg_album_seek_data_destroy(w->find_widget.sd); free(w); unload_pixmaps(); } GtkWidget * bg_gtk_album_widget_get_widget(bg_gtk_album_widget_t * w) { return w->widget; } bg_album_t * bg_gtk_album_widget_get_album(bg_gtk_album_widget_t * w) { return w->album; } void bg_gtk_album_widget_goto_current(bg_gtk_album_widget_t * aw) { int i; const bg_album_entry_t * entry, *current_entry; GtkTreeSelection * selection; GtkTreePath * path; current_entry = bg_album_get_current_entry(aw->album); if(!current_entry) return; selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(aw->treeview)); gtk_tree_selection_unselect_all(selection); for(i = 0; i < aw->num_entries; i++) { entry = bg_album_get_entry(aw->album, i); if(entry == current_entry) { path = gtk_tree_path_new_from_indices(i, -1); gtk_tree_selection_select_path(selection, path); gtk_tree_view_scroll_to_cell(GTK_TREE_VIEW(aw->treeview), path, NULL, 1, 0.0, 0.5); gtk_tree_path_free(path); break; } } } GtkAccelGroup * bg_gtk_album_widget_get_accel_group(bg_gtk_album_widget_t * w) { return w->accel_group; } void bg_gtk_album_widget_set_close_callback(bg_gtk_album_widget_t * w, void (*callback)(bg_gtk_album_widget_t *, void*), void* data) { w->close_callback = callback; w->close_callback_data = data; } /* Find widget */ static int prepare_seek(bg_gtk_album_widget_t * w) { const char * text; text = gtk_entry_get_text(GTK_ENTRY(w->find_widget.entry)); if(!text || (*text == '\0')) return 0; bg_album_seek_data_set_string(w->find_widget.sd, text); bg_album_seek_data_ignore_case(w->find_widget.sd, !gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(w->find_widget.match_case_button))); bg_album_seek_data_exact_string(w->find_widget.sd, gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(w->find_widget.exact_button))); if(bg_album_seek_data_changed(w->find_widget.sd)) w->find_widget.last_match = NULL; return 1; } static void find_widget_button_callback(GtkWidget * wid, gpointer data) { bg_gtk_album_widget_t * w; bg_album_entry_t * e = NULL; int index; GtkTreePath * p; w = data; if(wid == w->find_widget.up_button) { if(!prepare_seek(w)) return; e = bg_album_seek_entry_before(w->album, w->find_widget.last_match, w->find_widget.sd); if(!e) { if(w->find_widget.last_match) { e = bg_album_seek_entry_before(w->album, NULL, w->find_widget.sd); if(e) bg_log(BG_LOG_INFO, LOG_DOMAIN, "Backward search hit top, continuing at bottom"); } } if(!e) { bg_album_unselect_all(w->album); display_selected(w); w->find_widget.last_match = NULL; bg_log(BG_LOG_WARNING, LOG_DOMAIN, "Backward search: No tracks found"); } } else if(wid == w->find_widget.down_button) { if(!prepare_seek(w)) return; e = bg_album_seek_entry_after(w->album, w->find_widget.last_match, w->find_widget.sd); if(!e) { if(w->find_widget.last_match) { e = bg_album_seek_entry_after(w->album, NULL, w->find_widget.sd); if(e) bg_log(BG_LOG_INFO, LOG_DOMAIN, "Forward search hit bottom, continuing at top"); } } if(!e) { bg_album_unselect_all(w->album); display_selected(w); w->find_widget.last_match = NULL; bg_log(BG_LOG_WARNING, LOG_DOMAIN, "Forward search: No tracks found"); } } else if(wid == w->find_widget.close_button) { gtk_widget_hide(w->find_widget.box); w->find_widget.visible = 0; } if(e) { w->find_widget.last_match = e; index = bg_album_get_index(w->album, e); p = gtk_tree_path_new_from_indices(index, -1); gtk_tree_view_set_cursor(GTK_TREE_VIEW(w->treeview), // NULL, p, NULL, FALSE); bg_album_unselect_all(w->album); bg_album_select_entry(w->album, index); display_selected(w); gtk_tree_path_free(p); } } static GtkWidget * find_create_pixmap_button(bg_gtk_album_widget_t * w, const char * filename, const char * tooltip) { GtkWidget * button; GtkWidget * image; char * path; path = bg_search_file_read("icons", filename); if(path) { image = gtk_image_new_from_file(path); free(path); } else image = gtk_image_new(); gtk_widget_show(image); button = gtk_button_new(); gtk_container_add(GTK_CONTAINER(button), image); g_signal_connect(G_OBJECT(button), "clicked", G_CALLBACK(find_widget_button_callback), w); gtk_widget_show(button); bg_gtk_tooltips_set_tip(button, tooltip, PACKAGE); return button; } static GtkWidget * find_create_check_button(bg_gtk_album_widget_t * w, const char * name, const char * tooltip) { GtkWidget * button; button = gtk_check_button_new_with_label(name); gtk_widget_show(button); bg_gtk_tooltips_set_tip(button, tooltip, PACKAGE); return button; } static gboolean find_key_press_callback(GtkWidget * w, GdkEventKey * evt, gpointer user_data) { bg_gtk_album_widget_t * wid = (bg_gtk_album_widget_t *)user_data; switch(evt->keyval) { case GDK_Return: find_widget_button_callback(wid->find_widget.down_button, user_data); break; case GDK_Escape: gtk_widget_hide(wid->find_widget.box); wid->find_widget.visible = 0; break; default: break; } return FALSE; } static void find_widget_init(bg_gtk_album_widget_t * w) { w->find_widget.box = gtk_hbox_new(0, 0); } static void find_widget_reset(bg_gtk_album_widget_t * w) { w->find_widget.last_match = NULL; } static void find_widget_run(bg_gtk_album_widget_t * w) { if(!w->find_widget.sd) { w->find_widget.down_button = find_create_pixmap_button(w, "down_16.png", "Seek forward"); w->find_widget.up_button = find_create_pixmap_button(w, "up_16.png", "Seek backward"); w->find_widget.close_button = find_create_pixmap_button(w, "close_16.png", "Close search"); w->find_widget.sd = bg_album_seek_data_create(); w->find_widget.entry = gtk_entry_new(); gtk_widget_set_events(w->find_widget.entry, GDK_KEY_PRESS_MASK ); g_signal_connect(G_OBJECT(w->find_widget.entry), "key-press-event", G_CALLBACK(find_key_press_callback), (gpointer)w); gtk_widget_show(w->find_widget.entry); w->find_widget.exact_button = find_create_check_button(w, TRS("Exact match"), TRS("String is an exact substring")); w->find_widget.match_case_button = find_create_check_button(w, TRS("Match case"), TRS("Match upper and lower case")); gtk_box_pack_start(GTK_BOX(w->find_widget.box), w->find_widget.close_button, FALSE, FALSE, 0); bg_gtk_box_pack_start_defaults(GTK_BOX(w->find_widget.box), w->find_widget.entry); gtk_box_pack_start(GTK_BOX(w->find_widget.box), w->find_widget.down_button, FALSE, FALSE, 0); gtk_box_pack_start(GTK_BOX(w->find_widget.box), w->find_widget.up_button, FALSE, FALSE, 0); gtk_box_pack_start(GTK_BOX(w->find_widget.box), w->find_widget.match_case_button, FALSE, FALSE, 0); gtk_box_pack_start(GTK_BOX(w->find_widget.box), w->find_widget.exact_button, FALSE, FALSE, 0); } if(!w->find_widget.visible) { gtk_widget_show(w->find_widget.box); gtk_widget_grab_focus(w->find_widget.entry); w->find_widget.visible = 1; return; } find_widget_button_callback(w->find_widget.down_button, w); } gmerlin-1.2.0~dfsg/lib/gtk/cfg_checkbutton.c0000644000175000017500000000560211764363406020735 0ustar alessioalessio/***************************************************************** * gmerlin - a general purpose multimedia framework and applications * * Copyright (c) 2001 - 2011 Members of the Gmerlin project * gmerlin-general@lists.sourceforge.net * http://gmerlin.sourceforge.net * * 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 of the License, 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 this program. If not, see . * *****************************************************************/ #include #include "gtk_dialog.h" #include typedef struct { GtkWidget * button; } checkbutton_t; static void get_value(bg_gtk_widget_t * w) { checkbutton_t * priv; priv = (checkbutton_t*)(w->priv); gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(priv->button), w->value.val_i); } static void set_value(bg_gtk_widget_t * w) { checkbutton_t * priv; priv = (checkbutton_t*)(w->priv); w->value.val_i = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(priv->button)); } static void destroy(bg_gtk_widget_t * w) { checkbutton_t * priv = (checkbutton_t *)w->priv; free(priv); } static void attach(void * priv, GtkWidget * table, int * row, int * num_columns) { checkbutton_t * b = (checkbutton_t*)priv; if(*num_columns < 2) *num_columns = 2; gtk_table_resize(GTK_TABLE(table), *row+1, *num_columns); gtk_table_attach(GTK_TABLE(table), b->button, 0, 2, *row, *row+1, GTK_FILL | GTK_EXPAND, GTK_FILL, 0, 0); (*row)++; } static const gtk_widget_funcs_t funcs = { .get_value = get_value, .set_value = set_value, .destroy = destroy, .attach = attach }; void bg_gtk_create_checkbutton(bg_gtk_widget_t * w, const char * translation_domain) { checkbutton_t * priv = calloc(1, sizeof(*priv)); priv->button = gtk_check_button_new_with_label(TR_DOM(w->info->long_name)); if(w->info->flags & BG_PARAMETER_SYNC) { w->callback_id = g_signal_connect(G_OBJECT(priv->button), "toggled", G_CALLBACK(bg_gtk_change_callback), (gpointer)w); w->callback_widget = priv->button; } if(w->info->help_string) { bg_gtk_tooltips_set_tip(priv->button, w->info->help_string, translation_domain); } gtk_widget_show(priv->button); w->funcs = &funcs; w->priv = priv; } gmerlin-1.2.0~dfsg/lib/gtk/textwindow.c0000644000175000017500000000715511764363406020026 0ustar alessioalessio/***************************************************************** * gmerlin - a general purpose multimedia framework and applications * * Copyright (c) 2001 - 2011 Members of the Gmerlin project * gmerlin-general@lists.sourceforge.net * http://gmerlin.sourceforge.net * * 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 of the License, 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 this program. If not, see . * *****************************************************************/ #include #include #include #include /* Box for displaying static text */ struct bg_gtk_textwindow_s { GtkWidget * window; GtkWidget * close_button; bg_gtk_textview_t * textview; }; static void button_callback(GtkWidget * w, gpointer data) { bg_gtk_textwindow_t * win; win = (bg_gtk_textwindow_t*)data; bg_gtk_textview_destroy(win->textview); gtk_widget_hide(win->window); gtk_widget_destroy(win->window); free(win); } static gboolean delete_callback(GtkWidget * w, GdkEventAny * event, gpointer data) { button_callback(w, data); return TRUE; } bg_gtk_textwindow_t * bg_gtk_textwindow_create(const char * text, const char * title) { GtkWidget * table; bg_gtk_textwindow_t * ret; ret = calloc(1, sizeof(*ret)); ret->window = bg_gtk_window_new(GTK_WINDOW_TOPLEVEL); gtk_window_set_type_hint(GTK_WINDOW(ret->window), GDK_WINDOW_TYPE_HINT_DIALOG); gtk_window_set_position(GTK_WINDOW(ret->window), GTK_WIN_POS_CENTER); g_signal_connect(G_OBJECT(ret->window), "delete_event", G_CALLBACK(delete_callback), (gpointer)ret); gtk_window_set_title(GTK_WINDOW(ret->window), title); /* Create close button */ ret->close_button = gtk_button_new_from_stock(GTK_STOCK_CLOSE); bg_gtk_widget_set_can_default(ret->close_button, TRUE); g_signal_connect(G_OBJECT(ret->close_button), "clicked", G_CALLBACK(button_callback), (gpointer)ret); gtk_widget_show(ret->close_button); table = gtk_table_new(2, 1, 0); gtk_table_set_row_spacings(GTK_TABLE(table), 5); gtk_table_set_col_spacings(GTK_TABLE(table), 5); gtk_container_set_border_width(GTK_CONTAINER(table), 5); /* Create text */ ret->textview = bg_gtk_textview_create(); bg_gtk_textview_update(ret->textview, text); gtk_table_attach_defaults(GTK_TABLE(table), bg_gtk_textview_get_widget(ret->textview), 0, 1, 0, 1); gtk_table_attach(GTK_TABLE(table), ret->close_button, 0, 1, 1, 2, GTK_SHRINK, GTK_SHRINK, 0, 0); gtk_widget_show(table); gtk_container_add(GTK_CONTAINER(ret->window), table); return ret; } void bg_gtk_textwindow_show(bg_gtk_textwindow_t * w, int modal, GtkWidget * parent) { parent = bg_gtk_get_toplevel(parent); if(parent) { gtk_window_set_transient_for(GTK_WINDOW(w->window), GTK_WINDOW(parent)); } gtk_window_set_modal(GTK_WINDOW(w->window), modal); gtk_widget_grab_default(w->close_button); gtk_widget_show(w->window); } gmerlin-1.2.0~dfsg/lib/gtk/logwindow.c0000644000175000017500000003464611764363406017630 0ustar alessioalessio/***************************************************************** * gmerlin - a general purpose multimedia framework and applications * * Copyright (c) 2001 - 2011 Members of the Gmerlin project * gmerlin-general@lists.sourceforge.net * http://gmerlin.sourceforge.net * * 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 of the License, 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 this program. If not, see . * *****************************************************************/ #include #include #include #include #include #include #include #include /* This is missing in the gtk headers */ extern void gtk_decorated_window_move_resize_window(GtkWindow*, int, int, int, int); /* Delay between update calls in Milliseconds */ #define DELAY_TIME 50 struct bg_gtk_log_window_s { GtkWidget * window; GtkWidget * textview; GtkTextBuffer * buffer; GtkWidget * scrolledwindow; void (*close_callback)(bg_gtk_log_window_t*, void*); void * close_callback_data; bg_msg_queue_t * queue; GtkTextTagTable * tag_table; GtkTextTag * info_tag; GtkTextTag * debug_tag; GtkTextTag * error_tag; GtkTextTag * warning_tag; int visible; int num_messages; int max_messages; int show_info; int show_warning; int show_error; int show_debug; int x, y, width, height; char * last_error; }; static gboolean delete_callback(GtkWidget * w, GdkEventAny * event, gpointer data) { bg_gtk_log_window_t * win; win = (bg_gtk_log_window_t*)data; if(win->close_callback) win->close_callback(win, win->close_callback_data); gtk_widget_hide(win->window); win->visible = 0; return TRUE; } static void delete_first_line(bg_gtk_log_window_t * win) { GtkTextIter start_iter, end_iter; gtk_text_buffer_get_iter_at_line(win->buffer, &start_iter, 0); gtk_text_buffer_get_iter_at_line(win->buffer, &end_iter, 1); gtk_text_buffer_delete(win->buffer, &start_iter, &end_iter); win->num_messages--; } static void changed_callback(gpointer data) { bg_gtk_log_window_t * w; GtkTextIter iter; GtkTextMark * mark = NULL; w = (bg_gtk_log_window_t *)data; gtk_text_buffer_get_end_iter(w->buffer, &iter); mark = gtk_text_buffer_create_mark(w->buffer, NULL, &iter, FALSE); gtk_text_view_scroll_mark_onscreen(GTK_TEXT_VIEW(w->textview), mark); gtk_text_buffer_delete_mark(w->buffer, mark); // gtk_text_view_scroll_to_iter(GTK_TEXT_VIEW(w->textview), // &iter, 0.0, FALSE, 0.0, 0.0); } static gboolean idle_callback(gpointer data) { bg_msg_t * msg; bg_gtk_log_window_t * w; bg_log_level_t level; const char * level_name; char * domain; char * message; GtkTextTag * tag = NULL; char * str; GtkTextIter iter; int i; char ** lines; int got_message = 0; int do_log = 0; w = (bg_gtk_log_window_t *)data; while((msg = bg_msg_queue_try_lock_read(w->queue))) { while(w->num_messages > w->max_messages - 1) delete_first_line(w); level = bg_msg_get_id(msg); level_name = bg_log_level_to_string(level); domain = bg_msg_get_arg_string(msg, 0); message = bg_msg_get_arg_string(msg, 1); do_log = 0; switch(level) { case BG_LOG_DEBUG: tag = w->debug_tag; if(w->show_debug) do_log = 1; break; case BG_LOG_WARNING: tag = w->warning_tag; if(w->show_warning) do_log = 1; break; case BG_LOG_ERROR: tag = w->error_tag; if(w->show_error) do_log = 1; w->last_error = bg_strdup(w->last_error, message); break; case BG_LOG_INFO: tag = w->info_tag; if(w->show_info) do_log = 1; break; } if(do_log) { gtk_text_buffer_get_end_iter(w->buffer, &iter); if(*message == '\0') /* Empty string */ { str = bg_sprintf("[%s]\n", domain); gtk_text_buffer_insert_with_tags(w->buffer, &iter, str, -1, tag, NULL); } else { lines = bg_strbreak(message, '\n'); i = 0; while(lines[i]) { str = bg_sprintf("[%s]: %s\n", domain, lines[i]); gtk_text_buffer_insert_with_tags(w->buffer, &iter, str, -1, tag, NULL); free(str); i++; } bg_strbreak_free(lines); } w->num_messages++; got_message = 1; } free(message); free(domain); bg_msg_queue_unlock_read(w->queue); } if(got_message) changed_callback(w); return TRUE; } static gboolean configure_callback(GtkWidget * w, GdkEventConfigure *event, gpointer data) { bg_gtk_log_window_t * win; win = (bg_gtk_log_window_t*)data; win->x = event->x; win->y = event->y; win->width = event->width; win->height = event->height; gdk_window_get_root_origin(win->window->window, &win->x, &win->y); return FALSE; } bg_gtk_log_window_t * bg_gtk_log_window_create(void (*close_callback)(bg_gtk_log_window_t*, void*), void * close_callback_data, const char * app_name) { char * tmp_string; bg_gtk_log_window_t * ret; ret = calloc(1, sizeof(*ret)); /* Create window */ ret->window = bg_gtk_window_new(GTK_WINDOW_TOPLEVEL); tmp_string = bg_sprintf(TR("%s messages"), app_name); gtk_window_set_title(GTK_WINDOW(ret->window), tmp_string); free(tmp_string); g_signal_connect(G_OBJECT(ret->window), "delete_event", G_CALLBACK(delete_callback), (gpointer)ret); g_signal_connect(G_OBJECT(ret->window), "configure-event", G_CALLBACK(configure_callback), (gpointer)ret); /* Create and connect message queue */ ret->queue = bg_msg_queue_create(); bg_log_set_dest(ret->queue); ret->close_callback = close_callback; ret->close_callback_data = close_callback_data; /* Create tag table */ ret->tag_table = gtk_text_tag_table_new(); ret->info_tag = gtk_text_tag_new(NULL); ret->debug_tag = gtk_text_tag_new(NULL); ret->error_tag = gtk_text_tag_new(NULL); ret->warning_tag = gtk_text_tag_new(NULL); gtk_text_tag_table_add(ret->tag_table, ret->info_tag); gtk_text_tag_table_add(ret->tag_table, ret->debug_tag); gtk_text_tag_table_add(ret->tag_table, ret->error_tag); gtk_text_tag_table_add(ret->tag_table, ret->warning_tag); /* Create textbuffer */ ret->buffer = gtk_text_buffer_new(ret->tag_table); /* Create textview */ ret->textview = gtk_text_view_new_with_buffer(ret->buffer); gtk_text_view_set_editable(GTK_TEXT_VIEW(ret->textview), FALSE); gtk_text_view_set_cursor_visible(GTK_TEXT_VIEW(ret->textview), FALSE); gtk_widget_set_size_request(ret->textview, 300, 100); gtk_widget_show(ret->textview); /* Create scrolledwindow */ ret->scrolledwindow = gtk_scrolled_window_new(NULL, NULL); gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(ret->scrolledwindow), GTK_POLICY_ALWAYS, GTK_POLICY_ALWAYS); gtk_container_add(GTK_CONTAINER(ret->scrolledwindow), ret->textview); gtk_widget_show(ret->scrolledwindow); gtk_container_add(GTK_CONTAINER(ret->window), ret->scrolledwindow); /* Add idle callback */ g_timeout_add(DELAY_TIME, idle_callback, (gpointer)ret); return ret; } void bg_gtk_log_window_destroy(bg_gtk_log_window_t * win) { if(win->last_error) free(win->last_error); gtk_widget_destroy(win->window); free(win); } void bg_gtk_log_window_show(bg_gtk_log_window_t * w) { if(!w->width || !w->height) { gtk_window_set_position(GTK_WINDOW(w->window), GTK_WIN_POS_CENTER_ON_PARENT); } gtk_widget_show(w->window); if(w->width && w->height) gtk_decorated_window_move_resize_window(GTK_WINDOW(w->window), w->x, w->y, w->width, w->height); else gtk_window_resize(GTK_WINDOW(w->window), 600, 300); w->visible = 1; } void bg_gtk_log_window_hide(bg_gtk_log_window_t * win) { gtk_widget_hide(win->window); win->visible = 0; } /* Configuration stuff */ static const bg_parameter_info_t parameters[] = { { .name = "max_messages", .long_name = TRS("Number of messages"), .type = BG_PARAMETER_INT, .val_default = { .val_i = 20 }, .help_string = TRS("Maximum number of messages hold in the window") }, { .name = "show_info", .long_name = TRS("Show info messages"), .type = BG_PARAMETER_CHECKBUTTON, .val_default = { .val_i = 1 } }, { .name = "show_warning", .long_name = TRS("Show warning messages"), .type = BG_PARAMETER_CHECKBUTTON, .val_default = { .val_i = 1 } }, { .name = "show_error", .long_name = TRS("Show error messages"), .type = BG_PARAMETER_CHECKBUTTON, .val_default = { .val_i = 1 } }, { .name = "show_debug", .long_name = TRS("Show debug messages"), .type = BG_PARAMETER_CHECKBUTTON, .val_default = { .val_i = 0 } }, { .name = "info_color", .long_name = TRS("Info foreground"), .type = BG_PARAMETER_COLOR_RGB, .val_default = { .val_color = { 0.0, 0.0, 0.0 } }, .help_string = TRS("Color for info messages"), }, { .name = "warning_color", .long_name = TRS("Warning foreground"), .type = BG_PARAMETER_COLOR_RGB, .val_default = { .val_color = { 1.0, 0.5, 0.0 } }, .help_string = TRS("Color for warning messages"), }, { .name = "error_color", .long_name = TRS("Error foreground"), .type = BG_PARAMETER_COLOR_RGB, .val_default = { .val_color = { 1.0, 0.0, 0.0 } }, .help_string = TRS("Color for error messages"), }, { .name = "debug_color", .long_name = TRS("Debug foreground"), .type = BG_PARAMETER_COLOR_RGB, .val_default = { .val_color = { 0.0, 0.0, 1.0 } }, .help_string = TRS("Color for debug messages"), }, { .name = "x", .long_name = "X", .flags = BG_PARAMETER_HIDE_DIALOG, .type = BG_PARAMETER_INT, .val_default = { .val_i = 100 } }, { .name = "y", .long_name = "Y", .flags = BG_PARAMETER_HIDE_DIALOG, .type = BG_PARAMETER_INT, .val_default = { .val_i = 100 } }, { .name = "width", .long_name = "Width", .flags = BG_PARAMETER_HIDE_DIALOG, .type = BG_PARAMETER_INT, .val_default = { .val_i = 0 } }, { .name = "height", .long_name = "Height", .flags = BG_PARAMETER_HIDE_DIALOG, .type = BG_PARAMETER_INT, .val_default = { .val_i = 0 } }, { /* */ } }; const bg_parameter_info_t * bg_gtk_log_window_get_parameters(bg_gtk_log_window_t * w) { return parameters; } void bg_gtk_log_window_set_parameter(void * data, const char * name, const bg_parameter_value_t * v) { GdkColor color; bg_gtk_log_window_t * win; if(!name) return; win = (bg_gtk_log_window_t *)data; if(!strcmp(name, "max_messages")) { win->max_messages = v->val_i; while(win->num_messages > win->max_messages) delete_first_line(win); } else if(!strcmp(name, "show_info")) win->show_info = v->val_i; else if(!strcmp(name, "show_warning")) win->show_warning = v->val_i; else if(!strcmp(name, "show_error")) win->show_error = v->val_i; else if(!strcmp(name, "show_debug")) win->show_debug = v->val_i; else if(!strcmp(name, "info_color")) { color.red = (guint16)(v->val_color[0] * 65535.0); color.green = (guint16)(v->val_color[1] * 65535.0); color.blue = (guint16)(v->val_color[2] * 65535.0); g_object_set(win->info_tag, "foreground-gdk", &color, NULL); } else if(!strcmp(name, "warning_color")) { color.red = (guint16)(v->val_color[0] * 65535.0); color.green = (guint16)(v->val_color[1] * 65535.0); color.blue = (guint16)(v->val_color[2] * 65535.0); g_object_set(win->warning_tag, "foreground-gdk", &color, NULL); } else if(!strcmp(name, "error_color")) { color.red = (guint16)(v->val_color[0] * 65535.0); color.green = (guint16)(v->val_color[1] * 65535.0); color.blue = (guint16)(v->val_color[2] * 65535.0); g_object_set(win->error_tag, "foreground-gdk", &color, NULL); } else if(!strcmp(name, "debug_color")) { color.red = (guint16)(v->val_color[0] * 65535.0); color.green = (guint16)(v->val_color[1] * 65535.0); color.blue = (guint16)(v->val_color[2] * 65535.0); g_object_set(win->debug_tag, "foreground-gdk", &color, NULL); } if(!strcmp(name, "x")) { win->x = v->val_i; } else if(!strcmp(name, "y")) { win->y = v->val_i; } else if(!strcmp(name, "width")) { win->width = v->val_i; } else if(!strcmp(name, "height")) { win->height = v->val_i; } } int bg_gtk_log_window_get_parameter(void * data, const char * name, bg_parameter_value_t * val) { bg_gtk_log_window_t * win; win = (bg_gtk_log_window_t*)data; if(!name) return 1; if(!strcmp(name, "x")) { val->val_i = win->x; return 1; } else if(!strcmp(name, "y")) { val->val_i = win->y; return 1; } else if(!strcmp(name, "width")) { val->val_i = win->width; return 1; } else if(!strcmp(name, "height")) { val->val_i = win->height; return 1; } return 0; } void bg_gtk_log_window_flush(bg_gtk_log_window_t * win) { idle_callback(win); } const char * bg_gtk_log_window_last_error(bg_gtk_log_window_t * win) { return win->last_error; } gmerlin-1.2.0~dfsg/lib/gtk/cfg_string.c0000644000175000017500000000653411764363406017737 0ustar alessioalessio/***************************************************************** * gmerlin - a general purpose multimedia framework and applications * * Copyright (c) 2001 - 2011 Members of the Gmerlin project * gmerlin-general@lists.sourceforge.net * http://gmerlin.sourceforge.net * * 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 of the License, 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 this program. If not, see . * *****************************************************************/ #include #include #include "gtk_dialog.h" #include typedef struct { GtkWidget * entry; GtkWidget * label; } string_t; static void get_value(bg_gtk_widget_t * w) { string_t * priv; priv = (string_t*)(w->priv); if(!w->value.val_str || (*w->value.val_str == '\0')) { gtk_entry_set_text(GTK_ENTRY(priv->entry), ""); return; } gtk_entry_set_text(GTK_ENTRY(priv->entry), w->value.val_str); } static void set_value(bg_gtk_widget_t * w) { string_t * priv; const char * str; priv = (string_t*)(w->priv); str = gtk_entry_get_text(GTK_ENTRY(priv->entry)); if(w->value.val_str) { free(w->value.val_str); w->value.val_str = NULL; } if(*str != '\0') { w->value.val_str = malloc(strlen(str)+1); strcpy(w->value.val_str, str); } } static void destroy(bg_gtk_widget_t * w) { string_t * priv = (string_t*)(w->priv); free(priv); } static void attach(void * priv, GtkWidget * table, int * row, int * num_columns) { string_t * b = (string_t*)priv; if(*num_columns < 2) *num_columns = 2; gtk_table_resize(GTK_TABLE(table), *row+1, *num_columns); // gtk_table_attach_defaults(GTK_TABLE(table), b->button, // 0, 1, *row, *row+1); gtk_table_attach(GTK_TABLE(table), b->label, 0, 1, *row, *row+1, GTK_FILL, GTK_SHRINK, 0, 0); gtk_table_attach(GTK_TABLE(table), b->entry, 1, 2, *row, *row+1, GTK_FILL | GTK_EXPAND, GTK_SHRINK, 0, 0); (*row)++; } static const gtk_widget_funcs_t funcs = { .get_value = get_value, .set_value = set_value, .destroy = destroy, .attach = attach }; void bg_gtk_create_string(bg_gtk_widget_t * w, const char * translation_domain) { string_t * priv = calloc(1, sizeof(*priv)); priv->entry = gtk_entry_new(); if(w->info->help_string) { bg_gtk_tooltips_set_tip(priv->entry, w->info->help_string, translation_domain); } if(w->info->type == BG_PARAMETER_STRING_HIDDEN) gtk_entry_set_visibility(GTK_ENTRY(priv->entry), FALSE); gtk_widget_show(priv->entry); priv->label = gtk_label_new(TR_DOM(w->info->long_name)); gtk_misc_set_alignment(GTK_MISC(priv->label), 0.0, 0.5); gtk_widget_show(priv->label); w->funcs = &funcs; w->priv = priv; } gmerlin-1.2.0~dfsg/lib/gtk/auth.c0000644000175000017500000001304111764363406016542 0ustar alessioalessio/***************************************************************** * gmerlin - a general purpose multimedia framework and applications * * Copyright (c) 2001 - 2011 Members of the Gmerlin project * gmerlin-general@lists.sourceforge.net * http://gmerlin.sourceforge.net * * 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 of the License, 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 this program. If not, see . * *****************************************************************/ #include #include #include #include #include #include typedef struct { GtkWidget * window; GtkWidget * user; GtkWidget * pass; GtkWidget * save_auth; GtkWidget * ok_button; GtkWidget * cancel_button; int ok_clicked; } userpass_win; static void button_callback(GtkWidget * w, gpointer data) { userpass_win * win = (userpass_win *)data; if(w == win->ok_button) win->ok_clicked = 1; gtk_widget_hide(win->window); gtk_main_quit(); } static gboolean delete_callback(GtkWidget * w, GdkEventAny * event, gpointer data) { button_callback(w, data); return TRUE; } static userpass_win * userpass_win_create(const char * resource) { GtkWidget * w; GtkWidget * table; GtkWidget * box; GtkWidget * mainbox; userpass_win * ret; ret = calloc(1, sizeof(*ret)); /* Create window */ ret->window = bg_gtk_window_new(GTK_WINDOW_TOPLEVEL); gtk_window_set_title(GTK_WINDOW(ret->window), TR("Authentication")); gtk_window_set_modal(GTK_WINDOW(ret->window), 1); gtk_window_set_position(GTK_WINDOW(ret->window), GTK_WIN_POS_CENTER); gtk_container_set_border_width(GTK_CONTAINER(ret->window), 5); /* Create OK/Cancel */ ret->ok_button = gtk_button_new_from_stock(GTK_STOCK_OK); ret->cancel_button = gtk_button_new_from_stock(GTK_STOCK_CANCEL); bg_gtk_widget_set_can_default(ret->ok_button, TRUE); bg_gtk_widget_set_can_default(ret->cancel_button, TRUE); g_signal_connect(G_OBJECT(ret->ok_button), "clicked", G_CALLBACK(button_callback), ret); g_signal_connect(G_OBJECT(ret->cancel_button), "clicked", G_CALLBACK(button_callback), ret); g_signal_connect(G_OBJECT(ret->window), "delete-event", G_CALLBACK(delete_callback), ret); gtk_widget_show(ret->ok_button); gtk_widget_show(ret->cancel_button); ret->user = gtk_entry_new(); ret->pass = gtk_entry_new(); gtk_entry_set_visibility(GTK_ENTRY(ret->pass), FALSE); gtk_widget_show(ret->user); gtk_widget_show(ret->pass); ret->save_auth = gtk_check_button_new_with_label(TR("Save user/password (can be dangerous!)")); gtk_widget_show(ret->save_auth); /* Pack everything */ mainbox = gtk_vbox_new(0, 5); table = gtk_table_new(5, 3, 0); gtk_table_set_row_spacings(GTK_TABLE(table), 5); gtk_table_set_col_spacings(GTK_TABLE(table), 5); w = gtk_label_new(TR("Enter username and password for")); gtk_widget_show(w); gtk_table_attach(GTK_TABLE(table), w, 0, 3, 0, 1, GTK_FILL, GTK_FILL, 0, 0); w = gtk_label_new(resource); gtk_widget_show(w); gtk_table_attach(GTK_TABLE(table), w, 0, 3, 1, 2, GTK_FILL, GTK_FILL, 0, 0); #ifdef GTK_STOCK_DIALOG_AUTHENTICATION w = gtk_image_new_from_stock(GTK_STOCK_DIALOG_AUTHENTICATION, GTK_ICON_SIZE_DIALOG); gtk_widget_show(w); gtk_table_attach(GTK_TABLE(table), w, 0, 1, 2, 5, GTK_FILL, GTK_FILL, 0, 0); #endif w = gtk_label_new(TR("Username")); gtk_widget_show(w); gtk_table_attach(GTK_TABLE(table), w, 1, 2, 2, 3, GTK_FILL, GTK_FILL, 0, 0); gtk_table_attach_defaults(GTK_TABLE(table), ret->user, 2, 3, 2, 3); w = gtk_label_new(TR("Password")); gtk_widget_show(w); gtk_table_attach(GTK_TABLE(table), w, 1, 2, 3, 4, GTK_FILL, GTK_FILL, 0, 0); gtk_table_attach_defaults(GTK_TABLE(table), ret->pass, 2, 3, 3, 4); gtk_table_attach_defaults(GTK_TABLE(table), ret->save_auth, 1, 3, 4, 5); gtk_widget_show(table); bg_gtk_box_pack_start_defaults(GTK_BOX(mainbox), table); box = gtk_hbutton_box_new(); gtk_box_set_spacing(GTK_BOX(box), 5); gtk_container_add(GTK_CONTAINER(box), ret->cancel_button); gtk_container_add(GTK_CONTAINER(box), ret->ok_button); gtk_widget_show(box); gtk_box_pack_start(GTK_BOX(mainbox), box, FALSE, FALSE, 0); gtk_widget_show(mainbox); gtk_container_add(GTK_CONTAINER(ret->window), mainbox); return ret; } int bg_gtk_get_userpass(const char * resource, char ** user, char ** pass, int * save_password, void * data) { int ret = 0; userpass_win * win = userpass_win_create(resource); gtk_widget_show(win->window); gtk_main(); if(win->ok_clicked) { *user = bg_strdup(*user, gtk_entry_get_text(GTK_ENTRY(win->user))); *pass = bg_strdup(*pass, gtk_entry_get_text(GTK_ENTRY(win->pass))); *save_password = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(win->save_auth)); ret = 1; } gtk_widget_destroy(win->window); free(win); return ret; } gmerlin-1.2.0~dfsg/lib/gtk/fileselect.c0000644000175000017500000003704211764363406017727 0ustar alessioalessio/***************************************************************** * gmerlin - a general purpose multimedia framework and applications * * Copyright (c) 2001 - 2011 Members of the Gmerlin project * gmerlin-general@lists.sourceforge.net * http://gmerlin.sourceforge.net * * 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 of the License, 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 this program. If not, see . * *****************************************************************/ #include #include #include #include #include #include #include #include #include #include #include #include #include #include struct bg_gtk_filesel_s { GtkWidget * filesel; GtkWidget * plugin_menu; bg_gtk_plugin_menu_t * plugins; void (*add_files)(char ** files, const char * plugin, int prefer_edl, void * data); void (*add_dir)(char * dir, int recursive, int subdirs_as_subalbums, int watch, const char * plugin, int prefer_edl, void * data); void (*close_notify)(bg_gtk_filesel_t * f, void * data); void * callback_data; char * cwd; int is_modal; int unsensitive; GtkWidget * recursive; GtkWidget * subdirs_as_subalbums; GtkWidget * watch; GtkWidget * prefer_edl; }; static void add_files(bg_gtk_filesel_t * f) { char ** filenames; GSList * file_list; GSList * tmp; const char * plugin = NULL; int num, i; if(f->plugins) plugin = bg_gtk_plugin_menu_get_plugin(f->plugins); file_list = gtk_file_chooser_get_filenames(GTK_FILE_CHOOSER(f->filesel)); num = g_slist_length(file_list); filenames = calloc(num+1, sizeof(*filenames)); tmp = file_list; for(i = 0; i < num; i++) { filenames[i] = (char*)tmp->data; tmp = tmp->next; } f->unsensitive = 1; gtk_widget_set_sensitive(f->filesel, 0); f->add_files(filenames, plugin, gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(f->prefer_edl)), f->callback_data); gtk_widget_set_sensitive(f->filesel, 1); f->unsensitive = 0; g_slist_foreach(file_list, (GFunc)g_free, NULL); g_slist_free(file_list); free(filenames); } static void add_dir(bg_gtk_filesel_t * f) { const char * plugin = NULL; char * tmp = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(f->filesel)); if(f->plugins) plugin = bg_gtk_plugin_menu_get_plugin(f->plugins); f->unsensitive = 1; gtk_widget_set_sensitive(f->filesel, 0); f->add_dir(tmp, gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(f->recursive)), gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(f->subdirs_as_subalbums)), gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(f->watch)), plugin, gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(f->prefer_edl)), f->callback_data); gtk_widget_set_sensitive(f->filesel, 1); f->unsensitive = 0; g_free(tmp); } static void fileselect_callback(GtkWidget *chooser, gint response_id, gpointer data) { bg_gtk_filesel_t * f; f = (bg_gtk_filesel_t *)data; if(f->unsensitive) return; if(response_id == GTK_RESPONSE_OK) { if(f->add_files) add_files(f); else if(f->add_dir) add_dir(f); } else { gtk_widget_hide(f->filesel); if(f->is_modal) gtk_main_quit(); if(f->close_notify) f->close_notify(f, f->callback_data); bg_gtk_filesel_destroy(f); } } #if 0 static gboolean delete_callback(GtkWidget * w, GdkEventAny * event, gpointer data) { fileselect_callback(w, GTK_RESPONSE_CANCEL, data); return TRUE; } static gboolean destroy_callback(GtkWidget * w, GdkEvent * event, gpointer data) { fileselect_callback(w, GTK_RESPONSE_CANCEL, data); return TRUE; } #endif static bg_gtk_filesel_t * filesel_create(const char * title, void (*add_files)(char ** files, const char * plugin, int prefer_edl, void * data), void (*add_dir)(char * dir, int recursive, int subdirs_as_subalbums, int watch, const char * plugin, int prefer_edl, void * data), void (*close_notify)(bg_gtk_filesel_t *, void * data), void * user_data, GtkWidget * parent_window, bg_plugin_registry_t * plugin_reg, int type_mask, int flag_mask) { bg_gtk_filesel_t * ret; GtkWidget * extra = NULL; ret = calloc(1, sizeof(*ret)); parent_window = bg_gtk_get_toplevel(parent_window); /* Create fileselection */ if(add_files) { ret->filesel = gtk_file_chooser_dialog_new(title, GTK_WINDOW(parent_window), GTK_FILE_CHOOSER_ACTION_OPEN, GTK_STOCK_CLOSE, GTK_RESPONSE_CANCEL, GTK_STOCK_ADD, GTK_RESPONSE_OK, NULL); gtk_file_chooser_set_select_multiple(GTK_FILE_CHOOSER(ret->filesel), TRUE); } else if(add_dir) { ret->filesel = gtk_file_chooser_dialog_new(title, GTK_WINDOW(parent_window), GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER, GTK_STOCK_CLOSE, GTK_RESPONSE_CANCEL, GTK_STOCK_ADD, GTK_RESPONSE_OK, NULL); extra = gtk_vbox_new(FALSE, 5); ret->recursive = gtk_check_button_new_with_label(TR("Recursive")); gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(ret->recursive), 1); gtk_widget_show(ret->recursive); bg_gtk_box_pack_start_defaults(GTK_BOX(extra), ret->recursive); ret->subdirs_as_subalbums = gtk_check_button_new_with_label(TR("Add subdirectories as subalbums")); gtk_widget_show(ret->subdirs_as_subalbums); gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(ret->subdirs_as_subalbums), 1); ret->watch = gtk_check_button_new_with_label(TR("Watch directories")); gtk_widget_show(ret->watch); bg_gtk_box_pack_start_defaults(GTK_BOX(extra), ret->subdirs_as_subalbums); bg_gtk_box_pack_start_defaults(GTK_BOX(extra), ret->watch); } gtk_window_set_default_size(GTK_WINDOW(ret->filesel), 400, 400); /* Create plugin menu */ if(plugin_reg) { if(!extra) extra = gtk_vbox_new(FALSE, 5); ret->plugins = bg_gtk_plugin_menu_create(1, plugin_reg, type_mask, flag_mask); bg_gtk_box_pack_start_defaults(GTK_BOX(extra), bg_gtk_plugin_menu_get_widget(ret->plugins)); ret->prefer_edl = gtk_check_button_new_with_label(TR("Prefer EDL")); gtk_widget_show(ret->prefer_edl); bg_gtk_box_pack_start_defaults(GTK_BOX(extra), ret->prefer_edl); } if(extra) { gtk_widget_show(extra); gtk_file_chooser_set_extra_widget(GTK_FILE_CHOOSER(ret->filesel), extra); } /* Set callbacks */ #if 0 g_signal_connect(G_OBJECT(ret->filesel), "delete_event", G_CALLBACK(delete_callback), ret); #endif g_signal_connect(ret->filesel, "response", G_CALLBACK(fileselect_callback), (gpointer)ret); ret->add_files = add_files; ret->add_dir = add_dir; ret->close_notify = close_notify; ret->callback_data = user_data; return ret; } bg_gtk_filesel_t * bg_gtk_filesel_create(const char * title, void (*add_file)(char ** files, const char * plugin, int prefer_edl, void * data), void (*close_notify)(bg_gtk_filesel_t *, void * data), void * user_data, GtkWidget * parent_window, bg_plugin_registry_t * plugin_reg, int type_mask, int flag_mask) { return filesel_create(title, add_file, NULL, close_notify, user_data, parent_window, plugin_reg, type_mask, flag_mask); } bg_gtk_filesel_t * bg_gtk_dirsel_create(const char * title, void (*add_dir)(char * dir, int recursive, int subdirs_as_subalbums, int watch, const char * plugin, int prefer_edl, void * data), void (*close_notify)(bg_gtk_filesel_t *, void * data), void * user_data, GtkWidget * parent_window, bg_plugin_registry_t * plugin_reg, int type_mask, int flag_mask) { return filesel_create(title, NULL, add_dir, close_notify, user_data, parent_window, plugin_reg, type_mask, flag_mask); } /* Destroy fileselector */ void bg_gtk_filesel_destroy(bg_gtk_filesel_t * filesel) { if(filesel->cwd) g_free(filesel->cwd); // g_object_unref(G_OBJECT(filesel)); free(filesel); } /* Show the window */ void bg_gtk_filesel_run(bg_gtk_filesel_t * filesel, int modal) { gtk_window_set_modal(GTK_WINDOW(filesel->filesel), modal); gtk_widget_show(filesel->filesel); filesel->is_modal = modal; if(modal) gtk_main(); } /* Get the current working directory */ void bg_gtk_filesel_set_directory(bg_gtk_filesel_t * filesel, const char * dir) { gtk_file_chooser_set_current_folder(GTK_FILE_CHOOSER(filesel->filesel), dir); } const char * bg_gtk_filesel_get_directory(bg_gtk_filesel_t * filesel) { if(filesel->cwd) g_free(filesel->cwd); filesel->cwd = gtk_file_chooser_get_current_folder(GTK_FILE_CHOOSER(filesel->filesel)); return filesel->cwd; } /* * Create a temporary fileselector and ask * for a file to save something * * Return value should be freed with free(); */ typedef struct { GtkWidget * w; int answer; } filesel_write_struct; static void write_callback(GtkWidget *chooser, gint response_id, gpointer data) { filesel_write_struct * ws; ws = (filesel_write_struct*)data; if(response_id == GTK_RESPONSE_OK) ws->answer = 1; gtk_widget_hide(ws->w); gtk_main_quit(); } static gboolean write_delete_callback(GtkWidget * w, GdkEventAny * evt, gpointer data) { write_callback(w, GTK_RESPONSE_CANCEL, data); return TRUE; } char * bg_gtk_get_filename_write(const char * title, char ** directory, int ask_overwrite, GtkWidget * parent) { char * ret; char * tmp_string; filesel_write_struct f; ret = NULL; parent = bg_gtk_get_toplevel(parent); f.w = gtk_file_chooser_dialog_new(title, GTK_WINDOW(parent), GTK_FILE_CHOOSER_ACTION_SAVE, GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, GTK_STOCK_OK, GTK_RESPONSE_OK, NULL); if(ask_overwrite) gtk_file_chooser_set_do_overwrite_confirmation(GTK_FILE_CHOOSER(f.w), TRUE); /* Set attributes */ gtk_window_set_modal(GTK_WINDOW(f.w), 1); f.answer = 0; /* Set callbacks */ g_signal_connect(G_OBJECT(f.w), "delete_event", G_CALLBACK(write_delete_callback), (gpointer)(&f)); g_signal_connect(G_OBJECT(f.w), "response", G_CALLBACK(write_callback), (gpointer)(&f)); /* Set the current directory */ if(directory && *directory) gtk_file_chooser_set_current_folder(GTK_FILE_CHOOSER(f.w), *directory); /* Run the widget */ gtk_widget_show(f.w); gtk_main(); /* Fetch the answer */ if(!f.answer) { gtk_widget_destroy(f.w); return NULL; } tmp_string = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(f.w)); ret = bg_strdup(NULL, tmp_string); g_free(tmp_string); /* Update current directory */ if(directory) { tmp_string = gtk_file_chooser_get_current_folder(GTK_FILE_CHOOSER(f.w)); *directory = bg_strdup(*directory, tmp_string); g_free(tmp_string); } return ret; } char * bg_gtk_get_filename_read(const char * title, char ** directory, GtkWidget * parent) { char * ret; char * tmp_string; filesel_write_struct f; ret = NULL; parent = bg_gtk_get_toplevel(parent); f.w = gtk_file_chooser_dialog_new(title, GTK_WINDOW(parent), GTK_FILE_CHOOSER_ACTION_OPEN, GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, GTK_STOCK_OK, GTK_RESPONSE_OK, NULL); /* Set attributes */ gtk_window_set_modal(GTK_WINDOW(f.w), 1); f.answer = 0; /* Set callbacks */ g_signal_connect(G_OBJECT(f.w), "delete_event", G_CALLBACK(write_delete_callback), (gpointer)(&f)); g_signal_connect(G_OBJECT(f.w), "response", G_CALLBACK(write_callback), (gpointer)(&f)); /* Set the current directory */ if(directory && *directory) gtk_file_chooser_set_current_folder(GTK_FILE_CHOOSER(f.w), *directory); /* Run the widget */ gtk_widget_show(f.w); gtk_main(); /* Fetch the answer */ if(!f.answer) { gtk_widget_destroy(f.w); return NULL; } tmp_string = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(f.w)); ret = bg_strdup(NULL, tmp_string); g_free(tmp_string); /* Update current directory */ if(directory) { tmp_string = gtk_file_chooser_get_current_folder(GTK_FILE_CHOOSER(f.w)); *directory = bg_strdup(*directory, tmp_string); g_free(tmp_string); } return ret; } gmerlin-1.2.0~dfsg/lib/gtk/pluginmenu.c0000644000175000017500000001215311764363406017767 0ustar alessioalessio/***************************************************************** * gmerlin - a general purpose multimedia framework and applications * * Copyright (c) 2001 - 2011 Members of the Gmerlin project * gmerlin-general@lists.sourceforge.net * http://gmerlin.sourceforge.net * * 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 of the License, 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 this program. If not, see . * *****************************************************************/ #include #include #include #include #include #include #include #include #include static char const * const auto_string = TRS("Auto Select"); struct bg_gtk_plugin_menu_s { int auto_supported; GtkWidget * combo; GtkWidget * label; bg_plugin_registry_t * plugin_reg; int type_mask; int flag_mask; void (*callback)(bg_gtk_plugin_menu_t*, void*); void * callback_data; }; static void change_callback(GtkWidget * w, gpointer data) { bg_gtk_plugin_menu_t * m; m = (bg_gtk_plugin_menu_t*)data; if(m->callback) m->callback(m, m->callback_data); } bg_gtk_plugin_menu_t * bg_gtk_plugin_menu_create(int auto_supported, bg_plugin_registry_t * plugin_reg, int type_mask, int flag_mask) { int num, i; bg_gtk_plugin_menu_t * ret; const bg_plugin_info_t * plugin_info; ret = calloc(1, sizeof(*ret)); ret->auto_supported = auto_supported; ret->combo = bg_gtk_combo_box_new_text(); g_signal_connect(G_OBJECT(ret->combo), "changed", G_CALLBACK(change_callback), (gpointer)ret); if(auto_supported) bg_gtk_combo_box_append_text(ret->combo, TR(auto_string)); ret->plugin_reg = plugin_reg; ret->type_mask = type_mask; ret->flag_mask = flag_mask; num = bg_plugin_registry_get_num_plugins(ret->plugin_reg, ret->type_mask, ret->flag_mask); for(i = 0; i < num; i++) { plugin_info = bg_plugin_find_by_index(ret->plugin_reg, i, ret->type_mask, ret->flag_mask); bg_bindtextdomain(plugin_info->gettext_domain, plugin_info->gettext_directory); bg_gtk_combo_box_append_text(ret->combo, TRD(plugin_info->long_name, plugin_info->gettext_domain)); } /* We always take the 0th option */ gtk_combo_box_set_active(GTK_COMBO_BOX(ret->combo), 0); gtk_widget_show(ret->combo); ret->label = gtk_label_new(TR("Plugin: ")); gtk_widget_show(ret->label); gtk_widget_show(ret->combo); return ret; } const char * bg_gtk_plugin_menu_get_plugin(bg_gtk_plugin_menu_t * m) { int selected; const bg_plugin_info_t * plugin_info; selected = gtk_combo_box_get_active(GTK_COMBO_BOX(m->combo)); if(m->auto_supported) { if(!selected) return NULL; else { plugin_info = bg_plugin_find_by_index(m->plugin_reg, selected-1, m->type_mask, m->flag_mask); return plugin_info->name; } } else { plugin_info = bg_plugin_find_by_index(m->plugin_reg, selected, m->type_mask, m->flag_mask); return plugin_info->name; } } GtkWidget * bg_gtk_plugin_menu_get_widget(bg_gtk_plugin_menu_t * m) { GtkWidget * ret; ret = gtk_hbox_new(0, 5); gtk_box_pack_start(GTK_BOX(ret), m->label, FALSE, FALSE, 0); bg_gtk_box_pack_start_defaults(GTK_BOX(ret), m->combo); gtk_widget_show(ret); return ret; } void bg_gtk_plugin_menu_attach(bg_gtk_plugin_menu_t * m, GtkWidget * table, int row, int column) { gtk_table_attach(GTK_TABLE(table), m->label, column, column+1, row, row+1, GTK_FILL, GTK_SHRINK, 0, 0); gtk_table_attach(GTK_TABLE(table), m->combo, column+1, column+2, row, row+1, GTK_FILL | GTK_EXPAND, GTK_SHRINK, 0, 0); } void bg_gtk_plugin_menu_destroy(bg_gtk_plugin_menu_t * m) { } void bg_gtk_plugin_menu_set_change_callback(bg_gtk_plugin_menu_t * m, void (*callback)(bg_gtk_plugin_menu_t*, void*), void * callback_data) { m->callback = callback; m->callback_data = callback_data; } gmerlin-1.2.0~dfsg/lib/gtk/cfg_button.c0000644000175000017500000000475111764363406017743 0ustar alessioalessio/***************************************************************** * gmerlin - a general purpose multimedia framework and applications * * Copyright (c) 2001 - 2011 Members of the Gmerlin project * gmerlin-general@lists.sourceforge.net * http://gmerlin.sourceforge.net * * 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 of the License, 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 this program. If not, see . * *****************************************************************/ #include #include "gtk_dialog.h" #include typedef struct { GtkWidget * button; } button_t; static void destroy(bg_gtk_widget_t * w) { button_t * priv = (button_t *)w->priv; free(priv); } static void attach(void * priv, GtkWidget * table, int * row, int * num_columns) { button_t * b = (button_t*)priv; if(*num_columns < 2) *num_columns = 2; gtk_table_resize(GTK_TABLE(table), *row+1, *num_columns); gtk_table_attach(GTK_TABLE(table), b->button, 0, 2, *row, *row+1, GTK_FILL | GTK_EXPAND, GTK_FILL, 0, 0); (*row)++; } static const gtk_widget_funcs_t funcs = { .destroy = destroy, .attach = attach }; static void callback(GtkWidget * w, gpointer data) { bg_gtk_widget_t * wid = data; if(wid->change_callback) wid->change_callback(wid->change_callback_data, wid->info->name, NULL); } void bg_gtk_create_button(bg_gtk_widget_t * w, const char * translation_domain) { button_t * priv = calloc(1, sizeof(*priv)); priv->button = gtk_button_new_with_label(TR_DOM(w->info->long_name)); g_signal_connect(G_OBJECT(priv->button), "clicked", G_CALLBACK(callback), (gpointer)w); if(w->info->help_string) { bg_gtk_tooltips_set_tip(priv->button, w->info->help_string, translation_domain); } gtk_widget_show(priv->button); w->funcs = &funcs; w->priv = priv; } gmerlin-1.2.0~dfsg/lib/gtk/infowindow.c0000644000175000017500000010045611764363406017773 0ustar alessioalessio/***************************************************************** * gmerlin - a general purpose multimedia framework and applications * * Copyright (c) 2001 - 2011 Members of the Gmerlin project * gmerlin-general@lists.sourceforge.net * http://gmerlin.sourceforge.net * * 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 of the License, 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 this program. If not, see . * *****************************************************************/ #include #include #include #include #include #include #include #include //#include #include #include #include //#include #include #include /* This is missing in the gtk headers */ #define FG_SENSITIVE "#000000" #define FG_INSENSITIVE "#808080" extern void gtk_decorated_window_move_resize_window(GtkWindow*, int, int, int, int); enum { COLUMN_1, COLUMN_2, COLUMN_FG_COLOR, NUM_COLUMNS }; #define PATH_NAME 0 #define PATH_INPUT_PLUGIN 1 #define PATH_LOCATION 2 #define PATH_TRACK 3 #define PATH_METADATA 4 #define PATH_AUDIO 5 #define PATH_AUDIO_DESC 6 #define PATH_AUDIO_FORMAT_I 7 #define PATH_AUDIO_FORMAT_O 8 #define PATH_VIDEO 9 #define PATH_VIDEO_DESC 10 #define PATH_VIDEO_FORMAT_I 11 #define PATH_VIDEO_FORMAT_O 12 #define PATH_SUBTITLE 13 #define PATH_SUBTITLE_DESC 14 #define PATH_SUBTITLE_FORMAT_I 15 #define PATH_SUBTITLE_FORMAT_O 16 #define PATH_NUM 17 /* Delay between update calls in Milliseconds */ #define DELAY_TIME 50 struct bg_gtk_info_window_s { int x, y, width, height; /* We store everything interesting locally */ int num_audio_streams; int num_video_streams; int num_subtitle_streams; GtkWidget * window; GtkWidget * treeview; bg_msg_queue_t * queue; void (*close_callback)(bg_gtk_info_window_t*, void*); void * close_callback_data; GtkTreePath * paths[PATH_NUM]; int expanded[PATH_NUM]; guint expand_id; guint collapse_id; /* Clipboard */ char * clipboard; int clipboard_len; struct { GtkWidget * copy_all; GtkWidget * copy_selected; GtkWidget * menu; } menu; guint idle_id; }; static void reset_tree(bg_gtk_info_window_t * w); #define EXPANDED_PARAM(n) \ { \ .name = n, \ .long_name = n,\ .type = BG_PARAMETER_CHECKBUTTON, \ .flags = BG_PARAMETER_HIDE_DIALOG, \ } static const bg_parameter_info_t parameters[] = { { .name = "x", .long_name = "X", .flags = BG_PARAMETER_HIDE_DIALOG, .type = BG_PARAMETER_INT, .val_default = { .val_i = 100 } }, { .name = "y", .long_name = "Y", .flags = BG_PARAMETER_HIDE_DIALOG, .type = BG_PARAMETER_INT, .val_default = { .val_i = 100 } }, { .name = "width", .long_name = "Width", .flags = BG_PARAMETER_HIDE_DIALOG, .type = BG_PARAMETER_INT, .val_default = { .val_i = 0 } }, { .name = "height", .long_name = "Height", .flags = BG_PARAMETER_HIDE_DIALOG, .type = BG_PARAMETER_INT, .val_default = { .val_i = 0 } }, EXPANDED_PARAM("exp_0"), EXPANDED_PARAM("exp_1"), EXPANDED_PARAM("exp_2"), EXPANDED_PARAM("exp_3"), EXPANDED_PARAM("exp_4"), EXPANDED_PARAM("exp_5"), EXPANDED_PARAM("exp_6"), EXPANDED_PARAM("exp_7"), EXPANDED_PARAM("exp_8"), EXPANDED_PARAM("exp_9"), EXPANDED_PARAM("exp_10"), EXPANDED_PARAM("exp_11"), EXPANDED_PARAM("exp_12"), EXPANDED_PARAM("exp_13"), EXPANDED_PARAM("exp_14"), EXPANDED_PARAM("exp_15"), EXPANDED_PARAM("exp_16"), EXPANDED_PARAM("exp_17"), { /* End of parameters */ } }; const bg_parameter_info_t * bg_gtk_info_window_get_parameters(bg_gtk_info_window_t * win) { return parameters; } void bg_gtk_info_window_set_parameter(void * data, const char * name, const bg_parameter_value_t * val) { int index; bg_gtk_info_window_t * win; GtkTreeModel * model; GtkTreeIter iter; win = (bg_gtk_info_window_t*)data; if(!name) return; if(!strcmp(name, "x")) { win->x = val->val_i; } else if(!strcmp(name, "y")) { win->y = val->val_i; } else if(!strcmp(name, "width")) { win->width = val->val_i; } else if(!strcmp(name, "height")) { win->height = val->val_i; } else if(! strncmp(name, "exp_", 4)) { index = atoi(name+4); win->expanded[index] = val->val_i; if(win->expanded[index] && win->paths[index]) { model = gtk_tree_view_get_model(GTK_TREE_VIEW(win->treeview)); gtk_tree_model_get_iter(model, &iter, win->paths[index]); gtk_tree_view_expand_row(GTK_TREE_VIEW(win->treeview), win->paths[index], 0); } } } int bg_gtk_info_window_get_parameter(void * data, const char * name, bg_parameter_value_t * val) { bg_gtk_info_window_t * win; int index; win = (bg_gtk_info_window_t*)data; if(!name) return 1; if(!strcmp(name, "x")) { val->val_i = win->x; return 1; } else if(!strcmp(name, "y")) { val->val_i = win->y; return 1; } else if(!strcmp(name, "width")) { val->val_i = win->width; return 1; } else if(!strcmp(name, "height")) { val->val_i = win->height; return 1; } else if(! strncmp(name, "exp_", 4)) { index = atoi(name+4); val->val_i = win->expanded[index]; return 1; } return 0; } static char * iter_to_string(bg_gtk_info_window_t * w, char * ret, int depth, GtkTreeIter * iter, int append_children) { int i; int num_children; GtkTreeModel * model; char * str; GtkTreeIter child; /* */ model = gtk_tree_view_get_model(GTK_TREE_VIEW(w->treeview)); if(iter) { /* Check if the entry is present at all */ gtk_tree_model_get(model, iter, COLUMN_FG_COLOR, &str, -1); if(!strcmp(str, FG_INSENSITIVE)) { g_free(str); return ret; } g_free(str); /* * Ugly, that's right, but the code isn't meant to be run * for each video pixel :) */ for(i = 0; i < depth; i++) ret = bg_strcat(ret, " "); /* First column */ gtk_tree_model_get(model, iter, COLUMN_1, &str, -1); if(*str) ret = bg_strcat(ret, str); else { g_free(str); return ret; } g_free(str); /* Second column */ gtk_tree_model_get(model, iter, COLUMN_2, &str, -1); if(*str) { ret = bg_strcat(ret, "\t"); ret = bg_strcat(ret, str); } g_free(str); ret = bg_strcat(ret, "\n"); } if(!append_children) return ret; num_children = gtk_tree_model_iter_n_children(model, iter); if(!num_children) return ret; gtk_tree_model_iter_children(model, &child, iter); for(i = 0; i < num_children; i++) { ret = iter_to_string(w, ret, depth + !!(iter), &child, append_children); gtk_tree_model_iter_next(model, &child); } return ret; } static void set_line(bg_gtk_info_window_t * w, GtkTreeIter * iter, char * line, int sensitive) { char * pos; GtkTreeModel * model; model = gtk_tree_view_get_model(GTK_TREE_VIEW(w->treeview)); pos = strchr(line, '\t'); if(pos) { *pos = '\0'; pos++; } gtk_tree_store_set(GTK_TREE_STORE(model), iter, COLUMN_1, line, -1); if(pos) gtk_tree_store_set(GTK_TREE_STORE(model), iter, COLUMN_2, pos, -1); else gtk_tree_store_set(GTK_TREE_STORE(model), iter, COLUMN_2, "", -1); if(sensitive) gtk_tree_store_set(GTK_TREE_STORE(model), iter, COLUMN_FG_COLOR, FG_SENSITIVE, -1); else gtk_tree_store_set(GTK_TREE_STORE(model), iter, COLUMN_FG_COLOR, FG_INSENSITIVE, -1); } static void set_line_index(bg_gtk_info_window_t * w, int iter_index, char * line, int sensitive) { GtkTreeIter iter; GtkTreeModel * model; model = gtk_tree_view_get_model(GTK_TREE_VIEW(w->treeview)); gtk_tree_model_get_iter(model, &iter, w->paths[iter_index]); set_line(w, &iter, line, sensitive); } static void remove_children(bg_gtk_info_window_t * w, GtkTreeIter * parent) { GtkTreeModel * model; GtkTreeIter child; model = gtk_tree_view_get_model(GTK_TREE_VIEW(w->treeview)); while(gtk_tree_model_iter_children(GTK_TREE_MODEL(model), &child, parent)) { gtk_tree_store_remove(GTK_TREE_STORE(model), &child); } } static void set_line_multi(bg_gtk_info_window_t * w, int parent_index, char * line) { int i; GtkTreeIter parent; GtkTreeIter iter; GtkTreeModel * model; char ** tmp_strings; model = gtk_tree_view_get_model(GTK_TREE_VIEW(w->treeview)); gtk_tree_model_get_iter(model, &parent, w->paths[parent_index]); tmp_strings = bg_strbreak(line, '\n'); i = 0; gtk_tree_store_set(GTK_TREE_STORE(model), &parent, COLUMN_FG_COLOR, FG_SENSITIVE, -1); remove_children(w, &parent); while(tmp_strings[i]) { gtk_tree_store_append(GTK_TREE_STORE(model), &iter, &parent); set_line(w, &iter, tmp_strings[i], 1); i++; } if(w->expanded[parent_index]) gtk_tree_view_expand_row(GTK_TREE_VIEW(w->treeview), w->paths[parent_index], 0); if(tmp_strings) bg_strbreak_free(tmp_strings); } static void set_audio_format(bg_gtk_info_window_t * w, int parent_index, gavl_audio_format_t * format) { char * tmp_string; tmp_string = bg_audio_format_to_string(format, 1); set_line_multi(w, parent_index, tmp_string); free(tmp_string); } static void set_video_format(bg_gtk_info_window_t * w, int parent_index, gavl_video_format_t * format) { char * tmp_string; tmp_string = bg_video_format_to_string(format, 1); set_line_multi(w, parent_index, tmp_string); free(tmp_string); } static gboolean idle_callback(gpointer data) { int arg_i; int arg_i2; char * arg_str; char * tmp_string; gavl_audio_format_t arg_af; gavl_video_format_t arg_vf; gavl_metadata_t arg_m; bg_gtk_info_window_t * w; bg_msg_t * msg; w = (bg_gtk_info_window_t*)data; while((msg = bg_msg_queue_try_lock_read(w->queue))) { switch(bg_msg_get_id(msg)) { case BG_PLAYER_MSG_STATE_CHANGED: arg_i = bg_msg_get_arg_int(msg, 0); switch(arg_i) { case BG_PLAYER_STATE_STARTING: /* New info on the way, clean up everything */ reset_tree(w); break; case BG_PLAYER_STATE_PLAYING: /* All infos sent, update display */ // update_format(w); break; default: break; } break; case BG_PLAYER_MSG_TRACK_NAME: arg_str = bg_msg_get_arg_string(msg, 0); if(arg_str) { tmp_string = bg_sprintf(TR("Name:\t%s"), arg_str); set_line_index(w, PATH_NAME, tmp_string, 1); free(tmp_string); free(arg_str); } break; case BG_PLAYER_MSG_INPUT: arg_str = bg_msg_get_arg_string(msg, 0); if(arg_str) { tmp_string = bg_sprintf(TR("Input plugin:\t%s"), arg_str); set_line_index(w, PATH_INPUT_PLUGIN, tmp_string, 1); free(tmp_string); free(arg_str); } arg_str = bg_msg_get_arg_string(msg, 1); if(arg_str) { tmp_string = bg_sprintf(TR("Location:\t%s"), arg_str); set_line_index(w, PATH_LOCATION, tmp_string, 1); free(tmp_string); free(arg_str); } arg_i = bg_msg_get_arg_int(msg, 2); tmp_string = bg_sprintf(TR("Track:\t%d"), arg_i+1); set_line_index(w, PATH_TRACK, tmp_string, 1); free(tmp_string); break; case BG_PLAYER_MSG_TRACK_NUM_STREAMS: w->num_audio_streams = bg_msg_get_arg_int(msg, 0); w->num_video_streams = bg_msg_get_arg_int(msg, 1); w->num_subtitle_streams = bg_msg_get_arg_int(msg, 2); break; case BG_PLAYER_MSG_TRACK_DURATION: break; case BG_PLAYER_MSG_AUDIO_STREAM_INFO: gavl_metadata_init(&arg_m); bg_msg_get_arg_metadata(msg, 1, &arg_m); tmp_string = bg_metadata_to_string(&arg_m, 1); if(tmp_string) { set_line_multi(w, PATH_AUDIO_DESC, tmp_string); free(tmp_string); } gavl_metadata_free(&arg_m); break; case BG_PLAYER_MSG_SUBTITLE_STREAM_INFO: gavl_metadata_init(&arg_m); bg_msg_get_arg_metadata(msg, 1, &arg_m); tmp_string = bg_metadata_to_string(&arg_m, 1); if(tmp_string) { set_line_multi(w, PATH_SUBTITLE_DESC, tmp_string); free(tmp_string); } gavl_metadata_free(&arg_m); break; case BG_PLAYER_MSG_VIDEO_STREAM_INFO: gavl_metadata_init(&arg_m); bg_msg_get_arg_metadata(msg, 1, &arg_m); tmp_string = bg_metadata_to_string(&arg_m, 1); if(tmp_string) { set_line_multi(w, PATH_VIDEO_DESC, tmp_string); free(tmp_string); } gavl_metadata_free(&arg_m); break; case BG_PLAYER_MSG_AUDIO_STREAM: arg_i = bg_msg_get_arg_int(msg, 0); tmp_string = bg_sprintf(TR("Audio stream %d/%d"), arg_i + 1, w->num_audio_streams); set_line_index(w, PATH_AUDIO, tmp_string, 1); free(tmp_string); bg_msg_get_arg_audio_format(msg, 1, &arg_af, NULL); set_audio_format(w, PATH_AUDIO_FORMAT_I, &arg_af); bg_msg_get_arg_audio_format(msg, 2, &arg_af, NULL); set_audio_format(w, PATH_AUDIO_FORMAT_O, &arg_af); break; case BG_PLAYER_MSG_SUBTITLE_STREAM: arg_i = bg_msg_get_arg_int(msg, 0); arg_i2 = bg_msg_get_arg_int(msg, 1); tmp_string = bg_sprintf(TR("Subtitle stream %d/%d [%s]"), arg_i + 1, w->num_subtitle_streams, (arg_i2 ? "Text" : "Overlay")); set_line_index(w, PATH_SUBTITLE, tmp_string, 1); free(tmp_string); bg_msg_get_arg_video_format(msg, 2, &arg_vf, NULL); set_video_format(w, PATH_SUBTITLE_FORMAT_I, &arg_vf); bg_msg_get_arg_video_format(msg, 3, &arg_vf, NULL); set_video_format(w, PATH_SUBTITLE_FORMAT_O, &arg_vf); break; case BG_PLAYER_MSG_VIDEO_STREAM: arg_i = bg_msg_get_arg_int(msg, 0); tmp_string = bg_sprintf(TR("Video stream %d/%d"), arg_i + 1, w->num_video_streams); set_line_index(w, PATH_VIDEO, tmp_string, 1); free(tmp_string); bg_msg_get_arg_video_format(msg, 1, &arg_vf, NULL); set_video_format(w, PATH_VIDEO_FORMAT_I, &arg_vf); bg_msg_get_arg_video_format(msg, 2, &arg_vf, NULL); set_video_format(w, PATH_VIDEO_FORMAT_O, &arg_vf); break; case BG_PLAYER_MSG_METADATA: gavl_metadata_init(&arg_m); bg_msg_get_arg_metadata(msg, 0, &arg_m); tmp_string = bg_metadata_to_string(&arg_m, 1); if(tmp_string) { set_line_multi(w, PATH_METADATA, tmp_string); free(tmp_string); } gavl_metadata_free(&arg_m); break; } bg_msg_queue_unlock_read(w->queue); } return TRUE; } static gboolean delete_callback(GtkWidget * w, GdkEventAny * event, gpointer data) { bg_gtk_info_window_t * win; win = (bg_gtk_info_window_t*)data; if(win->close_callback) win->close_callback(win, win->close_callback_data); gtk_widget_hide(win->window); return TRUE; } static gboolean configure_callback(GtkWidget * w, GdkEventConfigure *event, gpointer data) { bg_gtk_info_window_t * win; win = (bg_gtk_info_window_t*)data; win->x = event->x; win->y = event->y; win->width = event->width; win->height = event->height; gdk_window_get_root_origin(win->window->window, &win->x, &win->y); return FALSE; } #define FREE(str) if(str) free(str);str=NULL; static void reset_tree(bg_gtk_info_window_t * w) { GtkTreeModel * model; GtkTreeIter iter; g_signal_handler_block(w->treeview, w->collapse_id); model = gtk_tree_view_get_model(GTK_TREE_VIEW(w->treeview)); /* Metadata */ gtk_tree_model_get_iter(model, &iter, w->paths[PATH_METADATA]); set_line(w, &iter, TR("Metadata"), 0); remove_children(w, &iter); /* Audio */ gtk_tree_model_get_iter(model, &iter, w->paths[PATH_AUDIO]); set_line(w, &iter, TR("Audio"), 0); /* Audio -> desc */ gtk_tree_model_get_iter(model, &iter, w->paths[PATH_AUDIO_DESC]); set_line(w, &iter, TR("Metadata"), 0); remove_children(w, &iter); /* Audio -> format_i */ gtk_tree_model_get_iter(model, &iter, w->paths[PATH_AUDIO_FORMAT_I]); set_line(w, &iter, TR("Input format"), 0); remove_children(w, &iter); /* Audio -> format_o */ gtk_tree_model_get_iter(model, &iter, w->paths[PATH_AUDIO_FORMAT_O]); set_line(w, &iter, TR("Output format"), 0); remove_children(w, &iter); /* Video */ gtk_tree_model_get_iter(model, &iter, w->paths[PATH_VIDEO]); set_line(w, &iter, TR("Video"), 0); /* Video -> desc */ gtk_tree_model_get_iter(model, &iter, w->paths[PATH_VIDEO_DESC]); set_line(w, &iter, TR("Metadata"), 0); remove_children(w, &iter); /* Video -> format_i */ gtk_tree_model_get_iter(model, &iter, w->paths[PATH_VIDEO_FORMAT_I]); set_line(w, &iter, TR("Input format"), 0); remove_children(w, &iter); /* Video -> format_o */ gtk_tree_model_get_iter(model, &iter, w->paths[PATH_VIDEO_FORMAT_O]); set_line(w, &iter, TR("Output format"), 0); remove_children(w, &iter); /* Subtitle */ gtk_tree_model_get_iter(model, &iter, w->paths[PATH_SUBTITLE]); set_line(w, &iter, TR("Subtitles"), 0); /* Subtitle -> desc */ gtk_tree_model_get_iter(model, &iter, w->paths[PATH_SUBTITLE_DESC]); set_line(w, &iter, TR("Metadata"), 0); remove_children(w, &iter); /* Subtitle -> format_i */ gtk_tree_model_get_iter(model, &iter, w->paths[PATH_SUBTITLE_FORMAT_I]); set_line(w, &iter, TR("Input format"), 0); remove_children(w, &iter); /* Subtitle -> format_o */ gtk_tree_model_get_iter(model, &iter, w->paths[PATH_SUBTITLE_FORMAT_O]); set_line(w, &iter, TR("Output format"), 0); remove_children(w, &iter); g_signal_handler_unblock(w->treeview, w->collapse_id); } static void init_tree(bg_gtk_info_window_t * w) { GtkTreeIter iter; GtkTreeIter child; GtkTreeModel * model; model = gtk_tree_view_get_model(GTK_TREE_VIEW(w->treeview)); /* Name */ gtk_tree_store_append(GTK_TREE_STORE(model), &iter, NULL); w->paths[PATH_NAME] = gtk_tree_model_get_path(model, &iter); set_line(w, &iter, TR("Name"), 0); /* Plugin */ gtk_tree_store_append(GTK_TREE_STORE(model), &iter, NULL); w->paths[PATH_INPUT_PLUGIN] = gtk_tree_model_get_path(model, &iter); set_line(w, &iter, TR("Input plugin"), 0); /* Location */ gtk_tree_store_append(GTK_TREE_STORE(model), &iter, NULL); w->paths[PATH_LOCATION] = gtk_tree_model_get_path(model, &iter); set_line(w, &iter, TR("Location"), 0); /* Track */ gtk_tree_store_append(GTK_TREE_STORE(model), &iter, NULL); w->paths[PATH_TRACK] = gtk_tree_model_get_path(model, &iter); set_line(w, &iter, TR("Track"), 0); /* Metadata */ gtk_tree_store_append(GTK_TREE_STORE(model), &iter, NULL); w->paths[PATH_METADATA] = gtk_tree_model_get_path(model, &iter); /* Audio */ gtk_tree_store_append(GTK_TREE_STORE(model), &iter, NULL); w->paths[PATH_AUDIO] = gtk_tree_model_get_path(model, &iter); /* Audio -> desc */ gtk_tree_store_append(GTK_TREE_STORE(model), &child, &iter); w->paths[PATH_AUDIO_DESC] = gtk_tree_model_get_path(model, &child); /* Audio -> format_i */ gtk_tree_store_append(GTK_TREE_STORE(model), &child, &iter); w->paths[PATH_AUDIO_FORMAT_I] = gtk_tree_model_get_path(model, &child); /* Audio -> format_o */ gtk_tree_store_append(GTK_TREE_STORE(model), &child, &iter); w->paths[PATH_AUDIO_FORMAT_O] = gtk_tree_model_get_path(model, &child); /* Video */ gtk_tree_store_append(GTK_TREE_STORE(model), &iter, NULL); w->paths[PATH_VIDEO] = gtk_tree_model_get_path(model, &iter); /* Video -> desc */ gtk_tree_store_append(GTK_TREE_STORE(model), &child, &iter); w->paths[PATH_VIDEO_DESC] = gtk_tree_model_get_path(model, &child); /* Video -> format_i */ gtk_tree_store_append(GTK_TREE_STORE(model), &child, &iter); w->paths[PATH_VIDEO_FORMAT_I] = gtk_tree_model_get_path(model, &child); /* Video -> format_o */ gtk_tree_store_append(GTK_TREE_STORE(model), &child, &iter); w->paths[PATH_VIDEO_FORMAT_O] = gtk_tree_model_get_path(model, &child); /* Subtitle */ gtk_tree_store_append(GTK_TREE_STORE(model), &iter, NULL); w->paths[PATH_SUBTITLE] = gtk_tree_model_get_path(model, &iter); /* Subtitle -> desc */ gtk_tree_store_append(GTK_TREE_STORE(model), &child, &iter); w->paths[PATH_SUBTITLE_DESC] = gtk_tree_model_get_path(model, &child); /* Subtitle -> format_i */ gtk_tree_store_append(GTK_TREE_STORE(model), &child, &iter); w->paths[PATH_SUBTITLE_FORMAT_I] = gtk_tree_model_get_path(model, &child); /* Subtitle -> format_o */ gtk_tree_store_append(GTK_TREE_STORE(model), &child, &iter); w->paths[PATH_SUBTITLE_FORMAT_O] = gtk_tree_model_get_path(model, &child); reset_tree(w); } static int find_node(bg_gtk_info_window_t * w, GtkTreePath * path) { int i; for(i = 0; i < PATH_NUM; i++) { if(!gtk_tree_path_compare(path, w->paths[i])) return i; } return -1; } static void row_expanded_callback(GtkTreeView *treeview, GtkTreeIter *arg1, GtkTreePath *arg2, gpointer user_data) { int i; bg_gtk_info_window_t * w; w = (bg_gtk_info_window_t*)user_data; i = find_node(w, arg2); if(i < 0) return; w->expanded[i] = 1; } static void row_collapsed_callback(GtkTreeView *treeview, GtkTreeIter *arg1, GtkTreePath *arg2, gpointer user_data) { int i; bg_gtk_info_window_t * w; w = (bg_gtk_info_window_t*)user_data; i = find_node(w, arg2); if(i < 0) return; w->expanded[i] = 0; } /* Clipboard */ #define TARGET_TEXT_PLAIN 1 static const GtkTargetEntry copy_paste_entries[] = { { "STRING", 0, TARGET_TEXT_PLAIN }, }; /* Callback functions for the clipboard */ static void clipboard_get_func(GtkClipboard *clipboard, GtkSelectionData *selection_data, guint info, gpointer data) { GdkAtom type_atom; bg_gtk_info_window_t * w = (bg_gtk_info_window_t*)data; type_atom = gdk_atom_intern("STRING", FALSE); if(!type_atom) return; gtk_selection_data_set(selection_data, type_atom, 8, (uint8_t*)w->clipboard, w->clipboard_len); } static void clipboard_clear_func(GtkClipboard *clipboard, gpointer data) { bg_gtk_info_window_t * w = (bg_gtk_info_window_t*)data; if(w->clipboard) { free(w->clipboard); w->clipboard_len = 0; w->clipboard = NULL; } } static void copy_selected(bg_gtk_info_window_t * w) { GtkTreeIter iter; GtkTreeSelection * selection; GtkClipboard *clipboard; GdkAtom clipboard_atom; clipboard_atom = gdk_atom_intern ("CLIPBOARD", FALSE); clipboard = gtk_clipboard_get(clipboard_atom); selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(w->treeview)); gtk_clipboard_set_with_data(clipboard, copy_paste_entries, sizeof(copy_paste_entries)/ sizeof(copy_paste_entries[0]), clipboard_get_func, clipboard_clear_func, (gpointer)w); if(w->clipboard) free(w->clipboard); gtk_tree_selection_get_selected(selection, NULL, &iter); w->clipboard = iter_to_string(w, NULL, 0, &iter, 1); if(w->clipboard) { /* Remove trailing '\n' */ w->clipboard[strlen(w->clipboard)-1] = '\0'; w->clipboard_len = strlen(w->clipboard) + 1; } else w->clipboard_len = 0; } static void copy_all(bg_gtk_info_window_t * w) { GtkClipboard *clipboard; GdkAtom clipboard_atom; clipboard_atom = gdk_atom_intern ("CLIPBOARD", FALSE); clipboard = gtk_clipboard_get(clipboard_atom); gtk_clipboard_set_with_data(clipboard, copy_paste_entries, sizeof(copy_paste_entries)/ sizeof(copy_paste_entries[0]), clipboard_get_func, clipboard_clear_func, (gpointer)w); if(w->clipboard) free(w->clipboard); w->clipboard = iter_to_string(w, NULL, 0, NULL, 1); if(w->clipboard) { w->clipboard_len = strlen(w->clipboard) + 1; } else w->clipboard_len = 0; } static void menu_callback(GtkWidget * wid, gpointer data) { bg_gtk_info_window_t * w = (bg_gtk_info_window_t*)data; /* Add files */ if(wid == w->menu.copy_all) copy_all(w); else if(wid == w->menu.copy_selected) copy_selected(w); } static GtkWidget * create_item(bg_gtk_info_window_t * w, GtkWidget * parent, const char * label, const char * pixmap) { GtkWidget * ret, *image; char * path; if(pixmap) { path = bg_search_file_read("icons", pixmap); if(path) { image = gtk_image_new_from_file(path); free(path); } else image = gtk_image_new(); gtk_widget_show(image); ret = gtk_image_menu_item_new_with_label(label); gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(ret), image); } else { ret = gtk_menu_item_new_with_label(label); } g_signal_connect(G_OBJECT(ret), "activate", G_CALLBACK(menu_callback), (gpointer)w); gtk_widget_show(ret); gtk_menu_shell_append(GTK_MENU_SHELL(parent), ret); return ret; } static void init_menu(bg_gtk_info_window_t * w) { w->menu.menu = gtk_menu_new(); w->menu.copy_selected = create_item(w, w->menu.menu, TR("Copy selected"), "copy_16.png"); w->menu.copy_all = create_item(w, w->menu.menu, TR("Copy all"), "copy_16.png"); } static gboolean button_press_callback(GtkWidget * wid, GdkEventButton * evt, gpointer data) { bg_gtk_info_window_t * w = (bg_gtk_info_window_t *)data; if(evt->button == 3) { gtk_menu_popup(GTK_MENU(w->menu.menu), NULL, NULL, NULL, NULL, 3, evt->time); return FALSE; } return FALSE; } bg_gtk_info_window_t * bg_gtk_info_window_create(bg_player_t * player, void (*close_callback)(bg_gtk_info_window_t*, void*), void * close_callback_data) { GtkTreeStore * store; GtkWidget * scrolledwin; GtkCellRenderer * text_renderer; GtkTreeViewColumn *column; GtkTreeSelection *selection; bg_gtk_info_window_t * ret; ret = calloc(1, sizeof(*ret)); ret->close_callback = close_callback; ret->close_callback_data = close_callback_data; /* Create objects */ ret->window = bg_gtk_window_new(GTK_WINDOW_TOPLEVEL); g_signal_connect(G_OBJECT(ret->window), "configure-event", G_CALLBACK(configure_callback), (gpointer)ret); gtk_window_set_title(GTK_WINDOW(ret->window), TR("Gmerlin Track Info")); ret->queue = bg_msg_queue_create(); /* Link message queue to the player */ bg_player_add_message_queue(player, ret->queue); /* Create treeview */ store = gtk_tree_store_new(NUM_COLUMNS, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING); ret->treeview = gtk_tree_view_new_with_model(GTK_TREE_MODEL(store)); gtk_tree_view_set_headers_visible(GTK_TREE_VIEW(ret->treeview), 0); gtk_tree_view_set_rules_hint(GTK_TREE_VIEW(ret->treeview), TRUE); gtk_widget_set_events(ret->treeview, GDK_BUTTON_PRESS_MASK); ret->collapse_id = g_signal_connect(G_OBJECT(ret->treeview), "row-collapsed", G_CALLBACK(row_collapsed_callback), (gpointer)ret); ret->expand_id = g_signal_connect(G_OBJECT(ret->treeview), "row-expanded", G_CALLBACK(row_expanded_callback), (gpointer)ret); g_signal_connect(G_OBJECT(ret->treeview), "button-press-event", G_CALLBACK(button_press_callback), (gpointer)ret); /* Column 1 */ text_renderer = gtk_cell_renderer_text_new(); column = gtk_tree_view_column_new(); gtk_tree_view_column_pack_start(column, text_renderer, TRUE); gtk_tree_view_column_add_attribute(column, text_renderer, "text", COLUMN_1); gtk_tree_view_column_add_attribute(column, text_renderer, "foreground", COLUMN_FG_COLOR); gtk_tree_view_append_column (GTK_TREE_VIEW(ret->treeview), column); /* Column 2 */ text_renderer = gtk_cell_renderer_text_new(); column = gtk_tree_view_column_new(); gtk_tree_view_column_pack_start(column, text_renderer, TRUE); gtk_tree_view_column_add_attribute(column, text_renderer, "text", COLUMN_2); gtk_tree_view_append_column (GTK_TREE_VIEW(ret->treeview), column); gtk_tree_view_column_add_attribute(column, text_renderer, "foreground", COLUMN_FG_COLOR); gtk_widget_show(ret->treeview); /* Selection mode */ selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(ret->treeview)); gtk_tree_selection_set_mode(selection, GTK_SELECTION_SINGLE); /* Set callbacks */ ret->idle_id = g_timeout_add(DELAY_TIME, idle_callback, (gpointer)ret); g_signal_connect(G_OBJECT(ret->window), "delete_event", G_CALLBACK(delete_callback), (gpointer)ret); /* pack objects */ scrolledwin = gtk_scrolled_window_new(NULL, NULL); gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolledwin), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC); gtk_container_add(GTK_CONTAINER(scrolledwin), ret->treeview); gtk_widget_show(scrolledwin); /* */ gtk_container_add(GTK_CONTAINER(ret->window), scrolledwin); init_tree(ret); init_menu(ret); return ret; } void bg_gtk_info_window_destroy(bg_gtk_info_window_t * w) { int i; bg_msg_queue_destroy(w->queue); if(w->clipboard) free(w->clipboard); g_source_remove(w->idle_id); for(i = 0; i < PATH_NUM; i++) { if(w->paths[i]) gtk_tree_path_free(w->paths[i]); } gtk_widget_destroy(w->window); free(w); } /* Show/hide the window */ void bg_gtk_info_window_show(bg_gtk_info_window_t * w) { if(!w->width || !w->height) { gtk_window_set_position(GTK_WINDOW(w->window), GTK_WIN_POS_CENTER); } gtk_widget_show(w->window); if(w->width && w->height) gtk_decorated_window_move_resize_window(GTK_WINDOW(w->window), w->x, w->y, w->width, w->height); else gtk_window_resize(GTK_WINDOW(w->window), 400, 400); } void bg_gtk_info_window_hide(bg_gtk_info_window_t * w) { gtk_widget_hide(w->window); } gmerlin-1.2.0~dfsg/lib/gtk/aboutwindow.c0000644000175000017500000001446711764363406020160 0ustar alessioalessio/***************************************************************** * gmerlin - a general purpose multimedia framework and applications * * Copyright (c) 2001 - 2011 Members of the Gmerlin project * gmerlin-general@lists.sourceforge.net * http://gmerlin.sourceforge.net * * 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 of the License, 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 this program. If not, see . * *****************************************************************/ #include #include #include #include #include #include #include #include struct bg_gtk_about_window_s { GtkWidget * window; GtkWidget * close_button; GtkWidget * url_button; bg_gtk_urllink_t * link; char * url_opener; bg_gtk_scrolltext_t * scrolltext; void (*close_callback)(bg_gtk_about_window_t*, void*); void * close_callback_data; }; static void about_window_destroy(bg_gtk_about_window_t * win) { bg_gtk_scrolltext_destroy(win->scrolltext); bg_gtk_urllink_destroy(win->link); gtk_widget_destroy(win->window); free(win); } static void button_callback(GtkWidget * w, gpointer data) { bg_gtk_about_window_t * win; win = (bg_gtk_about_window_t*)data; if((w == win->close_button) || (w == win->window)) { if(win->close_callback) win->close_callback(win, win->close_callback_data); about_window_destroy(win); } else if(w == win->url_button) { } } static gboolean delete_callback(GtkWidget * w, GdkEventAny * event, gpointer data) { bg_gtk_about_window_t * win; win = (bg_gtk_about_window_t*)data; button_callback(win->window, data); return TRUE; } static const float scroll_fg[3] = { 0.0, 1.0, 1.0 }; static const float scroll_bg[3] = { 0.0, 0.0, 0.0 }; bg_gtk_about_window_t * bg_gtk_about_window_create(const char * name, const char * version, const char * icon, void (*close_callback)(bg_gtk_about_window_t*, void*), void * close_callback_data) { char * path; char * label_text; GtkWidget * box; GtkWidget * label1; GtkWidget * label2; GtkWidget * label3; GtkWidget * table; GtkWidget * image; bg_gtk_about_window_t * ret; ret = calloc(1, sizeof(*ret)); ret->close_callback = close_callback; ret->close_callback_data = close_callback_data; ret->scrolltext = bg_gtk_scrolltext_create(300, 24); bg_gtk_scrolltext_set_font(ret->scrolltext, "Sans-10:slant=0:weight=200:width=100"); bg_gtk_scrolltext_set_text(ret->scrolltext, TR("Get the latest source version from http://gmerlin.sourceforge.net * * * If you installed gmerlin from a binary package, you might have limited features"), scroll_fg, scroll_bg); /* Create window */ ret->window = bg_gtk_window_new(GTK_WINDOW_TOPLEVEL); gtk_window_set_position(GTK_WINDOW(ret->window), GTK_WIN_POS_CENTER); gtk_window_set_title(GTK_WINDOW(ret->window), TR("About")); g_signal_connect(G_OBJECT(ret->window), "delete_event", G_CALLBACK(delete_callback), (gpointer)ret); ret->close_button = gtk_button_new_from_stock(GTK_STOCK_CLOSE); g_signal_connect(G_OBJECT(ret->close_button), "clicked", G_CALLBACK(button_callback), (gpointer)ret); ret->link = bg_gtk_urllink_create(TR("Visit homepage"), "http://gmerlin.sourceforge.net"); gtk_widget_show(ret->close_button); path = bg_search_file_read("icons", icon); if(path) { image = gtk_image_new_from_file(path); gtk_widget_show(image); free(path); } else image = NULL; /* Label 1 */ label_text = bg_sprintf("%s %s", name, version); label1 = gtk_label_new(""); gtk_label_set_markup(GTK_LABEL(label1), label_text); free(label_text); #if 0 attr_list = pango_attr_list_new(); // attr = pango_attr_size_new_absolute(18); // pango_attr_list_insert(attr_list,attr); attr = pango_attr_weight_new(PANGO_WEIGHT_BOLD); pango_attr_list_insert(attr_list,attr); gtk_label_set_attributes(GTK_LABEL(label1), attr_list); pango_attr_list_unref(attr_list); #endif gtk_widget_show(label1); label2 = gtk_label_new(TR("Copyright \302\251 2001-2009 Members of the gmerlin project")); gtk_widget_show(label2); label3 = gtk_label_new(TR("This is free software. You may redistribute copies of it under the terms of\n\ the GNU General Public License .\n\ There is NO WARRANTY.")); gtk_widget_show(label3); /* Pack */ table = gtk_table_new(5, 2, 0); gtk_table_set_row_spacings(GTK_TABLE(table), 10); gtk_table_set_col_spacings(GTK_TABLE(table), 10); gtk_container_set_border_width(GTK_CONTAINER(table), 10); if(image) gtk_table_attach_defaults(GTK_TABLE(table), image, 0, 1, 2, 3); gtk_table_attach_defaults(GTK_TABLE(table), label1, 0, 2, 0, 1); box = gtk_hbox_new(0, 5); bg_gtk_box_pack_start_defaults(GTK_BOX(box), label2); bg_gtk_box_pack_start_defaults(GTK_BOX(box), bg_gtk_urllink_get_widget(ret->link)); gtk_widget_show(box); gtk_table_attach_defaults(GTK_TABLE(table), box, 0, 2, 1, 2); gtk_table_attach_defaults(GTK_TABLE(table), label3, 1, 2, 2, 3); gtk_table_attach_defaults(GTK_TABLE(table), bg_gtk_scrolltext_get_widget(ret->scrolltext), 0, 2, 3, 4); gtk_table_attach(GTK_TABLE(table), ret->close_button, 0, 2, 4, 5, GTK_SHRINK, GTK_FILL, 0, 0); gtk_widget_show(table); gtk_container_add(GTK_CONTAINER(ret->window), table); gtk_widget_show(ret->window); return ret; } gmerlin-1.2.0~dfsg/lib/gtk/gtk_dialog.h0000644000175000017500000001041511764363406017714 0ustar alessioalessio/***************************************************************** * gmerlin - a general purpose multimedia framework and applications * * Copyright (c) 2001 - 2011 Members of the Gmerlin project * gmerlin-general@lists.sourceforge.net * http://gmerlin.sourceforge.net * * 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 of the License, 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 this program. If not, see . * *****************************************************************/ #include #include #include #include #include typedef struct bg_gtk_widget_s bg_gtk_widget_t; typedef struct { /* value -> widget */ void (*get_value)(bg_gtk_widget_t * w); /* widget -> value */ void (*set_value)(bg_gtk_widget_t * w); /* Subsections -> set_parameter() */ void (*apply_sub_params)(bg_gtk_widget_t * w); void (*destroy)(bg_gtk_widget_t * w); void (*attach)(void * priv, GtkWidget * table, int * row, int * num_columns); } gtk_widget_funcs_t; struct bg_gtk_widget_s { void * priv; const gtk_widget_funcs_t * funcs; bg_parameter_value_t value; bg_parameter_value_t last_value; /* For pressing ESC */ const bg_parameter_info_t * info; /* For change callbacks */ bg_set_parameter_func_t change_callback; void * change_callback_data; gulong callback_id; GtkWidget * callback_widget; /* position needs this */ gulong callback_id_2; GtkWidget * callback_widget_2; bg_cfg_section_t * cfg_section; bg_cfg_section_t * cfg_subsection_save; /* Only set if the parameter refers to a plugin */ bg_plugin_registry_t * plugin_reg; }; void bg_gtk_create_checkbutton(bg_gtk_widget_t *, const char * translation_domain); void bg_gtk_create_int(bg_gtk_widget_t *, const char * translation_domain); void bg_gtk_create_float(bg_gtk_widget_t *, const char * translation_domain); void bg_gtk_create_slider_int(bg_gtk_widget_t *, const char * translation_domain); void bg_gtk_create_slider_float(bg_gtk_widget_t *, const char * translation_domain); void bg_gtk_create_string(bg_gtk_widget_t *, const char * translation_domain); void bg_gtk_create_stringlist(bg_gtk_widget_t *, const char * translation_domain); void bg_gtk_create_color_rgb(bg_gtk_widget_t *, const char * translation_domain); void bg_gtk_create_color_rgba(bg_gtk_widget_t *, const char * translation_domain); void bg_gtk_create_font(bg_gtk_widget_t *, const char * translation_domain); void bg_gtk_create_device(bg_gtk_widget_t *, const char * translation_domain); void bg_gtk_create_time(bg_gtk_widget_t *, const char * translation_domain); void bg_gtk_create_multi_list(bg_gtk_widget_t *, bg_set_parameter_func_t set_param, bg_get_parameter_func_t get_param, void * data, const char * translation_domain); void bg_gtk_create_multi_chain(bg_gtk_widget_t *, bg_set_parameter_func_t set_param, bg_get_parameter_func_t get_param, void * data, const char * translation_domain); void bg_gtk_create_multi_menu(bg_gtk_widget_t *, bg_set_parameter_func_t set_param, bg_get_parameter_func_t get_param, void * data, const char * translation_domain); void bg_gtk_create_position(bg_gtk_widget_t *, const char * translation_domain); void bg_gtk_create_directory(bg_gtk_widget_t *, const char * translation_domain); void bg_gtk_create_file(bg_gtk_widget_t *, const char * translation_domain); void bg_gtk_create_button(bg_gtk_widget_t *, const char * translation_domain); void bg_gtk_change_callback(GtkWidget * gw, gpointer data); void bg_gtk_change_callback_block(bg_gtk_widget_t * w, int block); gmerlin-1.2.0~dfsg/lib/gtk/albumentry.c0000644000175000017500000000464011764363406017770 0ustar alessioalessio/***************************************************************** * gmerlin - a general purpose multimedia framework and applications * * Copyright (c) 2001 - 2011 Members of the Gmerlin project * gmerlin-general@lists.sourceforge.net * http://gmerlin.sourceforge.net * * 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 of the License, 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 this program. If not, see . * *****************************************************************/ #include #include #include #include #include #include #include #include /* This pops up a which shows all informations about a selected track */ #define S(s) (s?s:"(NULL)") void bg_gtk_album_entry_show(const bg_album_entry_t * entry, GtkWidget * parent) { char * text, * utf8_location; bg_gtk_textwindow_t * win; char duration[GAVL_TIME_STRING_LEN]; gavl_time_prettyprint(entry->duration, duration); if(entry->location) utf8_location = bg_system_to_utf8(entry->location, -1); else utf8_location = NULL; text = bg_sprintf(TR("Name:\t %s\nLocation:\t %s\nTrack:\t %d/%d%s\nPlugin:\t %s\nDuration:\t %s\nAudio Streams:\t %d\nVideo Streams:\t %d\nSubtitle Streams:\t %d"), S(entry->name), S(utf8_location), entry->index+1, entry->total_tracks, (entry->flags & BG_ALBUM_ENTRY_EDL ? " (EDL)" : ""), (entry->plugin ? entry->plugin : TR("Auto detect")), duration, entry->num_audio_streams, entry->num_video_streams, entry->num_subtitle_streams ); win = bg_gtk_textwindow_create(text, entry->name); free(text); bg_gtk_textwindow_show(win, 0, parent); if(utf8_location) free(utf8_location); } gmerlin-1.2.0~dfsg/lib/gtk/gtkutils.c0000644000175000017500000003542411764363406017460 0ustar alessioalessio/***************************************************************** * gmerlin - a general purpose multimedia framework and applications * * Copyright (c) 2001 - 2011 Members of the Gmerlin project * gmerlin-general@lists.sourceforge.net * http://gmerlin.sourceforge.net * * 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 of the License, 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 this program. If not, see . * *****************************************************************/ #include #include #include #include #include #include #include #include #include #include #include #include #include GdkPixbuf * bg_gtk_pixbuf_scale_alpha(GdkPixbuf * src, int dest_width, int dest_height, float * foreground, float * background) { int i, j; GdkPixbuf * ret; int rowstride; uint8_t * data; uint8_t * ptr; int background_i[3]; int foreground_i[3]; for(i = 0; i < 3; i++) { background_i[i] = (int)(255.0 * background[i]); foreground_i[i] = (int)(255.0 * foreground[i]); } ret = gdk_pixbuf_scale_simple(src, dest_width, dest_height, GDK_INTERP_BILINEAR); rowstride = gdk_pixbuf_get_rowstride(ret); data = gdk_pixbuf_get_pixels(ret); for(i = 0; i < dest_height; i++) { ptr = data; for(j = 0; j < dest_width; j++) { ptr[0] = (ptr[3] * foreground_i[0] + (0xFF - ptr[3]) * background_i[0]) >> 8; ptr[1] = (ptr[3] * foreground_i[1] + (0xFF - ptr[3]) * background_i[1]) >> 8; ptr[2] = (ptr[3] * foreground_i[2] + (0xFF - ptr[3]) * background_i[2]) >> 8; ptr[3] = 0xff; ptr += 4; } data += rowstride; } return ret; } static GdkPixbuf * window_pixbuf = NULL; static char * default_window_name = NULL; static char * default_window_class = NULL; static void set_default_window_icon(const char * icon) { char * tmp; tmp = bg_search_file_read("icons", icon); if(tmp) { if(window_pixbuf) g_object_unref(window_pixbuf); window_pixbuf = gdk_pixbuf_new_from_file(tmp, NULL); free(tmp); } } GtkWidget * bg_gtk_window_new(GtkWindowType type) { GtkWidget * ret = gtk_window_new(type); if(window_pixbuf) gtk_window_set_icon(GTK_WINDOW(ret), window_pixbuf); if(default_window_name && default_window_class) { gtk_window_set_wmclass(GTK_WINDOW(ret), default_window_name, default_window_class); } return ret; } void bg_gtk_init(int * argc, char *** argv, const char * default_window_icon, const char * win_name, const char * win_class) { gtk_init(argc, argv); /* No, we don't like commas as decimal separators */ setlocale(LC_NUMERIC, "C"); /* Set the default window icon */ set_default_window_icon(default_window_icon); /* Set default class hints */ default_window_name = bg_strdup(default_window_name, win_name); default_window_class = bg_strdup(default_window_class, win_class); } void bg_gdk_pixbuf_render_pixmap_and_mask(GdkPixbuf *pixbuf, GdkPixmap **pixmap_return, GdkBitmap **mask_return) { int width, height; char * mask_data; gdk_pixbuf_render_pixmap_and_mask(pixbuf, pixmap_return, mask_return, 0x80); if(mask_return && !(*mask_return)) { width = gdk_pixbuf_get_width(pixbuf); height = gdk_pixbuf_get_height(pixbuf); mask_data = malloc(width * height); memset(mask_data, 0xff, width * height); *mask_return = gdk_bitmap_create_from_data(NULL, mask_data, width, height); free(mask_data); } } void bg_gtk_set_widget_bg_pixmap(GtkWidget * widget, GdkPixmap *pixmap) { GtkStyle *style; style = gtk_style_copy (widget->style); if (style->bg_pixmap[0]) g_object_unref (style->bg_pixmap[0]); style->bg_pixmap[0] = g_object_ref (pixmap); gtk_widget_set_style (widget, style); g_object_unref (style); } /* Font name conversion */ /* Really stupid, that pango font names are incompatible to * fontconfig names, so we must convert them ourselves */ /* Ripped from pango sourcecode */ static int pango_fc_convert_weight_to_fc (PangoWeight pango_weight) { if (pango_weight < (PANGO_WEIGHT_NORMAL + PANGO_WEIGHT_LIGHT) / 2) return FC_WEIGHT_LIGHT; else if (pango_weight < (PANGO_WEIGHT_NORMAL + 600) / 2) return FC_WEIGHT_MEDIUM; else if (pango_weight < (600 + PANGO_WEIGHT_BOLD) / 2) return FC_WEIGHT_DEMIBOLD; else if (pango_weight < (PANGO_WEIGHT_BOLD + PANGO_WEIGHT_ULTRABOLD) / 2) return FC_WEIGHT_BOLD; else return FC_WEIGHT_BLACK; } static int pango_fc_convert_slant_to_fc (PangoStyle pango_style) { switch (pango_style) { case PANGO_STYLE_NORMAL: return FC_SLANT_ROMAN; case PANGO_STYLE_ITALIC: return FC_SLANT_ITALIC; case PANGO_STYLE_OBLIQUE: return FC_SLANT_OBLIQUE; default: return FC_SLANT_ROMAN; } } #ifdef FC_WIDTH static int pango_fc_convert_width_to_fc (PangoStretch pango_stretch) { switch (pango_stretch) { case PANGO_STRETCH_NORMAL: return FC_WIDTH_NORMAL; case PANGO_STRETCH_ULTRA_CONDENSED: return FC_WIDTH_ULTRACONDENSED; case PANGO_STRETCH_EXTRA_CONDENSED: return FC_WIDTH_EXTRACONDENSED; case PANGO_STRETCH_CONDENSED: return FC_WIDTH_CONDENSED; case PANGO_STRETCH_SEMI_CONDENSED: return FC_WIDTH_SEMICONDENSED; case PANGO_STRETCH_SEMI_EXPANDED: return FC_WIDTH_SEMIEXPANDED; case PANGO_STRETCH_EXPANDED: return FC_WIDTH_EXPANDED; case PANGO_STRETCH_EXTRA_EXPANDED: return FC_WIDTH_EXTRAEXPANDED; case PANGO_STRETCH_ULTRA_EXPANDED: return FC_WIDTH_ULTRAEXPANDED; default: return FC_WIDTH_NORMAL; } } #endif static FcPattern * pango_fc_make_pattern (const PangoFontDescription *description, double size) { FcPattern *pattern; int slant; int weight; char **families; int i; #ifdef FC_WIDTH int width; #endif slant = pango_fc_convert_slant_to_fc (pango_font_description_get_style (description)); weight = pango_fc_convert_weight_to_fc (pango_font_description_get_weight (description)); #ifdef FC_WIDTH width = pango_fc_convert_width_to_fc (pango_font_description_get_stretch (description)); #endif /* The reason for passing in FC_SIZE as well as FC_PIXEL_SIZE is * to work around a bug in libgnomeprint where it doesn't look * for FC_PIXEL_SIZE. See http://bugzilla.gnome.org/show_bug.cgi?id=169020 * * Putting FC_SIZE in here slightly reduces the efficiency * of caching of patterns and fonts when working with multiple different * dpi values. */ pattern = FcPatternBuild (NULL, FC_WEIGHT, FcTypeInteger, weight, FC_SLANT, FcTypeInteger, slant, #ifdef FC_WIDTH FC_WIDTH, FcTypeInteger, width, #endif FC_SIZE, FcTypeDouble, size, NULL); families = g_strsplit (pango_font_description_get_family (description), ",", -1); for (i = 0; families[i]; i++) FcPatternAddString (pattern, FC_FAMILY, (const FcChar8*)families[i]); g_strfreev (families); return pattern; } char * bg_gtk_convert_font_name_from_pango(const char * name) { char * ret; PangoFontDescription *description; FcPattern *pattern; double size = 12.0; const char * pos; pos = &name[strlen(name) - 1]; while(!isspace(*pos)) { if(pos == name) return NULL; pos--; } pos++; if(isdigit(*pos) || (*pos == '.')) size = strtod(pos, NULL); else size = 12.0; description = pango_font_description_from_string(name); pattern = pango_fc_make_pattern(description, size); ret = (char*)FcNameUnparse(pattern); FcPatternDestroy(pattern); pango_font_description_free(description); return ret; } char * bg_gtk_convert_font_name_to_pango(const char * name) { char * ret, *tmp; PangoFontDescription *description; FcPattern *pattern; pattern = FcNameParse((const FcChar8 *)name); description = pango_fc_font_description_from_pattern(pattern, TRUE); tmp = pango_font_description_to_string(description); ret = bg_strdup(NULL, tmp); g_free(tmp); FcPatternDestroy(pattern); pango_font_description_free(description); return ret; } static int show_tooltips = 1; #if GTK_MINOR_VERSION < 12 static GtkTooltips * tooltips = NULL; void bg_gtk_tooltips_set_tip(GtkWidget * w, const char * str, const char * translation_domain) { str = dgettext(translation_domain, str); if(!tooltips) { tooltips = gtk_tooltips_new(); g_object_ref (G_OBJECT (tooltips)); #if GTK_MINOR_VERSION < 10 gtk_object_sink (GTK_OBJECT (tooltips)); #else g_object_ref_sink(G_OBJECT(tooltips)); #endif } if(show_tooltips) gtk_tooltips_enable(tooltips); else gtk_tooltips_disable(tooltips); gtk_tooltips_set_tip(tooltips, w, str, str); } void bg_gtk_set_tooltips(int enable) { show_tooltips = enable; if(tooltips) { if(show_tooltips) gtk_tooltips_enable(tooltips); else gtk_tooltips_disable(tooltips); } } #else static GQuark tooltip_quark = 0; static gboolean tooltip_callback(GtkWidget *widget, gint x, gint y, gboolean keyboard_mode, GtkTooltip *tooltip, gpointer user_data) { char * str; if(show_tooltips) { str = g_object_get_qdata(G_OBJECT(widget), tooltip_quark); gtk_tooltip_set_text(tooltip, str); return TRUE; } else return FALSE; } void bg_gtk_tooltips_set_tip(GtkWidget * w, const char * str, const char * translation_domain) { GValue val = { 0 }; str = TR_DOM(str); // gtk_widget_set_tooltip_text(w, str); if(!tooltip_quark) tooltip_quark = g_quark_from_string("gmerlin-tooltip"); g_object_set_qdata_full(G_OBJECT(w), tooltip_quark, g_strdup(str), g_free); g_value_init(&val, G_TYPE_BOOLEAN); g_value_set_boolean(&val, 1); g_object_set_property(G_OBJECT(w), "has-tooltip", &val); g_signal_connect(G_OBJECT(w), "query-tooltip", G_CALLBACK(tooltip_callback), NULL); } void bg_gtk_set_tooltips(int enable) { show_tooltips = enable; } #endif int bg_gtk_get_tooltips() { return show_tooltips; } GtkWidget * bg_gtk_get_toplevel(GtkWidget * w) { GtkWidget * toplevel; if(!w) return NULL; toplevel = gtk_widget_get_toplevel(w); if(!bg_gtk_widget_is_toplevel(toplevel)) toplevel = NULL; return toplevel; } static void pixbuf_destroy_notify(guchar *pixels, gpointer data) { gavl_video_frame_destroy(data); } GdkPixbuf * bg_gtk_pixbuf_from_frame(gavl_video_format_t * format, gavl_video_frame_t * frame) { if(format->pixelformat == GAVL_RGB_24) { return gdk_pixbuf_new_from_data(frame->planes[0], GDK_COLORSPACE_RGB, FALSE, 8, format->image_width, format->image_height, frame->strides[0], pixbuf_destroy_notify, frame); } else if(format->pixelformat == GAVL_RGBA_32) { return gdk_pixbuf_new_from_data(frame->planes[0], GDK_COLORSPACE_RGB, TRUE, 8, format->image_width, format->image_height, frame->strides[0], pixbuf_destroy_notify, frame); } else return NULL; } int bg_gtk_widget_is_realized(GtkWidget * w) { #if GTK_CHECK_VERSION(2,20,0) return gtk_widget_get_realized(w); #else return GTK_WIDGET_REALIZED(w); #endif } int bg_gtk_widget_is_toplevel(GtkWidget * w) { #if GTK_CHECK_VERSION(2,18,0) return gtk_widget_is_toplevel(w); #else return GTK_WIDGET_TOPLEVEL(w); #endif } void bg_gtk_widget_set_can_default(GtkWidget *w, gboolean can_default) { #if GTK_CHECK_VERSION(2,18,0) gtk_widget_set_can_default(w, can_default); #else if(can_default) GTK_WIDGET_SET_FLAGS(w, GTK_CAN_DEFAULT); else GTK_WIDGET_UNSET_FLAGS(w, GTK_CAN_DEFAULT); #endif } void bg_gtk_widget_set_can_focus(GtkWidget *w, gboolean can_focus) { #if GTK_CHECK_VERSION(2,18,0) gtk_widget_set_can_focus(w, can_focus); #else if(can_focus) GTK_WIDGET_SET_FLAGS(w, GTK_CAN_FOCUS); else GTK_WIDGET_UNSET_FLAGS(w, GTK_CAN_FOCUS); #endif } GtkWidget * bg_gtk_combo_box_new_text() { #if GTK_CHECK_VERSION(2,24,0) return gtk_combo_box_text_new(); #else return gtk_combo_box_new_text(); #endif } void bg_gtk_combo_box_append_text(GtkWidget *combo_box, const gchar *text) { #if GTK_CHECK_VERSION(2,24,0) gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo_box), text); #else gtk_combo_box_append_text(GTK_COMBO_BOX(combo_box), text); #endif } void bg_gtk_combo_box_remove_text(GtkWidget * b, int index) { #if GTK_CHECK_VERSION(2,24,0) int i; GtkTreeIter it; GtkTreeModel * model; model = gtk_combo_box_get_model(GTK_COMBO_BOX(b)); if(!gtk_tree_model_get_iter_first(model, &it)) return; for(i = 0; i < index; i++) { if(!gtk_tree_model_iter_next(model, &it)) return; } gtk_list_store_remove(GTK_LIST_STORE(model), &it); #else gtk_combo_box_remove_text(GTK_COMBO_BOX(b), index); #endif } gmerlin-1.2.0~dfsg/lib/gtk/cfg_font.c0000644000175000017500000001334411764363406017374 0ustar alessioalessio/***************************************************************** * gmerlin - a general purpose multimedia framework and applications * * Copyright (c) 2001 - 2011 Members of the Gmerlin project * gmerlin-general@lists.sourceforge.net * http://gmerlin.sourceforge.net * * 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 of the License, 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 this program. If not, see . * *****************************************************************/ #include #include #include #include "gtk_dialog.h" #include typedef struct { GtkWidget * entry; GtkWidget * label; GtkWidget * button; GtkWidget * fontselect; } font_t; static void button_callback(GtkWidget * w, gpointer data); static void get_value(bg_gtk_widget_t * w) { font_t * priv; char * tmp; priv = (font_t*)(w->priv); if(!w->value.val_str || (*w->value.val_str == '\0')) { gtk_entry_set_text(GTK_ENTRY(priv->entry), ""); return; } tmp = bg_gtk_convert_font_name_to_pango(w->value.val_str); gtk_entry_set_text(GTK_ENTRY(priv->entry), tmp); free(tmp); } static void set_value(bg_gtk_widget_t * w) { font_t * priv; const char * font; priv = (font_t*)(w->priv); font = gtk_entry_get_text(GTK_ENTRY(priv->entry)); if(w->value.val_str) { free(w->value.val_str); w->value.val_str = NULL; } if(*font != '\0') { w->value.val_str = bg_gtk_convert_font_name_from_pango(font); } } static void destroy(bg_gtk_widget_t * w) { font_t * priv = (font_t*)(w->priv); if(priv->fontselect) gtk_widget_destroy(priv->fontselect); free(priv); } static void attach(void * priv, GtkWidget * table, int * row, int * num_columns) { font_t * f = (font_t*)priv; if(*num_columns < 3) *num_columns = 3; gtk_table_resize(GTK_TABLE(table), *row+1, *num_columns); gtk_table_attach(GTK_TABLE(table), f->label, 0, 1, *row, *row+1, GTK_FILL, GTK_SHRINK, 0, 0); gtk_table_attach(GTK_TABLE(table), f->entry, 1, 2, *row, *row+1, GTK_FILL | GTK_EXPAND, GTK_SHRINK, 0, 0); gtk_table_attach(GTK_TABLE(table), f->button, 2, 3, *row, *row+1, GTK_FILL, GTK_SHRINK, 0, 0); (*row)++; } static const gtk_widget_funcs_t funcs = { .get_value = get_value, .set_value = set_value, .destroy = destroy, .attach = attach }; static gboolean delete_callback(GtkWidget * w, GdkEventAny * event, gpointer data) { button_callback(w, data); return TRUE; } static void button_callback(GtkWidget * w, gpointer data) { char * fontname; font_t * priv = (font_t*)data; GtkWidget * toplevel; if(w == priv->button) { if(!priv->fontselect) { priv->fontselect = gtk_font_selection_dialog_new("Select a font"); gtk_window_set_modal(GTK_WINDOW(priv->fontselect), TRUE); toplevel = bg_gtk_get_toplevel(priv->button); if(toplevel) gtk_window_set_transient_for(GTK_WINDOW(priv->fontselect), GTK_WINDOW(toplevel)); g_signal_connect(G_OBJECT(GTK_FONT_SELECTION_DIALOG(priv->fontselect)->ok_button), "clicked", G_CALLBACK(button_callback), (gpointer)priv); g_signal_connect(G_OBJECT(GTK_FONT_SELECTION_DIALOG(priv->fontselect)->cancel_button), "clicked", G_CALLBACK(button_callback), (gpointer)priv); g_signal_connect(G_OBJECT(priv->fontselect), "delete_event", G_CALLBACK(delete_callback), (gpointer)priv); } gtk_font_selection_set_font_name(GTK_FONT_SELECTION(GTK_FONT_SELECTION_DIALOG(priv->fontselect)->fontsel), gtk_entry_get_text(GTK_ENTRY(priv->entry))); gtk_widget_show(priv->fontselect); gtk_main(); } else if(priv->fontselect) { if(w == GTK_FONT_SELECTION_DIALOG(priv->fontselect)->ok_button) { gtk_widget_hide(priv->fontselect); gtk_main_quit(); fontname = gtk_font_selection_get_font_name(GTK_FONT_SELECTION(GTK_FONT_SELECTION_DIALOG(priv->fontselect)->fontsel)); gtk_entry_set_text(GTK_ENTRY(priv->entry), fontname); g_free(fontname); } if((w == GTK_FONT_SELECTION_DIALOG(priv->fontselect)->cancel_button) || (w == priv->fontselect)) { gtk_widget_hide(priv->fontselect); gtk_main_quit(); } } } void bg_gtk_create_font(bg_gtk_widget_t * w, const char * translation_domain) { font_t * priv = calloc(1, sizeof(*priv)); priv->entry = gtk_entry_new(); if(w->info->help_string) { bg_gtk_tooltips_set_tip(priv->entry, w->info->help_string, translation_domain); } gtk_widget_show(priv->entry); priv->label = gtk_label_new(TR_DOM(w->info->long_name)); gtk_misc_set_alignment(GTK_MISC(priv->label), 0.0, 0.5); gtk_widget_show(priv->label); priv->button = gtk_button_new_with_label(TR("Browse...")); g_signal_connect(G_OBJECT(priv->button), "clicked", G_CALLBACK(button_callback), (gpointer)priv); gtk_widget_show(priv->button); w->funcs = &funcs; w->priv = priv; } gmerlin-1.2.0~dfsg/lib/gtk/urllink.c0000644000175000017500000000630111764363406017262 0ustar alessioalessio/***************************************************************** * gmerlin - a general purpose multimedia framework and applications * * Copyright (c) 2001 - 2011 Members of the Gmerlin project * gmerlin-general@lists.sourceforge.net * http://gmerlin.sourceforge.net * * 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 of the License, 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 this program. If not, see . * *****************************************************************/ #include #include #include #include #include struct bg_gtk_urllink_s { GtkWidget * widget; GdkCursor * cursor; char * url; char * browser_command; }; static void realize_callback(GtkWidget * w, gpointer data) { bg_gtk_urllink_t * u; u = (bg_gtk_urllink_t *)data; gdk_window_set_cursor(u->widget->window, u->cursor); } static void button_callback(GtkWidget * w, GdkEventButton * evt, gpointer data) { char * command; bg_gtk_urllink_t * u; u = (bg_gtk_urllink_t *)data; command = bg_sprintf(u->browser_command, u->url); command = bg_strcat(command, " &"); bg_system(command); } bg_gtk_urllink_t * bg_gtk_urllink_create(const char * text, const char * url) { bg_gtk_urllink_t * ret; GtkWidget * label; char * tmp_string; ret = calloc(1, sizeof(*ret)); ret->browser_command = bg_find_url_launcher(); if(!ret->browser_command) { tmp_string = bg_sprintf("%s [%s]", text, url); ret->widget = gtk_label_new(tmp_string); gtk_widget_show(ret->widget); free(tmp_string); } else { ret->url = bg_strdup(ret->url, url); label = gtk_label_new(""); tmp_string = bg_sprintf("%s", text); gtk_label_set_markup(GTK_LABEL(label), tmp_string); gtk_widget_show(label); ret->widget = gtk_event_box_new(); gtk_container_add(GTK_CONTAINER(ret->widget), label); ret->cursor = gdk_cursor_new(GDK_HAND2); gtk_widget_set_events(ret->widget, GDK_BUTTON_PRESS_MASK); g_signal_connect(ret->widget, "realize", G_CALLBACK(realize_callback), ret); g_signal_connect(ret->widget, "button-press-event", G_CALLBACK(button_callback), ret); gtk_widget_show(ret->widget); } if(tmp_string) free(tmp_string); return ret; } GtkWidget * bg_gtk_urllink_get_widget(bg_gtk_urllink_t * u) { return u->widget; } void bg_gtk_urllink_destroy(bg_gtk_urllink_t * u) { gdk_cursor_unref(u->cursor); if(u->url) free(u->url); if(u->browser_command) free(u->browser_command); free(u); } gmerlin-1.2.0~dfsg/lib/gtk/message.c0000644000175000017500000001002111764363406017220 0ustar alessioalessio/***************************************************************** * gmerlin - a general purpose multimedia framework and applications * * Copyright (c) 2001 - 2011 Members of the Gmerlin project * gmerlin-general@lists.sourceforge.net * http://gmerlin.sourceforge.net * * 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 of the License, 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 this program. If not, see . * *****************************************************************/ #include #include #include #include #include #include typedef struct { GtkWidget * window; GtkWidget * ok_button; GtkWidget * label; } message_t; static void button_callback(GtkWidget * w, gpointer * data) { gtk_main_quit(); } static gboolean delete_callback(GtkWidget * w, GdkEventAny * evt, gpointer data) { button_callback(w, data); return TRUE; } void bg_gtk_message(const char * message, int type, GtkWidget * parent) { GtkWidget * buttonbox; message_t * q; GtkWidget * label; GtkWidget * mainbox; GtkWidget * hbox; GtkWidget * image = NULL; q = calloc(1, sizeof(*q)); /* Create objects */ q->window = bg_gtk_window_new(GTK_WINDOW_TOPLEVEL); gtk_window_set_position(GTK_WINDOW(q->window), GTK_WIN_POS_CENTER_ON_PARENT); parent = bg_gtk_get_toplevel(parent); if(parent) gtk_window_set_transient_for(GTK_WINDOW(q->window), GTK_WINDOW(parent)); q->ok_button = gtk_button_new_from_stock(GTK_STOCK_OK); label = gtk_label_new(message); if(type == BG_GTK_MESSAGE_INFO) image = gtk_image_new_from_stock(GTK_STOCK_DIALOG_INFO, GTK_ICON_SIZE_DIALOG); else if(type == BG_GTK_MESSAGE_ERROR) image = gtk_image_new_from_stock(GTK_STOCK_DIALOG_ERROR, GTK_ICON_SIZE_DIALOG); /* Set attributes */ gtk_window_set_modal(GTK_WINDOW(q->window), 1); gtk_window_set_title(GTK_WINDOW(q->window), TR("Message")); gtk_window_set_position(GTK_WINDOW(q->window), GTK_WIN_POS_CENTER_ON_PARENT); bg_gtk_widget_set_can_default(q->ok_button, TRUE); gtk_label_set_justify(GTK_LABEL(label), GTK_JUSTIFY_CENTER); /* Set callbacks */ g_signal_connect(G_OBJECT(q->ok_button), "clicked", G_CALLBACK(button_callback), (gpointer)q); g_signal_connect(G_OBJECT(q->window), "delete_event", G_CALLBACK(delete_callback), (gpointer)q); /* Show everything */ gtk_widget_show(label); gtk_widget_show(image); gtk_widget_show(q->ok_button); /* Pack the objects */ mainbox = gtk_vbox_new(0, 5); hbox = gtk_hbox_new(0, 5); gtk_container_set_border_width(GTK_CONTAINER(mainbox), 5); bg_gtk_box_pack_start_defaults(GTK_BOX(hbox), image); bg_gtk_box_pack_start_defaults(GTK_BOX(hbox), label); gtk_widget_show(hbox); bg_gtk_box_pack_start_defaults(GTK_BOX(mainbox), hbox); buttonbox = gtk_hbutton_box_new(); gtk_box_set_spacing(GTK_BOX(buttonbox), 10); gtk_container_add(GTK_CONTAINER(buttonbox), q->ok_button); gtk_widget_show(buttonbox); bg_gtk_box_pack_start_defaults(GTK_BOX(mainbox), buttonbox); gtk_widget_show(mainbox); gtk_container_add(GTK_CONTAINER(q->window), mainbox); gtk_widget_show(q->window); gtk_main(); /* Window has gone, fetch the answer */ /* Destroy everything */ gtk_widget_hide(q->window); gtk_widget_destroy(q->window); free(q); } gmerlin-1.2.0~dfsg/lib/gtk/urlselect.c0000644000175000017500000001505211764363406017607 0ustar alessioalessio/***************************************************************** * gmerlin - a general purpose multimedia framework and applications * * Copyright (c) 2001 - 2011 Members of the Gmerlin project * gmerlin-general@lists.sourceforge.net * http://gmerlin.sourceforge.net * * 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 of the License, 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 this program. If not, see . * *****************************************************************/ #include #include #include #include // #include #include #include #include #include #include #include struct bg_gtk_urlsel_s { GtkWidget * window; GtkWidget * add_button; GtkWidget * close_button; GtkWidget * entry; bg_gtk_plugin_menu_t * plugins; void (*add_files)(char ** files, const char * plugin, int prefer_edl, void * data); void (*close_notify)(bg_gtk_urlsel_t * f, void * data); void * callback_data; int is_modal; }; static void button_callback(GtkWidget * w, gpointer data) { bg_gtk_urlsel_t * f; const char * plugin = NULL; char * urls[2]; f = (bg_gtk_urlsel_t *)data; if(w == f->add_button) { if(f->plugins) plugin = bg_gtk_plugin_menu_get_plugin(f->plugins); urls[0] = bg_strdup(NULL, gtk_entry_get_text(GTK_ENTRY(f->entry))); urls[1] = NULL; f->add_files(urls, plugin, 0, f->callback_data); free(urls[0]); } else if((w == f->window) || (w == f->close_button)) { if(f->close_notify) f->close_notify(f, f->callback_data); gtk_widget_hide(f->window); if(f->is_modal) gtk_main_quit(); bg_gtk_urlsel_destroy(f); } } static gboolean delete_callback(GtkWidget * w, GdkEventAny * event, gpointer data) { button_callback(w, data); return TRUE; } static gboolean destroy_callback(GtkWidget * w, GdkEvent * event, gpointer data) { button_callback(w, data); return TRUE; } bg_gtk_urlsel_t * bg_gtk_urlsel_create(const char * title, void (*add_files)(char ** files, const char * plugin, int prefer_edl, void * data), void (*close_notify)(bg_gtk_urlsel_t *, void * data), void * user_data, GtkWidget * parent_window, bg_plugin_registry_t * plugin_reg, int type_mask, int flag_mask) { bg_gtk_urlsel_t * ret; GtkWidget * box; GtkWidget * mainbox; GtkWidget * label; ret = calloc(1, sizeof(*ret)); /* Create window */ ret->window = bg_gtk_window_new(GTK_WINDOW_TOPLEVEL); gtk_window_set_title(GTK_WINDOW(ret->window), title); gtk_window_set_position(GTK_WINDOW(ret->window), GTK_WIN_POS_CENTER_ON_PARENT); gtk_container_set_border_width(GTK_CONTAINER(ret->window), 5); if(parent_window) { gtk_window_set_transient_for(GTK_WINDOW(ret->window), GTK_WINDOW(parent_window)); gtk_window_set_destroy_with_parent(GTK_WINDOW(ret->window), TRUE); g_signal_connect(G_OBJECT(ret->window), "destroy-event", G_CALLBACK(destroy_callback), ret); } /* Create entry */ ret->entry = gtk_entry_new(); gtk_widget_show(ret->entry); /* Create plugin menu */ if(plugin_reg) ret->plugins = bg_gtk_plugin_menu_create(1, plugin_reg, type_mask, flag_mask); /* Create Buttons */ ret->add_button = gtk_button_new_from_stock(GTK_STOCK_ADD); ret->close_button = gtk_button_new_from_stock(GTK_STOCK_CLOSE); bg_gtk_widget_set_can_default(ret->close_button, TRUE); bg_gtk_widget_set_can_default(ret->add_button, TRUE); /* Set callbacks */ g_signal_connect(G_OBJECT(ret->window), "delete-event", G_CALLBACK(delete_callback), ret); g_signal_connect(G_OBJECT(ret->add_button), "clicked", G_CALLBACK(button_callback), ret); g_signal_connect(G_OBJECT(ret->close_button), "clicked", G_CALLBACK(button_callback), ret); /* Show Buttons */ gtk_widget_show(ret->add_button); gtk_widget_show(ret->close_button); /* Pack everything */ mainbox = gtk_vbox_new(0, 5); box = gtk_hbox_new(0, 5); label = gtk_label_new(TR("URL:")); gtk_widget_show(label); gtk_box_pack_start(GTK_BOX(box), label, FALSE, FALSE, 0); bg_gtk_box_pack_start_defaults(GTK_BOX(box), ret->entry); gtk_widget_show(box); bg_gtk_box_pack_start_defaults(GTK_BOX(mainbox), box); if(ret->plugins) bg_gtk_box_pack_start_defaults(GTK_BOX(mainbox), bg_gtk_plugin_menu_get_widget(ret->plugins)); box = gtk_hbutton_box_new(); gtk_box_set_spacing(GTK_BOX(box), 5); gtk_container_add(GTK_CONTAINER(box), ret->close_button); gtk_container_add(GTK_CONTAINER(box), ret->add_button); gtk_widget_show(box); bg_gtk_box_pack_start_defaults(GTK_BOX(mainbox), box); gtk_widget_show(mainbox); gtk_container_add(GTK_CONTAINER(ret->window), mainbox); /* Set pointers */ ret->add_files = add_files; ret->close_notify = close_notify; ret->callback_data = user_data; return ret; } /* Destroy urlselector */ void bg_gtk_urlsel_destroy(bg_gtk_urlsel_t * urlsel) { // g_object_unref(G_OBJECT(urlsel)); free(urlsel); } /* Show the window */ void bg_gtk_urlsel_run(bg_gtk_urlsel_t * urlsel, int modal, GtkWidget * parent) { parent = bg_gtk_get_toplevel(parent); if(parent) gtk_window_set_transient_for(GTK_WINDOW(urlsel->window), GTK_WINDOW(parent)); gtk_window_set_modal(GTK_WINDOW(urlsel->window), modal); gtk_widget_show(urlsel->window); gtk_widget_grab_default(urlsel->close_button); gtk_widget_grab_focus(urlsel->close_button); urlsel->is_modal = modal; if(modal) gtk_main(); } gmerlin-1.2.0~dfsg/lib/gtk/question.c0000644000175000017500000001065611764363406017461 0ustar alessioalessio/***************************************************************** * gmerlin - a general purpose multimedia framework and applications * * Copyright (c) 2001 - 2011 Members of the Gmerlin project * gmerlin-general@lists.sourceforge.net * http://gmerlin.sourceforge.net * * 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 of the License, 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 this program. If not, see . * *****************************************************************/ #include #include #include #include #include #include typedef struct { GtkWidget * window; GtkWidget * ok_button; GtkWidget * cancel_button; int answer; } question_t; static void button_callback(GtkWidget * w, gpointer * data) { question_t * q = (question_t*)data; if(w == q->ok_button) q->answer = 1; else q->answer = 0; gtk_widget_hide(q->window); gtk_main_quit(); } static gboolean delete_callback(GtkWidget * w, GdkEventAny * evt, gpointer data) { button_callback(w, data); return TRUE; } int bg_gtk_question(const char * question, GtkWidget * parent) { GtkWidget * buttonbox; int ret; question_t * q; GtkWidget * label; GtkWidget * mainbox; GtkWidget * hbox; GtkWidget * image; q = calloc(1, sizeof(*q)); /* Create objects */ q->window = bg_gtk_window_new(GTK_WINDOW_TOPLEVEL); gtk_window_set_position(GTK_WINDOW(q->window), GTK_WIN_POS_CENTER_ON_PARENT); q->ok_button = gtk_button_new_from_stock(GTK_STOCK_OK); q->cancel_button = gtk_button_new_from_stock(GTK_STOCK_CANCEL); label = gtk_label_new(question); image = gtk_image_new_from_stock(GTK_STOCK_DIALOG_QUESTION, GTK_ICON_SIZE_DIALOG); /* Set attributes */ parent = bg_gtk_get_toplevel(parent); if(parent) gtk_window_set_transient_for(GTK_WINDOW(q->window), GTK_WINDOW(parent)); gtk_window_set_modal(GTK_WINDOW(q->window), 1); gtk_window_set_title(GTK_WINDOW(q->window), TR("Question")); gtk_window_set_position(GTK_WINDOW(q->window), GTK_WIN_POS_CENTER_ON_PARENT); bg_gtk_widget_set_can_default(q->ok_button, TRUE); bg_gtk_widget_set_can_default(q->cancel_button, TRUE); gtk_label_set_justify(GTK_LABEL(label), GTK_JUSTIFY_CENTER); /* Set callbacks */ g_signal_connect(G_OBJECT(q->ok_button), "clicked", G_CALLBACK(button_callback), (gpointer)q); g_signal_connect(G_OBJECT(q->cancel_button), "clicked", G_CALLBACK(button_callback), (gpointer)q); g_signal_connect(G_OBJECT(q->window), "delete_event", G_CALLBACK(delete_callback), (gpointer)q); /* Show everything */ gtk_widget_show(label); gtk_widget_show(image); gtk_widget_show(q->ok_button); gtk_widget_show(q->cancel_button); /* Pack the objects */ mainbox = gtk_vbox_new(0, 5); hbox = gtk_hbox_new(0, 5); gtk_container_set_border_width(GTK_CONTAINER(mainbox), 5); bg_gtk_box_pack_start_defaults(GTK_BOX(hbox), image); bg_gtk_box_pack_start_defaults(GTK_BOX(hbox), label); gtk_widget_show(hbox); bg_gtk_box_pack_start_defaults(GTK_BOX(mainbox), hbox); buttonbox = gtk_hbutton_box_new(); gtk_box_set_spacing(GTK_BOX(buttonbox), 10); gtk_container_add(GTK_CONTAINER(buttonbox), q->ok_button); gtk_container_add(GTK_CONTAINER(buttonbox), q->cancel_button); gtk_widget_show(buttonbox); bg_gtk_box_pack_start_defaults(GTK_BOX(mainbox), buttonbox); gtk_widget_show(mainbox); gtk_container_add(GTK_CONTAINER(q->window), mainbox); gtk_widget_show(q->window); gtk_widget_grab_default(q->cancel_button); gtk_main(); /* Window has gone, fetch the answer */ ret = q->answer; /* Destroy everything */ // gtk_widget_hide(q->window); gtk_widget_destroy(q->window); free(q); return ret; } gmerlin-1.2.0~dfsg/lib/gtk/cfg_slider.c0000644000175000017500000001360411764363406017707 0ustar alessioalessio/***************************************************************** * gmerlin - a general purpose multimedia framework and applications * * Copyright (c) 2001 - 2011 Members of the Gmerlin project * gmerlin-general@lists.sourceforge.net * http://gmerlin.sourceforge.net * * 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 of the License, 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 this program. If not, see . * *****************************************************************/ #include #include "gtk_dialog.h" #include typedef struct { GtkWidget * label; GtkWidget * slider; } slider_t; /* typedef enum { GTK_EXPAND = 1 << 0, GTK_SHRINK = 1 << 1, GTK_FILL = 1 << 2 } GtkAttachOptions; */ static void destroy(bg_gtk_widget_t * w) { slider_t * priv = (slider_t*)(w->priv); free(priv); } static void get_value_int(bg_gtk_widget_t * w) { slider_t * priv; priv = (slider_t*)(w->priv); gtk_range_set_value(GTK_RANGE(priv->slider), (gdouble)w->value.val_i); } static void set_value_int(bg_gtk_widget_t * w) { slider_t * priv; priv = (slider_t*)(w->priv); w->value.val_i = (int)(gtk_range_get_value(GTK_RANGE(priv->slider))); } static void get_value_float(bg_gtk_widget_t * w) { slider_t * priv; priv = (slider_t*)(w->priv); gtk_range_set_value(GTK_RANGE(priv->slider), (gdouble)w->value.val_f); } static void set_value_float(bg_gtk_widget_t * w) { slider_t * priv; priv = (slider_t*)(w->priv); w->value.val_f = gtk_range_get_value(GTK_RANGE(priv->slider)); } static gboolean button_callback(GtkWidget * wid, GdkEventButton * evt, gpointer data) { bg_gtk_widget_t * w; slider_t * priv; w = (bg_gtk_widget_t*)data; priv = (slider_t*)(w->priv); if(evt->type == GDK_2BUTTON_PRESS) { if(w->info->type == BG_PARAMETER_SLIDER_FLOAT) { w->value.val_f = w->info->val_default.val_f; get_value_float(w); } else if(w->info->type == BG_PARAMETER_SLIDER_INT) { w->value.val_i = w->info->val_default.val_i; get_value_int(w); } return TRUE; } return FALSE; } static void attach(void * priv, GtkWidget * table, int * row, int * num_columns) { slider_t * s = (slider_t*)priv; if(*num_columns < 2) *num_columns = 2; gtk_table_resize(GTK_TABLE(table), *row + 1, *num_columns); gtk_table_attach(GTK_TABLE(table), s->label, 0, 1, *row, *row+1, GTK_FILL, GTK_SHRINK, 0, 0); gtk_table_attach(GTK_TABLE(table), s->slider, 1, 2, *row, *row+1, GTK_FILL | GTK_EXPAND, GTK_SHRINK, 0, 0); *row += 1; } static const gtk_widget_funcs_t int_funcs = { .get_value = get_value_int, .set_value = set_value_int, .destroy = destroy, .attach = attach }; static const gtk_widget_funcs_t float_funcs = { .get_value = get_value_float, .set_value = set_value_float, .destroy = destroy, .attach = attach }; static void create_common(bg_gtk_widget_t * w, const bg_parameter_info_t * info, float min_value, float max_value, const char * translation_domain) { float step; slider_t * s = calloc(1, sizeof(*s)); int i; s->label = gtk_label_new(TR_DOM(info->long_name)); step = 1.0; for(i = 0; i < info->num_digits; i++) step /= 10.0; gtk_misc_set_alignment(GTK_MISC(s->label), 0.0, 0.5); gtk_widget_show(s->label); s->slider = gtk_hscale_new_with_range(min_value, max_value, step); if(info->help_string) { bg_gtk_tooltips_set_tip(s->slider, info->help_string, translation_domain); } if(info->flags & BG_PARAMETER_SYNC) { w->callback_id = g_signal_connect(G_OBJECT(s->slider), "value-changed", G_CALLBACK(bg_gtk_change_callback), (gpointer)w); w->callback_widget = s->slider; } gtk_scale_set_value_pos(GTK_SCALE(s->slider), GTK_POS_LEFT); gtk_widget_set_events(s->slider, GDK_BUTTON_PRESS_MASK); g_signal_connect(G_OBJECT(s->slider), "button-press-event", G_CALLBACK(button_callback), (gpointer)w); gtk_widget_show(s->slider); gtk_widget_show(s->label); w->priv = s; } void bg_gtk_create_slider_int(bg_gtk_widget_t * w, const char * translation_domain) { float min_value; float max_value; slider_t * s; min_value = (float)(w->info->val_min.val_i); max_value = (float)(w->info->val_max.val_i); if(min_value >= max_value) { min_value = 0.0; max_value = 100000.0; } create_common(w, w->info, min_value, max_value, translation_domain); s = (slider_t *)(w->priv); w->funcs = &int_funcs; gtk_scale_set_digits(GTK_SCALE(s->slider), 0); } void bg_gtk_create_slider_float(bg_gtk_widget_t * w, const char * translation_domain) { float min_value; float max_value; slider_t * s; min_value = (float)(w->info->val_min.val_f); max_value = (float)(w->info->val_max.val_f); if(min_value >= max_value) { min_value = 0.0; max_value = 100000.0; } create_common(w, w->info, min_value, max_value, translation_domain); s = (slider_t *)(w->priv); gtk_scale_set_digits(GTK_SCALE(s->slider), w->info->num_digits); w->funcs = &float_funcs; } gmerlin-1.2.0~dfsg/lib/gtk/cfg_file.c0000644000175000017500000000706111764363406017344 0ustar alessioalessio/***************************************************************** * gmerlin - a general purpose multimedia framework and applications * * Copyright (c) 2001 - 2011 Members of the Gmerlin project * gmerlin-general@lists.sourceforge.net * http://gmerlin.sourceforge.net * * 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 of the License, 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 this program. If not, see . * *****************************************************************/ #include #include #include "gtk_dialog.h" #include #include typedef struct { bg_gtk_file_entry_t * fe; GtkWidget * label; } file_t; static void get_value(bg_gtk_widget_t * w) { file_t * priv; priv = (file_t*)(w->priv); if(!w->value.val_str || (*w->value.val_str == '\0')) { bg_gtk_file_entry_set_filename(priv->fe, ""); return; } bg_gtk_file_entry_set_filename(priv->fe, w->value.val_str); } static void set_value(bg_gtk_widget_t * w) { file_t * priv; const char * filename; priv = (file_t*)(w->priv); filename = bg_gtk_file_entry_get_filename(priv->fe); if(w->value.val_str) { free(w->value.val_str); w->value.val_str = NULL; } if(*filename != '\0') { w->value.val_str = malloc(strlen(filename)+1); strcpy(w->value.val_str, filename); } } static void destroy(bg_gtk_widget_t * w) { file_t * priv = (file_t*)w->priv; bg_gtk_file_entry_destroy(priv->fe); free(priv); } static void attach(void * priv, GtkWidget * table, int * row, int * num_columns) { file_t * f = (file_t*)priv; if(*num_columns < 3) *num_columns = 3; gtk_table_resize(GTK_TABLE(table), *row+1, *num_columns); gtk_table_attach(GTK_TABLE(table), f->label, 0, 1, *row, *row+1, GTK_FILL, GTK_FILL, 0, 0); gtk_table_attach(GTK_TABLE(table), bg_gtk_file_entry_get_entry(f->fe), 1, 2, *row, *row+1, GTK_FILL | GTK_EXPAND, GTK_SHRINK, 0, 0); gtk_table_attach(GTK_TABLE(table), bg_gtk_file_entry_get_button(f->fe), 2, 3, *row, *row+1, GTK_FILL, GTK_SHRINK, 0, 0); (*row)++; } static const gtk_widget_funcs_t funcs = { .get_value = get_value, .set_value = set_value, .destroy = destroy, .attach = attach }; void bg_gtk_create_file(bg_gtk_widget_t * w, const char * translation_domain) { file_t * priv = calloc(1, sizeof(*priv)); priv->fe = bg_gtk_file_entry_create((w->info->type == BG_PARAMETER_DIRECTORY) ? 1 : 0, NULL, NULL, w->info->help_string, translation_domain); priv->label = gtk_label_new(TR_DOM(w->info->long_name)); gtk_misc_set_alignment(GTK_MISC(priv->label), 0.0, 0.5); gtk_widget_show(priv->label); w->funcs = &funcs; w->priv = priv; } void bg_gtk_create_directory(bg_gtk_widget_t * w, const char * translation_domain) { bg_gtk_create_file(w, translation_domain); } gmerlin-1.2.0~dfsg/lib/gtk/display.c0000644000175000017500000002612211764363406017252 0ustar alessioalessio/***************************************************************** * gmerlin - a general purpose multimedia framework and applications * * Copyright (c) 2001 - 2011 Members of the Gmerlin project * gmerlin-general@lists.sourceforge.net * http://gmerlin.sourceforge.net * * 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 of the License, 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 this program. If not, see . * *****************************************************************/ #include #include #include #include #include #include #include #include #include #include #define MAX_CHARS GAVL_TIME_STRING_LEN_MS // 15 #define DIGIT_0 0 #define DIGIT_1 1 #define DIGIT_2 2 #define DIGIT_3 3 #define DIGIT_4 4 #define DIGIT_5 5 #define DIGIT_6 6 #define DIGIT_7 7 #define DIGIT_8 8 #define DIGIT_9 9 #define DIGIT_COLON 10 #define DIGIT_MINUS 11 #define DIGIT_DOT 12 #define NUM_PIXBUFS 13 static int num_time_displays = 0; static GdkPixbuf * digit_pixbufs[NUM_PIXBUFS]; static void load_pixbufs() { char * c_tmp1 = NULL; char * c_tmp2 = NULL; int i; if(num_time_displays) { num_time_displays++; return; } num_time_displays++; for(i = 0; i < 10; i++) { c_tmp1 = bg_sprintf("digit_%d.png", i); c_tmp2 = bg_search_file_read("icons", c_tmp1); digit_pixbufs[i] = gdk_pixbuf_new_from_file(c_tmp2, NULL); free(c_tmp1); free(c_tmp2); } c_tmp2 = bg_search_file_read("icons", "digit_colon.png"); digit_pixbufs[DIGIT_COLON] = gdk_pixbuf_new_from_file(c_tmp2, NULL); free(c_tmp2); c_tmp2 = bg_search_file_read("icons", "digit_minus.png"); digit_pixbufs[DIGIT_MINUS] = gdk_pixbuf_new_from_file(c_tmp2, NULL); free(c_tmp2); c_tmp2 = bg_search_file_read("icons", "digit_dot.png"); digit_pixbufs[DIGIT_DOT] = gdk_pixbuf_new_from_file(c_tmp2, NULL); free(c_tmp2); } static void unload_pixbufs() { int i; num_time_displays--; if(!num_time_displays) { for(i = 0; i < NUM_PIXBUFS; i++) { g_object_unref(digit_pixbufs[i]); digit_pixbufs[i] = NULL; } } } struct bg_gtk_time_display_s { GdkPixbuf * pixbufs[NUM_PIXBUFS]; float foreground_color[3]; float background_color[3]; int height; int digit_width; int colon_width; GtkWidget * widget; int indices[MAX_CHARS]; GdkGC * gc; int type_mask; int max_width; int border_width; }; static void set_bg_color(bg_gtk_time_display_t * d) { GdkColor bg; if(!d->gc) return; bg.red = (guint16)(d->background_color[0]*65535.0); bg.green = (guint16)(d->background_color[1]*65535.0); bg.blue = (guint16)(d->background_color[2]*65535.0); bg.pixel = (bg.red >> 8) << 16 | (bg.green >> 8) << 8 | (bg.blue >> 8); gdk_color_alloc(gdk_window_get_colormap(d->widget->window), &bg); gtk_widget_modify_bg(d->widget, GTK_STATE_NORMAL, &bg); gdk_gc_set_foreground(d->gc, &bg); } static void create_pixmaps(bg_gtk_time_display_t * d) { int i; for(i = 0; i < NUM_PIXBUFS; i++) { if(d->pixbufs[i]) { g_object_unref(G_OBJECT(d->pixbufs[i])); d->pixbufs[i] = NULL; } } /* Scale down the pixmaps */ for(i = 0; i < 10; i++) { d->pixbufs[i] = bg_gtk_pixbuf_scale_alpha(digit_pixbufs[i], d->digit_width, d->height, d->foreground_color, d->background_color); } d->pixbufs[DIGIT_COLON] = bg_gtk_pixbuf_scale_alpha(digit_pixbufs[DIGIT_COLON], d->colon_width, d->height, d->foreground_color, d->background_color); d->pixbufs[DIGIT_MINUS] = bg_gtk_pixbuf_scale_alpha(digit_pixbufs[DIGIT_MINUS], d->digit_width, d->height, d->foreground_color, d->background_color); if(d->type_mask & BG_GTK_DISPLAY_MODE_HMSMS) { d->pixbufs[DIGIT_DOT] = bg_gtk_pixbuf_scale_alpha(digit_pixbufs[DIGIT_DOT], d->colon_width, d->height, d->foreground_color, d->background_color); } } static gboolean expose_callback(GtkWidget * w, GdkEventExpose * evt, gpointer data) { int pos_i; bg_gtk_time_display_t * d; int x; d = (bg_gtk_time_display_t *)data; if(!d->widget->window) return TRUE; pos_i = 0; x = d->max_width - d->border_width; while((d->indices[pos_i] >= 0) && (pos_i < MAX_CHARS)) { if((d->indices[pos_i] == DIGIT_COLON) || (d->indices[pos_i] == DIGIT_DOT)) { x -= d->colon_width; gdk_draw_pixbuf(d->widget->window, NULL, d->pixbufs[d->indices[pos_i]], 0, // gint src_x, 0, // gint src_y, x, d->border_width, d->colon_width, d->height, GDK_RGB_DITHER_NONE, 0, 0); } else { x -= d->digit_width; gdk_draw_pixbuf(d->widget->window, NULL, d->pixbufs[d->indices[pos_i]], 0, // gint src_x, 0, // gint src_y, x, d->border_width, d->digit_width, d->height, GDK_RGB_DITHER_NONE, 0, 0); } pos_i++; } if(x) gdk_draw_rectangle(d->widget->window, d->gc, TRUE, 0, 0, x, d->height + 2 * d->border_width); return TRUE; } static void realize_callback(GtkWidget * w, gpointer data) { bg_gtk_time_display_t * d; d = (bg_gtk_time_display_t *)data; d->gc = gdk_gc_new(d->widget->window); set_bg_color(d); } void bg_gtk_time_display_set_colors(bg_gtk_time_display_t * d, float * foreground, float * background) { memcpy(d->foreground_color, foreground, 3 * sizeof(float)); memcpy(d->background_color, background, 3 * sizeof(float)); create_pixmaps(d); set_bg_color(d); expose_callback(d->widget, NULL, d); } void bg_gtk_time_display_update(bg_gtk_time_display_t * d, int64_t time, int mode) { char * pos; char buf[MAX_CHARS]; int pos_i; switch(mode) { case BG_GTK_DISPLAY_MODE_HMS: gavl_time_prettyprint(time, buf); break; case BG_GTK_DISPLAY_MODE_HMSMS: gavl_time_prettyprint_ms(time, buf); break; case BG_GTK_DISPLAY_MODE_TIMECODE: gavl_timecode_prettyprint_short(time, buf); break; case BG_GTK_DISPLAY_MODE_FRAMECOUNT: sprintf(buf, "%"PRId64, time); break; } pos = &buf[strlen(buf)]; pos_i = 0; do{ pos--; if(*pos == ':') d->indices[pos_i] = DIGIT_COLON; else if(*pos == '-') d->indices[pos_i] = DIGIT_MINUS; else if(*pos == '.') d->indices[pos_i] = DIGIT_DOT; else if(isdigit(*pos)) d->indices[pos_i] = (int)(*pos) - (int)('0'); pos_i++; } while(pos != buf); while(pos_i < MAX_CHARS) { d->indices[pos_i] = -1; pos_i++; } expose_callback(d->widget, NULL, d); } bg_gtk_time_display_t * bg_gtk_time_display_create(BG_GTK_DISPLAY_SIZE size, int border_width, int type_mask) { bg_gtk_time_display_t * ret; load_pixbufs(); ret = calloc(1, sizeof(*ret)); ret->border_width = border_width; ret->type_mask = type_mask; switch(size) { case BG_GTK_DISPLAY_SIZE_HUGE: /* 480 x 96, 1/1 */ ret->height = 96; ret->digit_width = 60; ret->colon_width = 30; break; case BG_GTK_DISPLAY_SIZE_LARGE: /* 240 x 48, 1/2 */ ret->height = 48; ret->digit_width = 30; ret->colon_width = 15; break; case BG_GTK_DISPLAY_SIZE_NORMAL: /* 160 x 32 1/3 */ ret->height = 32; ret->digit_width = 20; ret->colon_width = 10; break; case BG_GTK_DISPLAY_SIZE_SMALL: /* 80 x 16 1/6 */ ret->height = 16; ret->digit_width = 10; ret->colon_width = 5; break; } ret->foreground_color[0] = 0.0; ret->foreground_color[1] = 1.0; ret->foreground_color[2] = 0.0; ret->background_color[0] = 0.0; ret->background_color[1] = 0.0; ret->background_color[2] = 0.0; create_pixmaps(ret); ret->widget = gtk_drawing_area_new(); g_signal_connect(G_OBJECT(ret->widget), "expose_event", G_CALLBACK(expose_callback), (gpointer)ret); gtk_widget_set_events(ret->widget, GDK_EXPOSURE_MASK | GDK_ENTER_NOTIFY_MASK | GDK_LEAVE_NOTIFY_MASK); g_signal_connect(G_OBJECT(ret->widget), "realize", G_CALLBACK(realize_callback), (gpointer)ret); ret->max_width = 2 * ret->border_width; if(ret->type_mask & BG_GTK_DISPLAY_MODE_HMSMS) { // -000:00:00.000 ret->max_width += 3 * ret->colon_width + 10 * ret->digit_width; } else if(ret->type_mask & BG_GTK_DISPLAY_MODE_TIMECODE) { // -00:00:00:00 ret->max_width += 3 * ret->colon_width + 9 * ret->digit_width; } else { // -000:00:00 ret->max_width += 2 * ret->colon_width + 7 * ret->digit_width; } gtk_widget_set_size_request(ret->widget, ret->max_width, 2 * ret->border_width + ret->height); gtk_widget_show(ret->widget); return ret; } GtkWidget * bg_gtk_time_display_get_widget(bg_gtk_time_display_t * d) { return d->widget; } void bg_gtk_time_display_destroy(bg_gtk_time_display_t * d) { int i; if(d->gc) g_object_unref(d->gc); for(i = 0; i < NUM_PIXBUFS; i++) { if(d->pixbufs[i]) g_object_unref(d->pixbufs[i]); } free(d); unload_pixbufs(); } gmerlin-1.2.0~dfsg/lib/gtk/vumeter.c0000644000175000017500000005722611764363406017305 0ustar alessioalessio/***************************************************************** * gmerlin - a general purpose multimedia framework and applications * * Copyright (c) 2001 - 2011 Members of the Gmerlin project * gmerlin-general@lists.sourceforge.net * http://gmerlin.sourceforge.net * * 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 of the License, 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 this program. If not, see . * *****************************************************************/ #include #include #include #include #include #include #include #include #include #include /* Some constants */ #define TIC_LENGTH 7 #define METER_WIDTH 14 static const struct { float val; char * label; } scale_tics[] = { { -60.0, "60"}, { -50.0, "50"}, { -40.0, "40"}, { -30.0, "30"}, { -20.0, "20"}, { -10.0, "10"}, { -6.0, "6"}, { -3.0, "3"}, { -1.0, "1"}, { 0.0, "0"}, }; #define NUM_TICS sizeof(scale_tics)/sizeof(scale_tics[0]) #define LEVEL_MIN (float)(scale_tics[0].val) #define LEVEL_MAX (float)(scale_tics[NUM_TICS-1].val) /* Yellow color will be at the -6 dB mark */ #define YELLOW_LEVEL(len) (len*2)/3 struct bg_gtk_vumeter_s { GtkWidget * layout; gavl_peak_detector_t * pd; struct { GtkWidget * l; GdkRectangle coords; } labels[NUM_TICS]; GdkPixbuf * pixbuf_on; GdkPixbuf * pixbuf_off; GdkGC * gc; int width; int height; int min_width; int min_height; int pixmap_width, pixmap_height; int num_channels; int vertical; pthread_mutex_t analysis_mutex; /* Analysis stuff, level values are in dB */ struct { float level; float peak; int64_t peak_age; GdkRectangle coords; GdkPixmap * pixmap; } meters[GAVL_MAX_CHANNELS]; int max_peak_age; int redraw_pixbufs; int pixmaps_valid; }; /* Golor functions */ static void get_color_on(int i, int len, uint8_t * color) { int yellow_level = YELLOW_LEVEL(len); if(i < yellow_level) { /* Green -> Yellow */ color[0] = (i * 0xff)/yellow_level; // Red color[1] = 0xff; // Green color[2] = 0x00; // Blue } else { /* Yellow -> Red */ color[0] = 0xff; // Red color[1] = ((len - i) * 0xff)/(len - yellow_level); // Green color[2] = 0x00; // Blue } } static void get_color_off(int i, int len, uint8_t * color) { get_color_on(i, len, color); color[0] >>= 1; color[1] >>= 1; color[2] >>= 1; } static float level_2_dB(float level) { float ret; if(level == 0.0) return LEVEL_MIN; ret = log10(level) * 20; if(ret > LEVEL_MAX) ret = LEVEL_MAX; if(ret < LEVEL_MIN) ret = LEVEL_MIN; return ret; } static void set_coords_horizontal(bg_gtk_vumeter_t * m, int *min_width, int *min_height) { int i; int meter_height; int max_label_w = 0; int max_label_h = 0; int total_width = 0; /* Get maximum size of the labels */ for(i = 0; i < NUM_TICS; i++) { if(m->labels[i].coords.width > max_label_w) max_label_w = m->labels[i].coords.width; if(m->labels[i].coords.height > max_label_h) max_label_h = m->labels[i].coords.height; total_width += m->labels[i].coords.width; // gtk_layout_move(GTK_LAYOUT(m->layout), m->labels[i].l, 100, 100); } /* Calculate meter coordinates */ meter_height = (m->height - m->num_channels * TIC_LENGTH - max_label_h)/m->num_channels; for(i = 0; i < m->num_channels; i++) { m->meters[i].coords.x = m->labels[i].coords.width / 2; m->meters[i].coords.width = m->width - m->labels[NUM_TICS-1].coords.width / 2 - m->labels[i].coords.width / 2; } for(i = 0; i < m->num_channels; i++) { m->meters[i].coords.y = TIC_LENGTH + max_label_h + i * (meter_height + TIC_LENGTH); m->meters[i].coords.height = meter_height; } *min_width = NUM_TICS * max_label_w + (NUM_TICS-1) * 5; *min_height = max_label_h + m->num_channels * (TIC_LENGTH + 10); } static void set_coords_vertical(bg_gtk_vumeter_t * m, int *min_width, int *min_height) { int i; int meter_width; int max_label_w = 0; int max_label_h = 0; int total_height = 0; /* Get maximum size of the labels */ for(i = 0; i < NUM_TICS; i++) { if(m->labels[i].coords.width > max_label_w) max_label_w = m->labels[i].coords.width; if(m->labels[i].coords.height > max_label_h) max_label_h = m->labels[i].coords.height; total_height += m->labels[i].coords.height; // gtk_layout_move(GTK_LAYOUT(m->layout), m->labels[i].l, 100, 100); } /* Calculate meter coordinates */ meter_width = (m->width - m->num_channels * TIC_LENGTH - max_label_w)/m->num_channels; for(i = 0; i < m->num_channels; i++) { m->meters[i].coords.y = m->labels[i].coords.height / 2; m->meters[i].coords.height = m->height - m->labels[NUM_TICS-1].coords.height / 2 - m->labels[i].coords.height / 2; } for(i = 0; i < m->num_channels; i++) { m->meters[i].coords.x = TIC_LENGTH + max_label_w + i * (meter_width + TIC_LENGTH); m->meters[i].coords.width = meter_width; } *min_height = NUM_TICS * max_label_h + (NUM_TICS-1) * 5; *min_width = max_label_w + m->num_channels * (TIC_LENGTH + 10); } static void set_coords(bg_gtk_vumeter_t * m) { int min_width, min_height; if(m->vertical) set_coords_vertical(m, &min_width, &min_height); else set_coords_horizontal(m, &min_width, &min_height); if((m->min_width != min_width) || (m->min_height != min_height)) { m->min_width = min_width; m->min_height = min_height; gtk_widget_set_size_request(m->layout, min_width, min_height); } } static void draw_static_horizontal(bg_gtk_vumeter_t * m) { int i, j; GtkStyle * style; int label_x, label_y; style = gtk_widget_get_style(m->layout); /* Print meter shadows */ for(i = 0; i < m->num_channels; i++) { gtk_paint_shadow(style, GTK_LAYOUT(m->layout)->bin_window, GTK_STATE_NORMAL, GTK_SHADOW_IN, NULL, m->layout, NULL, m->meters[i].coords.x-1, m->meters[i].coords.y-1, m->meters[i].coords.width+2, m->meters[i].coords.height+2); } label_y = 0; for(i = 0; i < NUM_TICS; i++) { label_x = m->meters[0].coords.x + (m->meters[0].coords.width * i)/(NUM_TICS-1); if((m->labels[i].coords.x != label_x - m->labels[i].coords.width/2) || (m->labels[i].coords.y != label_y)) { m->labels[i].coords.x = label_x - m->labels[i].coords.width/2; m->labels[i].coords.y = label_y; gtk_layout_move(GTK_LAYOUT(m->layout), m->labels[i].l, m->labels[i].coords.x, m->labels[i].coords.y); } for(j = 0; j < m->num_channels; j++) { gtk_paint_vline(style, GTK_LAYOUT(m->layout)->bin_window, GTK_STATE_NORMAL, NULL, m->layout, NULL, m->meters[j].coords.y - TIC_LENGTH, m->meters[j].coords.y, label_x); } } } static void draw_static_vertical(bg_gtk_vumeter_t * m) { int i, j; GtkStyle * style; int label_x, label_y; style = gtk_widget_get_style(m->layout); /* Print meter shadows */ for(i = 0; i < m->num_channels; i++) { gtk_paint_shadow(style, GTK_LAYOUT(m->layout)->bin_window, GTK_STATE_NORMAL, GTK_SHADOW_IN, NULL, m->layout, NULL, m->meters[i].coords.x-1, m->meters[i].coords.y-1, m->meters[i].coords.width+2, m->meters[i].coords.height+2); } label_x = 0; for(i = 0; i < NUM_TICS; i++) { label_y = m->meters[0].coords.y + (m->meters[0].coords.height * i)/(NUM_TICS-1); if((m->labels[i].coords.x != label_x) || (m->labels[i].coords.y != label_y - m->labels[i].coords.height/2)) { m->labels[i].coords.x = label_x; m->labels[i].coords.y = label_y - m->labels[i].coords.height/2; gtk_layout_move(GTK_LAYOUT(m->layout), m->labels[i].l, m->labels[i].coords.x, m->labels[i].coords.y); } for(j = 0; j < m->num_channels; j++) { gtk_paint_hline(style, GTK_LAYOUT(m->layout)->bin_window, GTK_STATE_NORMAL, NULL, m->layout, NULL, m->meters[j].coords.x - TIC_LENGTH, m->meters[j].coords.x, label_y); } } } static void draw_static(bg_gtk_vumeter_t * m) { if(m->vertical) draw_static_vertical(m); else draw_static_horizontal(m); } static int interpolate_tics(float val, int len) { int i; int pos_1, pos_2; if(val <= scale_tics[0].val) return 0; if(val >= scale_tics[NUM_TICS-1].val) return len; for(i = 1; i < NUM_TICS; i++) { if(scale_tics[i].val > val) { pos_1 = (len * (i-1)) / (NUM_TICS-1); pos_2 = (len * i) / (NUM_TICS-1); return pos_1 + (int)((pos_2 - pos_1) * (val - scale_tics[i-1].val)/ (scale_tics[i].val - scale_tics[i-1].val)+0.5); } } return 0; } static int level_2_pos_horizontal(bg_gtk_vumeter_t * m, float level) { return interpolate_tics(level_2_dB(level), m->meters[0].coords.width); } static int level_2_pos_vertical(bg_gtk_vumeter_t * m, float level) { return interpolate_tics(level_2_dB(level), m->meters[0].coords.height); } static void draw_pixbufs_horizontal(bg_gtk_vumeter_t * m) { int i, j; uint8_t on_color[3]; uint8_t off_color[3]; uint8_t * on_pixels; uint8_t * off_pixels; uint8_t * on_ptr; uint8_t * off_ptr; int on_stride, off_stride; on_pixels = gdk_pixbuf_get_pixels(m->pixbuf_on); off_pixels = gdk_pixbuf_get_pixels(m->pixbuf_off); on_stride = gdk_pixbuf_get_rowstride(m->pixbuf_on); off_stride = gdk_pixbuf_get_rowstride(m->pixbuf_off); for(i = 0; i < m->meters[0].coords.width; i++) { get_color_on(i, m->meters[0].coords.width, on_color); get_color_off(i, m->meters[0].coords.width, off_color); on_ptr = on_pixels + 3 * i; off_ptr = off_pixels + 3 * i; for(j = 0; j < m->meters[0].coords.height; j++) { on_ptr[0] = on_color[0]; on_ptr[1] = on_color[1]; on_ptr[2] = on_color[2]; off_ptr[0] = off_color[0]; off_ptr[1] = off_color[1]; off_ptr[2] = off_color[2]; on_ptr += on_stride; off_ptr += on_stride; } } } static void draw_pixbufs_vertical(bg_gtk_vumeter_t * m) { int i, j; uint8_t on_color[3]; uint8_t off_color[3]; uint8_t * on_pixels; uint8_t * off_pixels; uint8_t * on_ptr; uint8_t * off_ptr; int on_stride, off_stride; on_pixels = gdk_pixbuf_get_pixels(m->pixbuf_on); off_pixels = gdk_pixbuf_get_pixels(m->pixbuf_off); on_stride = gdk_pixbuf_get_rowstride(m->pixbuf_on); off_stride = gdk_pixbuf_get_rowstride(m->pixbuf_off); for(i = 0; i < m->meters[0].coords.height; i++) { get_color_on(m->meters[0].coords.height - 1 - i, m->meters[0].coords.height, on_color); get_color_off(m->meters[0].coords.height - 1 - i, m->meters[0].coords.height, off_color); on_ptr = on_pixels + on_stride * i; off_ptr = off_pixels + on_stride * i; for(j = 0; j < m->meters[0].coords.width; j++) { on_ptr[0] = on_color[0]; on_ptr[1] = on_color[1]; on_ptr[2] = on_color[2]; off_ptr[0] = off_color[0]; off_ptr[1] = off_color[1]; off_ptr[2] = off_color[2]; on_ptr += 3; off_ptr += 3; } } } static void update_pixmap_horizontal(bg_gtk_vumeter_t * m, int channel) { int level_pos, peak_pos; level_pos = level_2_pos_horizontal(m, m->meters[channel].level); peak_pos = level_2_pos_horizontal(m, m->meters[channel].peak); if(level_pos) { gdk_draw_pixbuf(m->meters[channel].pixmap, m->gc, m->pixbuf_on, 0, /* gint src_x */ 0, /* gint src_y */ 0, /* gint dest_x */ 0, /* gint dest_y */ level_pos, /* gint width */ m->meters[channel].coords.height, /* gint height */ GDK_RGB_DITHER_NONE, 0, 0); } gdk_draw_pixbuf(m->meters[channel].pixmap, m->gc, m->pixbuf_off, level_pos, /* gint src_x */ 0, /* gint src_y */ level_pos, /* gint dest_x */ 0, /* gint dest_y */ m->meters[channel].coords.width - level_pos, /* gint width */ m->meters[channel].coords.height, /* gint height */ GDK_RGB_DITHER_NONE, 0, 0); if(peak_pos + 2 >= m->meters[channel].coords.width) peak_pos = m->meters[channel].coords.width - 2; if(peak_pos) { gdk_draw_pixbuf(m->meters[channel].pixmap, m->gc, m->pixbuf_on, peak_pos, /* gint src_x */ 0, /* gint src_y */ peak_pos, /* gint dest_x */ 0, /* gint dest_y */ 2, /* gint width */ m->meters[channel].coords.height, /* gint height */ GDK_RGB_DITHER_NONE, 0, 0); } } static void update_pixmap_vertical(bg_gtk_vumeter_t * m, int channel) { int level_pos, peak_pos; level_pos = level_2_pos_vertical(m, m->meters[channel].level); peak_pos = level_2_pos_vertical(m, m->meters[channel].peak); #if 1 if(level_pos) { gdk_draw_pixbuf(m->meters[channel].pixmap, m->gc, m->pixbuf_on, 0, /* gint src_x */ m->meters[channel].coords.height - level_pos, /* gint src_y */ 0, /* gint dest_x */ m->meters[channel].coords.height - level_pos, /* gint dest_y */ m->meters[channel].coords.width, /* gint width */ level_pos, /* gint height */ GDK_RGB_DITHER_NONE, 0, 0); } #endif gdk_draw_pixbuf(m->meters[channel].pixmap, m->gc, m->pixbuf_off, 0, /* gint src_x */ 0, /* gint src_y */ 0, /* gint dest_x */ 0, /* gint dest_y */ m->meters[channel].coords.width, /* gint width */ m->meters[channel].coords.height - level_pos, /* gint height */ GDK_RGB_DITHER_NONE, 0, 0); #if 1 if(peak_pos + 2 >= m->meters[channel].coords.height) peak_pos = m->meters[channel].coords.height - 2; if(peak_pos) { gdk_draw_pixbuf(m->meters[channel].pixmap, m->gc, m->pixbuf_on, 0, /* gint src_x */ m->meters[channel].coords.height - peak_pos, /* gint src_y */ 0, /* gint dest_x */ m->meters[channel].coords.height - peak_pos, /* gint dest_y */ m->meters[channel].coords.width, /* gint width */ 2, /* gint height */ GDK_RGB_DITHER_NONE, 0, 0); } #endif } static void update_pixmaps(bg_gtk_vumeter_t * m) { int i; if(!m->gc) m->gc = gdk_gc_new(GTK_LAYOUT(m->layout)->bin_window); if(!m->pixbuf_on) { m->pixbuf_on = gdk_pixbuf_new(GDK_COLORSPACE_RGB, 0, 8, m->pixmap_width, m->pixmap_height); m->pixbuf_off = gdk_pixbuf_new(GDK_COLORSPACE_RGB, 0, 8, m->pixmap_width, m->pixmap_height); if(m->vertical) draw_pixbufs_vertical(m); else draw_pixbufs_horizontal(m); m->redraw_pixbufs = 0; } else if(m->redraw_pixbufs) { if(m->vertical) draw_pixbufs_vertical(m); else draw_pixbufs_horizontal(m); m->redraw_pixbufs = 0; } for(i = 0; i < m->num_channels; i++) { if(!m->meters[i].pixmap) { m->meters[i].pixmap = gdk_pixmap_new(GTK_LAYOUT(m->layout)->bin_window, m->pixmap_width, m->pixmap_height, -1); } } if(m->vertical) { for(i = 0; i < m->num_channels; i++) update_pixmap_vertical(m, i); } else { for(i = 0; i < m->num_channels; i++) update_pixmap_horizontal(m, i); } m->pixmaps_valid = 1; } static void draw_dynamic(bg_gtk_vumeter_t * m) { int i; if(!bg_gtk_widget_is_realized(m->layout) || !m->pixmap_width || !m->pixmap_height) return; if(!m->pixmaps_valid) update_pixmaps(m); for(i = 0; i < m->num_channels; i++) { gdk_draw_drawable(GTK_LAYOUT(m->layout)->bin_window, m->gc, m->meters[i].pixmap, 0, 0, m->meters[i].coords.x, m->meters[i].coords.y, m->meters[i].coords.width, m->meters[i].coords.height); } } static void flash(bg_gtk_vumeter_t * m) { } static gboolean expose_callback(GtkWidget * w, GdkEventExpose *event, gpointer data) { bg_gtk_vumeter_t * m = (bg_gtk_vumeter_t *)data; draw_static(m); draw_dynamic(m); return FALSE; } static void label_size_request_callback(GtkWidget * w, GtkRequisition *requisition, gpointer data) { bg_gtk_vumeter_t * v; int i; v = (bg_gtk_vumeter_t *)data; for(i = 0; i < NUM_TICS; i++) { if(v->labels[i].l == w) { v->labels[i].coords.width = requisition->width; v->labels[i].coords.height = requisition->height; } } } static void size_allocate_callback(GtkWidget * w, GtkAllocation * allocation, gpointer data) { int i; bg_gtk_vumeter_t * v; v = (bg_gtk_vumeter_t *)data; v->width = allocation->width; v->height = allocation->height; // gtk_layout_move( gtk_layout_set_size(GTK_LAYOUT(v->layout), allocation->width, allocation->height); set_coords(v); if((v->meters[0].coords.width > v->pixmap_width) || (v->meters[0].coords.height > v->pixmap_height)) { /* Check if the pixmaps must be enlarged */ v->pixmap_width = (v->meters[0].coords.width > v->pixmap_width) ? v->meters[0].coords.width + 128 : v->pixmap_width; v->pixmap_height = (v->meters[0].coords.height > v->pixmap_height) ? v->meters[0].coords.height + 128 : v->pixmap_height; if(v->pixbuf_on) { gdk_pixbuf_unref(v->pixbuf_on); v->pixbuf_on = NULL; } if(v->pixbuf_off) { gdk_pixbuf_unref(v->pixbuf_off); v->pixbuf_off = NULL; } for(i = 0; i < GAVL_MAX_CHANNELS; i++) { if(!v->meters[i].pixmap) break; g_object_unref(v->meters[i].pixmap); v->meters[i].pixmap = NULL; } v->pixmaps_valid = 0; } else { v->redraw_pixbufs = 1; v->pixmaps_valid = 0; } } bg_gtk_vumeter_t * bg_gtk_vumeter_create(int num_channels, int vertical) { int i; bg_gtk_vumeter_t * ret = calloc(1, sizeof(*ret)); ret->num_channels = num_channels; ret->layout = gtk_layout_new(NULL, NULL); ret->vertical = vertical; gtk_widget_set_events(ret->layout, GDK_EXPOSURE_MASK); g_signal_connect(G_OBJECT(ret->layout), "expose-event", G_CALLBACK(expose_callback), (gpointer)ret); g_signal_connect(G_OBJECT(ret->layout), "size-allocate", G_CALLBACK(size_allocate_callback), (gpointer)ret); gtk_widget_show(ret->layout); if(vertical) gtk_layout_set_size(GTK_LAYOUT(ret->layout), 40, 100); else gtk_layout_set_size(GTK_LAYOUT(ret->layout), 100, 40); /* Create labels */ for(i = 0; i < NUM_TICS; i++) { if(vertical) /* Swap y */ ret->labels[i].l = gtk_label_new(scale_tics[NUM_TICS - 1 - i].label); else ret->labels[i].l = gtk_label_new(scale_tics[i].label); g_signal_connect(G_OBJECT(ret->labels[i].l), "size-request", G_CALLBACK(label_size_request_callback), (gpointer)ret); gtk_widget_show(ret->labels[i].l); gtk_layout_put(GTK_LAYOUT(ret->layout), ret->labels[i].l, 0, 0); } gtk_widget_show(ret->layout); ret->pd = gavl_peak_detector_create(); ret->max_peak_age = 44100; pthread_mutex_init(&ret->analysis_mutex, NULL); return ret; } GtkWidget * bg_gtk_vumeter_get_widget(bg_gtk_vumeter_t * m) { return m->layout; } void bg_gtk_vumeter_set_format(bg_gtk_vumeter_t * m, gavl_audio_format_t * format) { gavl_peak_detector_set_format(m->pd, format); m->num_channels = format->num_channels; } void bg_gtk_vumeter_update_peak(bg_gtk_vumeter_t * m, double * ampl, int samples) { int i; for(i = 0; i < m->num_channels; i++) { if(m->meters[i].level < ampl[i]) { m->meters[i].level = ampl[i]; if(m->meters[i].peak < ampl[i]) { m->meters[i].peak = ampl[i]; m->meters[i].peak_age = 0; } else if(m->meters[i].peak_age > m->max_peak_age) { m->meters[i].peak = ampl[i]; m->meters[i].peak_age = 0; } else m->meters[i].peak_age += samples; } else /* Lowpass */ { m->meters[i].level = 0.90 * m->meters[i].level + 0.10 * ampl[i]; if(m->meters[i].peak_age > m->max_peak_age) { m->meters[i].peak = m->meters[i].level; m->meters[i].peak_age = 0; } else m->meters[i].peak_age += samples; } } m->pixmaps_valid = 0; draw_dynamic(m); } void bg_gtk_vumeter_update(bg_gtk_vumeter_t * m, gavl_audio_frame_t * frame) { double ampl[GAVL_MAX_CHANNELS]; gavl_peak_detector_reset(m->pd); gavl_peak_detector_update(m->pd, frame); gavl_peak_detector_get_peaks(m->pd, NULL, NULL, ampl); bg_gtk_vumeter_update_peak(m, ampl, frame->valid_samples); } void bg_gtk_vumeter_draw(bg_gtk_vumeter_t * m) { pthread_mutex_lock(&m->analysis_mutex); draw_dynamic(m); pthread_mutex_unlock(&m->analysis_mutex); flash(m); } void bg_gtk_vumeter_destroy(bg_gtk_vumeter_t * m) { } gmerlin-1.2.0~dfsg/lib/gtk/cfg_multi_list.c0000644000175000017500000007130611764363406020615 0ustar alessioalessio/***************************************************************** * gmerlin - a general purpose multimedia framework and applications * * Copyright (c) 2001 - 2011 Members of the Gmerlin project * gmerlin-general@lists.sourceforge.net * http://gmerlin.sourceforge.net * * 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 of the License, 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 this program. If not, see . * *****************************************************************/ #include #include #include "gtk_dialog.h" #include #include #include enum { COLUMN_LABEL, COLUMN_NAME, NUM_COLUMNS }; typedef struct list_priv_s list_priv_t; struct list_priv_s { GtkWidget * treeview; GtkWidget * config_button; GtkWidget * info_button; GtkWidget * top_button; GtkWidget * bottom_button; GtkWidget * up_button; GtkWidget * down_button; GtkWidget * add_button; GtkWidget * remove_button; GtkWidget * scrolled; const char * translation_domain; bg_set_parameter_func_t set_param; bg_get_parameter_func_t get_param; void * data; int selected; int param_selected; int is_chain; int num; char ** multi_labels; }; static void translate_labels(bg_gtk_widget_t * w) { list_priv_t * priv; int i; priv = (list_priv_t*)(w->priv); i = 0; while(w->info->multi_labels[i]) i++; priv->multi_labels = calloc(i+1, sizeof(*priv->multi_labels)); i = 0; while(w->info->multi_labels[i]) { priv->multi_labels[i] = bg_strdup(NULL, TRD(w->info->multi_labels[i], priv->translation_domain)); i++; } } static void set_sub_param(void * priv, const char * name, const bg_parameter_value_t * val) { char * tmp_string; list_priv_t * list; bg_gtk_widget_t * w; w = (bg_gtk_widget_t*)priv; list = (list_priv_t*)(w->priv); if(!list->set_param) return; if(!name) tmp_string = NULL; else if(list->is_chain) tmp_string = bg_sprintf("%s.%d.%s", w->info->name, list->selected, name); else if(list->param_selected < 0) return; else { tmp_string = bg_sprintf("%s.%s.%s", w->info->name, w->info->multi_names[list->param_selected], name); } list->set_param(list->data, tmp_string, val); if(tmp_string) free(tmp_string); } static int get_sub_param(void * priv, const char * name, bg_parameter_value_t * val) { char * tmp_string; list_priv_t * list; bg_gtk_widget_t * w; int ret; w = (bg_gtk_widget_t*)priv; list = (list_priv_t*)(w->priv); if(!list->get_param) return 0; if(!name) tmp_string = NULL; else if(list->is_chain) tmp_string = bg_sprintf("%s.%d.%s", w->info->name, list->selected, name); else { tmp_string = bg_sprintf("%s.%s.%s", w->info->name, w->info->multi_names[list->param_selected], name); } ret = list->get_param(list->data, tmp_string, val); if(tmp_string) free(tmp_string); return ret; } static void apply_sub_params(bg_gtk_widget_t * w) { list_priv_t * list = (list_priv_t*)(w->priv); int index; bg_cfg_section_t * subsection; bg_cfg_section_t * subsubsection; int selected_save; char ** names; if(!list->set_param || !w->value.val_str) return; subsection = bg_cfg_section_find_subsection(w->cfg_section, w->info->name); names = bg_strbreak(w->value.val_str, ','); selected_save = list->selected; for(list->selected = 0; list->selected < list->num; list->selected++) { index = 0; while(w->info->multi_names[index]) { if(!strcmp(w->info->multi_names[index], names[list->selected])) break; index++; } if(w->info->multi_names[index] && w->info->multi_parameters[index]) { if(list->is_chain) subsubsection = bg_cfg_section_find_subsection_by_index(subsection, list->selected); else subsubsection = bg_cfg_section_find_subsection(subsection, names[list->selected]); bg_cfg_section_apply_noterminate(subsubsection, w->info->multi_parameters[index], set_sub_param, w); } } list->selected = selected_save; if(names) bg_strbreak_free(names); } /* Return the string corresponding to the current list */ static char * get_list_string(bg_gtk_widget_t * w) { char * ret = NULL; GtkTreeModel * model; GtkTreeIter iter; char * name; list_priv_t * priv = (list_priv_t*)(w->priv); model = gtk_tree_view_get_model(GTK_TREE_VIEW(priv->treeview)); if(!gtk_tree_model_get_iter_first(model, &iter)) { return NULL; } while(1) { gtk_tree_model_get(model, &iter, COLUMN_NAME, &name, -1); ret = bg_strcat(ret, name); g_free(name); if(!gtk_tree_model_iter_next(model, &iter)) break; ret = bg_strcat(ret, ","); } return ret; } /* Get the index in the multi_* arrays of the selected item */ static int get_selected_index(bg_gtk_widget_t * w) { GtkTreeModel * model; GtkTreeIter iter; char * name; int ret; list_priv_t * priv = (list_priv_t*)(w->priv); model = gtk_tree_view_get_model(GTK_TREE_VIEW(priv->treeview)); if(!gtk_tree_model_iter_nth_child(model, &iter, NULL, priv->selected)) { return 0; } gtk_tree_model_get(model, &iter, COLUMN_NAME, &name, -1); ret = 0; while(strcmp(w->info->multi_names[ret], name)) ret++; g_free(name); return ret; } static void set_value(bg_gtk_widget_t * w) { if(w->value.val_str) free(w->value.val_str); w->value.val_str = get_list_string(w); } static void get_value(bg_gtk_widget_t * w) { GtkTreeIter iter; GtkTreeModel * model; char const * const * names_c; char ** names; int init; int i, j, do_add; list_priv_t * priv = (list_priv_t*)(w->priv); char * val_current; /* Return early if nothing changed */ val_current = get_list_string(w); if((!val_current && !w->value.val_str) || ((val_current && w->value.val_str) && !strcmp(val_current, w->value.val_str))) { if(val_current) free(val_current); return; } free(val_current); /* Fill the list */ model = gtk_tree_view_get_model(GTK_TREE_VIEW(priv->treeview)); gtk_list_store_clear(GTK_LIST_STORE(model)); priv->num = 0; names = bg_strbreak(w->value.val_str, ','); if(!names) { names_c = w->info->multi_names; init = 1; } else { names_c = (char const **)names; init = 0; } /* create translated labels */ if(!priv->multi_labels && w->info->multi_labels) translate_labels(w); /* Append the codec names from the string, if they are available */ i = 0; if(!init) { while(names_c[i]) { j = 0; while(w->info->multi_names[j]) { if(!strcmp(names_c[i], w->info->multi_names[j])) { gtk_list_store_append(GTK_LIST_STORE(model), &iter); if(priv->multi_labels) gtk_list_store_set(GTK_LIST_STORE(model), &iter, COLUMN_LABEL, priv->multi_labels[j], -1); else gtk_list_store_set(GTK_LIST_STORE(model), &iter, COLUMN_LABEL, w->info->multi_names[j], -1); gtk_list_store_set(GTK_LIST_STORE(model), &iter, COLUMN_NAME, w->info->multi_names[j], -1); break; } j++; } i++; } } priv->num = i; /* Append the the new */ if(!priv->is_chain) { i = 0; while(w->info->multi_names[i]) { /* Test, if we didn't already add this */ if(init) do_add = 1; else { do_add = 1; j = 0; while(names_c[j]) { if(!strcmp(names_c[j], w->info->multi_names[i])) { do_add = 0; break; } j++; } } if(do_add) { gtk_list_store_append(GTK_LIST_STORE(model), &iter); if(w->info->multi_labels) gtk_list_store_set(GTK_LIST_STORE(model), &iter, COLUMN_LABEL, priv->multi_labels[i], -1); else gtk_list_store_set(GTK_LIST_STORE(model), &iter, COLUMN_LABEL, w->info->multi_names[i], -1); gtk_list_store_set(GTK_LIST_STORE(model), &iter, COLUMN_NAME, w->info->multi_names[i], -1); } i++; } } if(!init) bg_strbreak_free(names); // if(w->info->flags & BG_PARAMETER_SYNC) // bg_gtk_change_callback(NULL, w); } static void add_func(void * priv, const char * name, const bg_parameter_value_t * val) { list_priv_t * list; bg_gtk_widget_t * w; int index; GtkTreeModel * model; GtkTreeIter iter; bg_cfg_section_t * subsection; bg_cfg_section_t * subsubsection; // bg_cfg_section_t * subsection_default; w = priv; list = w->priv; if(!name) return; if(strcmp(name, w->info->name)) return; model = gtk_tree_view_get_model(GTK_TREE_VIEW(list->treeview)); index = 0; while(strcmp(w->info->multi_names[index], val->val_str)) index++; gtk_list_store_append(GTK_LIST_STORE(model), &iter); if(!list->multi_labels && w->info->multi_labels) translate_labels(w); if(list->multi_labels) gtk_list_store_set(GTK_LIST_STORE(model), &iter, COLUMN_LABEL, list->multi_labels[index], -1); else gtk_list_store_set(GTK_LIST_STORE(model), &iter, COLUMN_LABEL, w->info->multi_names[index], -1); gtk_list_store_set(GTK_LIST_STORE(model), &iter, COLUMN_NAME, w->info->multi_names[index], -1); subsection = bg_cfg_section_find_subsection(w->cfg_section, w->info->name); #if 0 subsection_default = bg_cfg_section_find_subsection(subsection, val->val_str); if(w->info->multi_parameters[index]) bg_cfg_section_create_items(subsection_default, w->info->multi_parameters[index]); #endif subsubsection = bg_cfg_section_create_subsection_at_pos(subsection, list->num); if(w->info->multi_parameters[index]) bg_cfg_section_create_items(subsubsection, w->info->multi_parameters[index]); // bg_cfg_section_transfer(subsection_default, subsubsection); list->num++; if(w->info->flags & BG_PARAMETER_SYNC) { bg_gtk_change_callback(NULL, w); } } static void attach(void * p, GtkWidget * table, int * row, int * num_columns) { list_priv_t * e = (list_priv_t*)(p); int num_rows = 2; if(e->is_chain) num_rows += 2; if(e->top_button) num_rows+=4; if(*num_columns < 3) *num_columns = 3; gtk_table_resize(GTK_TABLE(table), *row+num_rows, *num_columns); gtk_table_attach_defaults(GTK_TABLE(table), e->scrolled, 0, 2, *row, *row+num_rows); if(e->is_chain) { gtk_table_attach(GTK_TABLE(table), e->add_button, 2, 3, *row, *row+1, GTK_FILL, GTK_SHRINK, 0, 0); *row += 1; gtk_table_attach(GTK_TABLE(table), e->remove_button, 2, 3, *row, *row+1, GTK_FILL, GTK_SHRINK, 0, 0); *row += 1; } gtk_table_attach(GTK_TABLE(table), e->config_button, 2, 3, *row, *row+1, GTK_FILL, GTK_SHRINK, 0, 0); *row += 1; gtk_table_attach(GTK_TABLE(table), e->info_button, 2, 3, *row, *row+1, GTK_FILL, GTK_SHRINK, 0, 0); *row += 1; if(e->top_button) { gtk_table_attach(GTK_TABLE(table), e->top_button, 2, 3, *row, *row+1, GTK_FILL, GTK_SHRINK, 0, 0); *row += 1; } if(e->up_button) { gtk_table_attach(GTK_TABLE(table), e->up_button, 2, 3, *row, *row+1, GTK_FILL, GTK_SHRINK, 0, 0); *row += 1; } if(e->down_button) { gtk_table_attach(GTK_TABLE(table), e->down_button, 2, 3, *row, *row+1, GTK_FILL, GTK_SHRINK, 0, 0); *row += 1; } if(e->bottom_button) { gtk_table_attach(GTK_TABLE(table), e->bottom_button, 2, 3, *row, *row+1, GTK_FILL, GTK_SHRINK, 0, 0); *row += 1; } } static void destroy(bg_gtk_widget_t * w) { list_priv_t * priv = (list_priv_t*)(w->priv); if(priv->multi_labels) { int i = 0; while(priv->multi_labels[i]) free(priv->multi_labels[i++]); free(priv->multi_labels); } free(priv); } static const gtk_widget_funcs_t funcs = { .get_value = get_value, .set_value = set_value, .destroy = destroy, .attach = attach, .apply_sub_params = apply_sub_params, }; static void select_row_callback(GtkTreeSelection * s, gpointer data) { bg_gtk_widget_t * w; list_priv_t * priv; char * name; GtkTreeIter iter; GtkTreeModel * model; GtkTreeSelection * selection; w = (bg_gtk_widget_t *)data; priv = (list_priv_t *)(w->priv); selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(priv->treeview)); if(!gtk_tree_selection_get_selected(selection, &model, &iter)) priv->selected = -1; else { priv->selected = 0; gtk_tree_model_get_iter_first(model, &iter); while(1) { if(gtk_tree_selection_iter_is_selected(selection, &iter)) break; priv->selected++; gtk_tree_model_iter_next(model, &iter); } } if(priv->selected < 0) { gtk_widget_set_sensitive(priv->info_button, 0); gtk_widget_set_sensitive(priv->config_button, 0); if(priv->top_button) gtk_widget_set_sensitive(priv->top_button, 0); if(priv->bottom_button) gtk_widget_set_sensitive(priv->bottom_button, 0); if(priv->up_button) gtk_widget_set_sensitive(priv->up_button, 0); if(priv->down_button) gtk_widget_set_sensitive(priv->down_button, 0); if(priv->remove_button) gtk_widget_set_sensitive(priv->remove_button, 0); priv->param_selected = priv->selected; } else { gtk_tree_model_get(model, &iter, COLUMN_NAME, &name, -1); priv->param_selected = 0; while(strcmp(w->info->multi_names[priv->param_selected], name)) priv->param_selected++; g_free(name); if(w->info->multi_descriptions && w->info->multi_descriptions[priv->param_selected]) gtk_widget_set_sensitive(priv->info_button, 1); else gtk_widget_set_sensitive(priv->info_button, 0); if(w->info->multi_parameters && w->info->multi_parameters[priv->param_selected]) gtk_widget_set_sensitive(priv->config_button, 1); else gtk_widget_set_sensitive(priv->config_button, 0); if(priv->selected > 0) { if(priv->top_button) gtk_widget_set_sensitive(priv->top_button, 1); if(priv->up_button) gtk_widget_set_sensitive(priv->up_button, 1); } else { if(priv->top_button) gtk_widget_set_sensitive(priv->top_button, 0); if(priv->up_button) gtk_widget_set_sensitive(priv->up_button, 0); } if(priv->selected < priv->num-1) { if(priv->bottom_button) gtk_widget_set_sensitive(priv->bottom_button, 1); if(priv->down_button) gtk_widget_set_sensitive(priv->down_button, 1); } else { if(priv->bottom_button) gtk_widget_set_sensitive(priv->bottom_button, 0); if(priv->down_button) gtk_widget_set_sensitive(priv->down_button, 0); } if(priv->remove_button) gtk_widget_set_sensitive(priv->remove_button, 1); } } static void move_selected(bg_gtk_widget_t * w, int new_pos) { int i; list_priv_t * priv; bg_cfg_section_t * subsection; bg_cfg_section_t * subsubsection; GtkTreeSelection * selection; GtkTreeModel * model; GtkTreePath * path; GtkTreeIter iter; GtkTreeIter iter_before; priv = (list_priv_t *)(w->priv); selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(priv->treeview)); gtk_tree_selection_get_selected(selection, &model, &iter); if(!new_pos) { gtk_list_store_move_after(GTK_LIST_STORE(model), &iter, NULL); } else { gtk_tree_model_get_iter_first(model, &iter_before); for(i = 0; i < new_pos-1; i++) gtk_tree_model_iter_next(model, &iter_before); if(new_pos > priv->selected) gtk_tree_model_iter_next(model, &iter_before); gtk_list_store_move_after(GTK_LIST_STORE(model), &iter, &iter_before); } // gtk_tree_selection_select_iter(selection, &iter); path = gtk_tree_model_get_path(model, &iter); gtk_tree_view_scroll_to_cell(GTK_TREE_VIEW(priv->treeview), path, NULL, 0, 0.0, 0.0); gtk_tree_path_free(path); subsection = bg_cfg_section_find_subsection(w->cfg_section, w->info->name); /* Move config section */ if(priv->is_chain) { subsubsection = bg_cfg_section_find_subsection_by_index(subsection, priv->selected); bg_cfg_section_move_child(subsection, subsubsection, new_pos); } /* Apply parameter and subsections. It's easier to do it here. */ if(w->info->flags & BG_PARAMETER_SYNC) bg_gtk_change_callback(NULL, w); priv->selected = new_pos; if(!priv->selected) { if(priv->top_button) gtk_widget_set_sensitive(priv->top_button, 0); if(priv->up_button) gtk_widget_set_sensitive(priv->up_button, 0); } else { if(priv->top_button) gtk_widget_set_sensitive(priv->top_button, 1); if(priv->up_button) gtk_widget_set_sensitive(priv->up_button, 1); } if(priv->selected >= priv->num - 1) { if(priv->down_button) gtk_widget_set_sensitive(priv->down_button, 0); if(priv->bottom_button) gtk_widget_set_sensitive(priv->bottom_button, 0); } else { if(priv->down_button) gtk_widget_set_sensitive(priv->down_button, 1); if(priv->bottom_button) gtk_widget_set_sensitive(priv->bottom_button, 1); } } static void button_callback(GtkWidget * wid, gpointer data) { bg_gtk_widget_t * w; list_priv_t * priv; bg_dialog_t * dialog; GtkTreeSelection * selection; GtkTreeModel * model; const char * label; bg_cfg_section_t * subsection; bg_cfg_section_t * subsubsection; w = data; priv = w->priv; if(wid == priv->config_button) { if(w->cfg_section) { subsection = bg_cfg_section_find_subsection(w->cfg_section, w->info->name); if(priv->is_chain) subsection = bg_cfg_section_find_subsection_by_index(subsection, priv->selected); else subsection = bg_cfg_section_find_subsection(subsection, w->info->multi_names[priv->param_selected]); } else subsection = NULL; if(w->info->multi_labels && w->info->multi_labels[priv->param_selected]) label = TRD(w->info->multi_labels[priv->param_selected], priv->translation_domain); else label = w->info->multi_names[priv->param_selected]; dialog = bg_dialog_create(subsection, set_sub_param, get_sub_param, w, w->info->multi_parameters[priv->param_selected], label); bg_dialog_show(dialog, priv->treeview); } else if(wid == priv->info_button) { bg_gtk_multi_info_show(w->info, get_selected_index(w), priv->translation_domain, priv->info_button); } else if(wid == priv->top_button) { if(priv->selected == 0) return; move_selected(w, 0); } else if(wid == priv->up_button) { if(priv->selected == 0) return; move_selected(w, priv->selected - 1); } else if(wid == priv->down_button) { if(priv->selected >= priv->num - 1) return; move_selected(w, priv->selected+1); } else if(wid == priv->bottom_button) { if(priv->selected >= priv->num-1) return; move_selected(w, priv->num-1); } else if(wid == priv->add_button) { bg_parameter_info_t params[2]; char * tmp_string; memset(params, 0, sizeof(params)); params[0].name = w->info->name; params[0].long_name = w->info->long_name; params[0].type = BG_PARAMETER_MULTI_MENU; params[0].gettext_domain = bg_strdup(params[0].gettext_domain, priv->translation_domain); params[0].multi_names = w->info->multi_names; params[0].multi_labels = w->info->multi_labels; params[0].multi_descriptions = w->info->multi_descriptions; params[0].help_string = w->info->help_string; // params[0].multi_parameters = w->info->multi_parameters; tmp_string = bg_sprintf(TR("Add %s"), TRD(w->info->long_name, priv->translation_domain)); dialog = bg_dialog_create(w->cfg_section, add_func, NULL, w, params, tmp_string); free(tmp_string); bg_dialog_show(dialog, priv->treeview); free(params[0].gettext_domain); } else if(wid == priv->remove_button) { GtkTreeIter iter; selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(priv->treeview)); if(!gtk_tree_selection_get_selected(selection, &model, &iter)) return; subsection = bg_cfg_section_find_subsection(w->cfg_section, w->info->name); subsubsection = bg_cfg_section_find_subsection_by_index(subsection, priv->selected); bg_cfg_section_delete_subsection(subsection, subsubsection); gtk_list_store_remove(GTK_LIST_STORE(model), &iter); priv->num--; if(w->info->flags & BG_PARAMETER_SYNC) { bg_gtk_change_callback(NULL, w); } } } static GtkWidget * create_pixmap_button(const char * filename) { GtkWidget * button; GtkWidget * image; char * path; path = bg_search_file_read("icons", filename); if(path) { image = gtk_image_new_from_file(path); free(path); } else image = gtk_image_new(); gtk_widget_show(image); button = gtk_button_new(); gtk_container_add(GTK_CONTAINER(button), image); return button; } static void create_list_common(bg_gtk_widget_t * w, const bg_parameter_info_t * info, bg_set_parameter_func_t set_param, bg_get_parameter_func_t get_param, void * data, const char * translation_domain, int is_chain) { GtkListStore *store; GtkTreeViewColumn *column; GtkCellRenderer *renderer; GtkTreeSelection * selection; list_priv_t * priv = calloc(1, sizeof(*priv)); priv->set_param = set_param; priv->get_param = get_param; priv->data = data; priv->translation_domain = translation_domain; priv->is_chain = is_chain; w->funcs = &funcs; w->priv = priv; /* Create objects */ priv->info_button = create_pixmap_button("info_16.png"); priv->config_button = create_pixmap_button("config_16.png"); g_signal_connect(G_OBJECT(priv->info_button), "clicked", G_CALLBACK(button_callback), (gpointer)w); g_signal_connect(G_OBJECT(priv->config_button), "clicked", G_CALLBACK(button_callback), (gpointer)w); gtk_widget_show(priv->info_button); gtk_widget_show(priv->config_button); gtk_widget_set_sensitive(priv->info_button, 0); gtk_widget_set_sensitive(priv->config_button, 0); if(!(info->flags & BG_PARAMETER_NO_SORT)) { priv->top_button = create_pixmap_button("top_16.png"); priv->bottom_button = create_pixmap_button("bottom_16.png"); priv->up_button = create_pixmap_button("up_16.png"); priv->down_button = create_pixmap_button("down_16.png"); g_signal_connect(G_OBJECT(priv->top_button), "clicked", G_CALLBACK(button_callback), (gpointer)w); g_signal_connect(G_OBJECT(priv->bottom_button), "clicked", G_CALLBACK(button_callback), (gpointer)w); g_signal_connect(G_OBJECT(priv->up_button), "clicked", G_CALLBACK(button_callback), (gpointer)w); g_signal_connect(G_OBJECT(priv->down_button), "clicked", G_CALLBACK(button_callback), (gpointer)w); gtk_widget_show(priv->top_button); gtk_widget_show(priv->bottom_button); gtk_widget_show(priv->up_button); gtk_widget_show(priv->down_button); gtk_widget_set_sensitive(priv->top_button, 0); gtk_widget_set_sensitive(priv->bottom_button, 0); gtk_widget_set_sensitive(priv->up_button, 0); gtk_widget_set_sensitive(priv->down_button, 0); } if(priv->is_chain) { priv->add_button = create_pixmap_button("add_16.png"); priv->remove_button = create_pixmap_button("trash_16.png"); g_signal_connect(G_OBJECT(priv->add_button), "clicked", G_CALLBACK(button_callback), (gpointer)w); g_signal_connect(G_OBJECT(priv->remove_button), "clicked", G_CALLBACK(button_callback), (gpointer)w); gtk_widget_show(priv->add_button); gtk_widget_show(priv->remove_button); gtk_widget_set_sensitive(priv->remove_button, 0); } store = gtk_list_store_new(NUM_COLUMNS, G_TYPE_STRING, G_TYPE_STRING); priv->treeview = gtk_tree_view_new_with_model(GTK_TREE_MODEL(store)); if(info->help_string) { bg_gtk_tooltips_set_tip(priv->treeview, info->help_string, translation_domain); } gtk_tree_view_set_headers_visible(GTK_TREE_VIEW(priv->treeview), FALSE); selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(priv->treeview)); g_signal_connect(G_OBJECT(selection), "changed", G_CALLBACK(select_row_callback), (gpointer)w); renderer = gtk_cell_renderer_text_new (); column = gtk_tree_view_column_new_with_attributes("", renderer, "text", COLUMN_LABEL, NULL); gtk_tree_view_append_column (GTK_TREE_VIEW(priv->treeview), column); gtk_widget_show(priv->treeview); priv->scrolled = gtk_scrolled_window_new(gtk_tree_view_get_hadjustment(GTK_TREE_VIEW(priv->treeview)), gtk_tree_view_get_vadjustment(GTK_TREE_VIEW(priv->treeview))); gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(priv->scrolled), GTK_POLICY_NEVER, GTK_POLICY_ALWAYS); gtk_container_add(GTK_CONTAINER(priv->scrolled), priv->treeview); gtk_widget_show(priv->scrolled); } void bg_gtk_create_multi_list(bg_gtk_widget_t * w, bg_set_parameter_func_t set_param, bg_get_parameter_func_t get_param, void * data, const char * translation_domain) { create_list_common(w, w->info, set_param, get_param, data, translation_domain, 0); } void bg_gtk_create_multi_chain(bg_gtk_widget_t * w, bg_set_parameter_func_t set_param, bg_get_parameter_func_t get_param, void * data, const char * translation_domain) { create_list_common(w, w->info, set_param, get_param, data, translation_domain, 1); } gmerlin-1.2.0~dfsg/lib/gtk/plugin_multi.c0000644000175000017500000003243711764363406020323 0ustar alessioalessio/***************************************************************** * gmerlin - a general purpose multimedia framework and applications * * Copyright (c) 2001 - 2011 Members of the Gmerlin project * gmerlin-general@lists.sourceforge.net * http://gmerlin.sourceforge.net * * 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 of the License, 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 this program. If not, see . * *****************************************************************/ #include #include #include #include #include #include #include #include #include #include enum { COLUMN_PLUGIN, NUM_COLUMNS }; struct bg_gtk_plugin_widget_multi_s { GtkWidget * info_button; GtkWidget * config_button; GtkWidget * treeview; GtkWidget * widget; GtkWidget * protocols; GtkWidget * extensions; GtkWidget * priority; bg_plugin_registry_t * reg; const bg_plugin_info_t * info; bg_parameter_info_t * parameters; bg_cfg_section_t * section; gulong extensions_changed_id; gulong protocols_changed_id; gulong priority_changed_id; uint32_t flag_mask; uint32_t type_mask; }; static void button_callback(GtkWidget * w, gpointer data) { bg_gtk_plugin_widget_multi_t * win; bg_dialog_t * dialog; win = (bg_gtk_plugin_widget_multi_t *)data; if(w == win->info_button) { bg_gtk_plugin_info_show(win->info, win->info_button); } else if(w == win->config_button) { dialog = bg_dialog_create(win->section, NULL, NULL, NULL, win->info->parameters, TRD(win->info->long_name, win->info->gettext_domain)); bg_dialog_show(dialog, win->config_button); bg_dialog_destroy(dialog); } } static void select_row_callback(GtkTreeSelection * s, gpointer data) { GtkTreeModel * model; GtkTreeIter iter; int selected, i; bg_gtk_plugin_widget_multi_t * win = (bg_gtk_plugin_widget_multi_t*)data; model = gtk_tree_view_get_model(GTK_TREE_VIEW(win->treeview)); if(!gtk_tree_model_get_iter_first(model, &iter)) return; selected = -1; i = 0; while(1) { if(gtk_tree_selection_iter_is_selected(s, &iter)) { selected = i; break; } gtk_tree_model_iter_next(model, &iter); i++; } if(selected == -1) return; win->info = bg_plugin_find_by_index(win->reg, selected, win->type_mask, win->flag_mask); if(win->info->parameters) win->parameters = win->info->parameters; else win->parameters = NULL; win->section = bg_plugin_registry_get_section(win->reg, win->info->name); if(win->parameters) gtk_widget_set_sensitive(win->config_button, 1); else gtk_widget_set_sensitive(win->config_button, 0); if(win->extensions) { g_signal_handler_block(G_OBJECT(win->extensions), win->extensions_changed_id); if((win->info->flags & BG_PLUGIN_FILE) && win->info->extensions) { gtk_entry_set_text(GTK_ENTRY(win->extensions), win->info->extensions); gtk_widget_set_sensitive(win->extensions, 1); } else { gtk_entry_set_text(GTK_ENTRY(win->extensions), ""); gtk_widget_set_sensitive(win->extensions, 0); } g_signal_handler_unblock(G_OBJECT(win->extensions), win->extensions_changed_id); } if(win->protocols) { g_signal_handler_block(G_OBJECT(win->protocols), win->protocols_changed_id); if(win->info->flags & BG_PLUGIN_URL) { gtk_entry_set_text(GTK_ENTRY(win->protocols), win->info->protocols); gtk_widget_set_sensitive(win->protocols, 1); } else if(win->info->flags & (BG_PLUGIN_REMOVABLE | BG_PLUGIN_TUNER)) { gtk_entry_set_text(GTK_ENTRY(win->protocols), win->info->protocols); gtk_widget_set_sensitive(win->protocols, 0); } else { gtk_entry_set_text(GTK_ENTRY(win->protocols), ""); gtk_widget_set_sensitive(win->protocols, 0); } g_signal_handler_unblock(G_OBJECT(win->protocols), win->protocols_changed_id); } gtk_widget_set_sensitive(win->info_button, 1); if(win->priority) { g_signal_handler_block(G_OBJECT(win->priority), win->priority_changed_id); gtk_spin_button_set_value(GTK_SPIN_BUTTON(win->priority), win->info->priority); g_signal_handler_unblock(G_OBJECT(win->priority), win->priority_changed_id); if(win->info->flags & (BG_PLUGIN_URL | BG_PLUGIN_FILE)) gtk_widget_set_sensitive(win->priority, 1); else gtk_widget_set_sensitive(win->priority, 0); } } static void change_callback(GtkWidget * w, gpointer data) { bg_gtk_plugin_widget_multi_t * win = (bg_gtk_plugin_widget_multi_t*)data; if(w == win->extensions) { bg_plugin_registry_set_extensions(win->reg, win->info->name, gtk_entry_get_text(GTK_ENTRY(win->extensions))); } else if(w == win->protocols) { bg_plugin_registry_set_protocols(win->reg, win->info->name, gtk_entry_get_text(GTK_ENTRY(win->protocols))); } else if(w == win->priority) { bg_plugin_registry_set_priority(win->reg, win->info->name, gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(win->priority))); } } static GtkWidget * create_pixmap_button(const char * filename, const char * tooltip) { GtkWidget * button; GtkWidget * image; char * path; path = bg_search_file_read("icons", filename); if(path) { image = gtk_image_new_from_file(path); free(path); } else image = gtk_image_new(); gtk_widget_show(image); button = gtk_button_new(); gtk_container_add(GTK_CONTAINER(button), image); bg_gtk_tooltips_set_tip(button, tooltip, PACKAGE); return button; } bg_gtk_plugin_widget_multi_t * bg_gtk_plugin_widget_multi_create(bg_plugin_registry_t * reg, uint32_t type_mask, uint32_t flag_mask) { bg_gtk_plugin_widget_multi_t * ret; GtkListStore *store; GtkTreeViewColumn *column; GtkTreeIter iter; GtkCellRenderer *renderer; GtkWidget * label; GtkWidget * scrolled; GtkWidget * table; GtkTreeSelection * selection; GtkWidget * hbox; const bg_plugin_info_t * info; int num_plugins, i; ret = calloc(1,sizeof(*ret)); ret->reg = reg; ret->type_mask = type_mask; ret->flag_mask = flag_mask; /* Create buttons */ ret->info_button = create_pixmap_button("info_16.png", TRS("Plugin info")); ret->config_button = create_pixmap_button("config_16.png", TRS("Plugin options")); g_signal_connect(G_OBJECT(ret->info_button), "clicked", G_CALLBACK(button_callback), (gpointer)ret); g_signal_connect(G_OBJECT(ret->config_button), "clicked", G_CALLBACK(button_callback), (gpointer)ret); gtk_widget_show(ret->info_button); gtk_widget_show(ret->config_button); /* Create list */ store = gtk_list_store_new(NUM_COLUMNS, G_TYPE_STRING); ret->treeview = gtk_tree_view_new_with_model(GTK_TREE_MODEL(store)); selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(ret->treeview)); g_signal_connect(G_OBJECT(selection), "changed", G_CALLBACK(select_row_callback), (gpointer)ret); renderer = gtk_cell_renderer_text_new (); column = gtk_tree_view_column_new_with_attributes ("Installed Plugins", renderer, "text", COLUMN_PLUGIN, NULL); gtk_tree_view_column_set_sort_column_id (column, COLUMN_PLUGIN); gtk_tree_view_append_column (GTK_TREE_VIEW(ret->treeview), column); gtk_tree_view_set_headers_visible(GTK_TREE_VIEW(ret->treeview), FALSE); gtk_widget_show(ret->treeview); scrolled = gtk_scrolled_window_new(gtk_tree_view_get_hadjustment(GTK_TREE_VIEW(ret->treeview)), gtk_tree_view_get_vadjustment(GTK_TREE_VIEW(ret->treeview))); gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled), GTK_POLICY_NEVER, GTK_POLICY_ALWAYS); gtk_container_add(GTK_CONTAINER(scrolled), ret->treeview); gtk_widget_show(scrolled); /* Add Plugins */ num_plugins = bg_plugin_registry_get_num_plugins(reg, type_mask, flag_mask); for(i = 0; i < num_plugins; i++) { info = bg_plugin_find_by_index(reg, i, type_mask, flag_mask); gtk_list_store_append(store, &iter); gtk_list_store_set(store, &iter, COLUMN_PLUGIN, TRD(info->long_name, info->gettext_domain), -1); } /* Create entries */ if(type_mask & (BG_PLUGIN_INPUT | BG_PLUGIN_IMAGE_READER)) { ret->extensions = gtk_entry_new(); ret->protocols = gtk_entry_new(); ret->priority = gtk_spin_button_new_with_range(BG_PLUGIN_PRIORITY_MIN, BG_PLUGIN_PRIORITY_MAX, 1.0); ret->extensions_changed_id = g_signal_connect(G_OBJECT(ret->extensions), "changed", G_CALLBACK(change_callback), (gpointer)ret); ret->protocols_changed_id = g_signal_connect(G_OBJECT(ret->protocols), "changed", G_CALLBACK(change_callback), (gpointer)ret); ret->priority_changed_id = g_signal_connect(G_OBJECT(ret->priority), "value-changed", G_CALLBACK(change_callback), (gpointer)ret); gtk_widget_show(ret->protocols); gtk_widget_show(ret->extensions); gtk_widget_show(ret->priority); } /* Pack stuff */ table = gtk_table_new(5, 4, 0); gtk_container_set_border_width(GTK_CONTAINER(table), 5); gtk_table_set_row_spacings(GTK_TABLE(table), 5); gtk_table_set_col_spacings(GTK_TABLE(table), 5); // gtk_table_attach_defaults(GTK_TABLE(table), scrolled, 0, 1, 0, 5); gtk_table_attach(GTK_TABLE(table), ret->config_button, 0, 1, 0, 1, GTK_FILL, GTK_SHRINK, 0, 0); if(ret->priority) { gtk_table_attach(GTK_TABLE(table), ret->info_button, 1, 2, 0, 1, GTK_FILL, GTK_SHRINK, 0, 0); label = gtk_label_new(TR("Priority")); gtk_misc_set_alignment(GTK_MISC(label), 0.0, 0.5); gtk_widget_show(label); gtk_table_attach(GTK_TABLE(table), label, 2, 3, 0, 1, GTK_FILL, GTK_SHRINK, 0, 0); gtk_table_attach(GTK_TABLE(table), ret->priority, 3, 4, 0, 1, GTK_FILL|GTK_EXPAND, GTK_SHRINK, 0, 0); label = gtk_label_new(TR("Protocols")); gtk_misc_set_alignment(GTK_MISC(label), 0.0, 0.5); gtk_widget_show(label); gtk_table_attach(GTK_TABLE(table), label, 0, 4, 1, 2, GTK_FILL|GTK_EXPAND, GTK_SHRINK, 0, 0); gtk_table_attach(GTK_TABLE(table), ret->protocols, 0, 4, 2, 3, GTK_FILL|GTK_EXPAND, GTK_SHRINK, 0, 0); label = gtk_label_new(TR("Extensions")); gtk_misc_set_alignment(GTK_MISC(label), 0.0, 0.5); gtk_widget_show(label); gtk_table_attach(GTK_TABLE(table), label, 0, 4, 3, 4, GTK_FILL|GTK_EXPAND, GTK_SHRINK, 0, 0); gtk_table_attach(GTK_TABLE(table), ret->extensions, 0, 4, 4, 5, GTK_FILL|GTK_EXPAND, GTK_SHRINK, 0, 0); } else { gtk_table_attach(GTK_TABLE(table), ret->info_button, 0, 1, 1, 2, GTK_FILL, GTK_SHRINK, 0, 0); } gtk_widget_show(table); hbox = gtk_hpaned_new(); gtk_paned_add1(GTK_PANED(hbox), scrolled); gtk_paned_add2(GTK_PANED(hbox), table); gtk_widget_show(hbox); ret->widget = hbox; /* Make things insensitive, because nothing is selected so far */ if(ret->priority) gtk_widget_set_sensitive(ret->priority, 0); if(ret->protocols) gtk_widget_set_sensitive(ret->protocols, 0); if(ret->extensions) gtk_widget_set_sensitive(ret->extensions, 0); gtk_widget_set_sensitive(ret->config_button, 0); gtk_widget_set_sensitive(ret->info_button, 0); return ret; } GtkWidget * bg_gtk_plugin_widget_multi_get_widget(bg_gtk_plugin_widget_multi_t * w) { return w->widget; } void bg_gtk_plugin_widget_multi_destroy(bg_gtk_plugin_widget_multi_t * w) { free(w); } gmerlin-1.2.0~dfsg/lib/gtk/slider.c0000644000175000017500000005643011764363406017074 0ustar alessioalessio/***************************************************************** * gmerlin - a general purpose multimedia framework and applications * * Copyright (c) 2001 - 2011 Members of the Gmerlin project * gmerlin-general@lists.sourceforge.net * http://gmerlin.sourceforge.net * * 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 of the License, 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 this program. If not, see . * *****************************************************************/ #include #include #include #include #include #include #include struct bg_gtk_slider_s { GdkPixbuf * pixbuf_background; GdkPixbuf * pixbuf_background_l; GdkPixbuf * pixbuf_background_r; GdkPixbuf * pixbuf_normal; GdkPixbuf * pixbuf_highlight; GdkPixbuf * pixbuf_pressed; GdkPixbuf * pixbuf_inactive; int x, y; int width, height; int vertical; /* State information */ int action; int mouse_inside; bg_gtk_slider_state_t state; int mouse_root; int total_size; int slider_size; int pos; void (*change_callback)(bg_gtk_slider_t*, float, void*); void * change_callback_data; void (*release_callback)(bg_gtk_slider_t*, float, void*); void * release_callback_data; void (*scroll_callback)(bg_gtk_slider_t*, int up, void*); void * scroll_callback_data; /* Widget stuff */ GtkWidget * background_layout; GtkWidget * slider_eventbox; GtkWidget * slider_image; }; /* Callbacks */ static gboolean button_press_callback(GtkWidget * w, GdkEventButton * evt, gpointer data) { bg_gtk_slider_t * s; s = (bg_gtk_slider_t *)data; if(s->state != BG_GTK_SLIDER_ACTIVE) return TRUE; gtk_image_set_from_pixbuf(GTK_IMAGE(s->slider_image), s->pixbuf_pressed); if(s->vertical) s->mouse_root = (int)(evt->y_root); else s->mouse_root = (int)(evt->x_root); s->action = 1; return TRUE; } //static void static gboolean button_release_callback(GtkWidget * w, GdkEventButton * evt, gpointer data) { bg_gtk_slider_t * s; int mouse_root_1; s = (bg_gtk_slider_t *)data; if(s->state != BG_GTK_SLIDER_ACTIVE) return TRUE; if(s->mouse_inside) gtk_image_set_from_pixbuf(GTK_IMAGE(s->slider_image), s->pixbuf_highlight); else gtk_image_set_from_pixbuf(GTK_IMAGE(s->slider_image), s->pixbuf_normal); s->action = 0; if(s->release_callback) { if(s->vertical) mouse_root_1 = (int)(evt->y_root); else mouse_root_1 = (int)(evt->x_root); s->pos += (mouse_root_1 - s->mouse_root); if(s->pos > s->total_size - s->slider_size) s->pos = s->total_size - s->slider_size; else if(s->pos < 0) s->pos = 0; if(s->vertical) gtk_layout_move(GTK_LAYOUT(s->background_layout), s->slider_eventbox, 0, s->pos); else gtk_layout_move(GTK_LAYOUT(s->background_layout), s->slider_eventbox, s->pos, 0); if(s->vertical) s->release_callback(s, 1.0 - (float)(s->pos)/(float)(s->total_size - s->slider_size), s->release_callback_data); else s->release_callback(s, (float)(s->pos)/(float)(s->total_size - s->slider_size), s->release_callback_data); } return TRUE; } static gboolean scroll_callback(GtkWidget * w, GdkEventScroll * evt, gpointer data) { bg_gtk_slider_t * s; s = (bg_gtk_slider_t *)data; if(s->state != BG_GTK_SLIDER_ACTIVE) return FALSE; if(s->scroll_callback) { s->scroll_callback(s, (evt->direction == GDK_SCROLL_UP), s->scroll_callback_data); } return TRUE; } static gboolean enter_notify_callback(GtkWidget *widget, GdkEventCrossing *event, gpointer data) { bg_gtk_slider_t * s; s = (bg_gtk_slider_t *)data; if(s->state != BG_GTK_SLIDER_ACTIVE) return FALSE; s->mouse_inside = 1; if(!s->action) gtk_image_set_from_pixbuf(GTK_IMAGE(s->slider_image), s->pixbuf_highlight); return FALSE; } static gboolean leave_notify_callback(GtkWidget *widget, GdkEventCrossing *event, gpointer data) { bg_gtk_slider_t * s; s = (bg_gtk_slider_t *)data; if(s->state != BG_GTK_SLIDER_ACTIVE) return FALSE; s->mouse_inside = 0; if(!s->action) gtk_image_set_from_pixbuf(GTK_IMAGE(s->slider_image), s->pixbuf_normal); return FALSE; } static gboolean motion_callback(GtkWidget * w, GdkEventMotion * evt, gpointer data) { bg_gtk_slider_t * s; int mouse_root_1; s = (bg_gtk_slider_t *)data; /* Buggy (newer) gtk versions send motion events even if no button is pressed */ if(!(evt->state & (GDK_BUTTON1_MASK|GDK_BUTTON2_MASK|GDK_BUTTON3_MASK))) return TRUE; if(s->state != BG_GTK_SLIDER_ACTIVE) return TRUE; if(s->vertical) mouse_root_1 = (int)(evt->y_root); else mouse_root_1 = (int)(evt->x_root); s->pos += (mouse_root_1 - s->mouse_root); if(s->pos > s->total_size - s->slider_size) s->pos = s->total_size - s->slider_size; else if(s->pos < 0) s->pos = 0; if(s->vertical) gtk_layout_move(GTK_LAYOUT(s->background_layout), s->slider_eventbox, 0, s->pos); else gtk_layout_move(GTK_LAYOUT(s->background_layout), s->slider_eventbox, s->pos, 0); if(s->change_callback) { if(s->vertical) s->change_callback(s, 1.0 - (float)(s->pos)/(float)(s->total_size - s->slider_size), s->change_callback_data); else s->change_callback(s, (float)(s->pos)/(float)(s->total_size - s->slider_size), s->change_callback_data); } s->mouse_root = mouse_root_1; return TRUE; } /* Set background image. We don't do this before the widget is realized */ static void set_background(bg_gtk_slider_t * s) { GdkPixmap * pixmap; if(!s->pixbuf_background_l || !s->pixbuf_background_r) { bg_gdk_pixbuf_render_pixmap_and_mask(s->pixbuf_background, &pixmap, NULL); s->width = gdk_pixbuf_get_width(s->pixbuf_background); s->height = gdk_pixbuf_get_height(s->pixbuf_background); } else { int width, height; if(!s->width || !s->height) return; pixmap = gdk_pixmap_new(GTK_LAYOUT(s->background_layout)->bin_window, s->width, s->height, -1); if(s->vertical) { int dest_y = 0, dest_y_end; width = gdk_pixbuf_get_width(s->pixbuf_background); height = gdk_pixbuf_get_height(s->pixbuf_background_l); /* Draw top */ gdk_draw_pixbuf(pixmap, NULL, s->pixbuf_background_l, 0, 0, 0, // gint dest_x, dest_y, // gint dest_y, width, height, GDK_RGB_DITHER_NONE, 0, 0); dest_y += height; dest_y_end = s->height - gdk_pixbuf_get_height(s->pixbuf_background_r); height = gdk_pixbuf_get_height(s->pixbuf_background); while(dest_y < dest_y_end) { if(dest_y + height > dest_y_end) height = dest_y_end - dest_y; gdk_draw_pixbuf(pixmap, NULL, s->pixbuf_background, 0, 0, 0, // gint dest_x, dest_y, // gint dest_y, width, height, GDK_RGB_DITHER_NONE, 0, 0); dest_y += height; } gdk_draw_pixbuf(pixmap, NULL, s->pixbuf_background_r, 0, 0, 0, // gint dest_x, dest_y, // gint dest_y, width, height, GDK_RGB_DITHER_NONE, 0, 0); } else { int dest_x = 0, dest_x_end; height = gdk_pixbuf_get_height(s->pixbuf_background); width = gdk_pixbuf_get_width(s->pixbuf_background_l); gdk_draw_pixbuf(pixmap, NULL, s->pixbuf_background_l, 0, 0, dest_x, 0, width, height, GDK_RGB_DITHER_NONE, 0, 0); dest_x += width; dest_x_end = s->width - gdk_pixbuf_get_width(s->pixbuf_background_r); width = gdk_pixbuf_get_width(s->pixbuf_background); while(dest_x < dest_x_end) { if(dest_x + width > dest_x_end) width = dest_x_end - dest_x; gdk_draw_pixbuf(pixmap, NULL, s->pixbuf_background, 0, 0, dest_x, // gint dest_x, 0, // gint dest_y, width, height, GDK_RGB_DITHER_NONE, 0, 0); dest_x += width; } gdk_draw_pixbuf(pixmap, NULL, s->pixbuf_background_r, 0, 0, dest_x, // gint dest_x, 0, // gint dest_y, width, height, GDK_RGB_DITHER_NONE, 0, 0); } } if(s->vertical) s->total_size = s->height; else s->total_size = s->width; bg_gtk_set_widget_bg_pixmap(s->background_layout, pixmap); g_object_unref(G_OBJECT(pixmap)); } static void set_shape(bg_gtk_slider_t * s) { GdkBitmap * mask; bg_gdk_pixbuf_render_pixmap_and_mask(s->pixbuf_normal, NULL, &mask); gtk_widget_shape_combine_mask(s->slider_eventbox, mask, 0, 0); if(mask) g_object_unref(G_OBJECT(mask)); } static void realize_callback(GtkWidget * w, gpointer data) { bg_gtk_slider_t * s; s = (bg_gtk_slider_t *)data; if((w == s->background_layout) && (s->pixbuf_background)) set_background(s); else if((w == s->slider_eventbox) && (s->pixbuf_normal)) set_shape(s); } static void size_allocate_callback(GtkWidget * w, GtkAllocation * evt, gpointer data) { double old_pos; bg_gtk_slider_t * s; s = (bg_gtk_slider_t *)data; if((s->width == evt->width) && (s->height == evt->height)) return; if(s->total_size) old_pos = (float)(s->pos)/(float)(s->total_size - s->slider_size); else old_pos = 0.0; s->width = evt->width; s->height = evt->height; if(s->pixbuf_background) set_background(s); if(s->vertical) s->total_size = evt->height; else s->total_size = evt->width; if(old_pos != 0.0) bg_gtk_slider_set_pos(s, old_pos); } bg_gtk_slider_t * bg_gtk_slider_create() { bg_gtk_slider_t * ret = calloc(1, sizeof(*ret)); // ret->vertical = vertical; /* Create objects */ ret->background_layout = gtk_layout_new(NULL, NULL); ret->slider_eventbox = gtk_event_box_new(); ret->slider_image = gtk_image_new_from_pixbuf(NULL); /* Set Attributes */ gtk_widget_set_events(ret->slider_eventbox, GDK_BUTTON1_MOTION_MASK| GDK_BUTTON2_MOTION_MASK| GDK_BUTTON3_MOTION_MASK| GDK_BUTTON_PRESS_MASK| GDK_ENTER_NOTIFY_MASK| GDK_LEAVE_NOTIFY_MASK); /* Set Callbacks */ g_signal_connect(G_OBJECT(ret->slider_eventbox), "button_press_event", G_CALLBACK (button_press_callback), ret); #if 0 g_signal_connect(G_OBJECT(ret->background_layout), "configure-event", G_CALLBACK(configure_callback), ret); #endif g_signal_connect(G_OBJECT(ret->background_layout), "size-allocate", G_CALLBACK (size_allocate_callback), ret); g_signal_connect(G_OBJECT(ret->background_layout), "scroll_event", G_CALLBACK (scroll_callback), ret); g_signal_connect(G_OBJECT(ret->slider_eventbox), "scroll_event", G_CALLBACK (scroll_callback), ret); g_signal_connect(G_OBJECT(ret->slider_eventbox), "button_release_event", G_CALLBACK (button_release_callback), ret); g_signal_connect(G_OBJECT(ret->slider_eventbox), "enter_notify_event", G_CALLBACK (enter_notify_callback), ret); g_signal_connect(G_OBJECT(ret->slider_eventbox), "leave_notify_event", G_CALLBACK (leave_notify_callback), ret); g_signal_connect(G_OBJECT(ret->slider_eventbox), "motion_notify_event", G_CALLBACK (motion_callback), ret); g_signal_connect(G_OBJECT(ret->slider_eventbox), "realize", G_CALLBACK (realize_callback), ret); g_signal_connect(G_OBJECT(ret->background_layout), "realize", G_CALLBACK (realize_callback), ret); /* Pack */ gtk_widget_show(ret->slider_image); gtk_container_add(GTK_CONTAINER(ret->slider_eventbox), ret->slider_image); // gtk_widget_show(ret->slider_eventbox); gtk_layout_put(GTK_LAYOUT(ret->background_layout), ret->slider_eventbox, 0, 0); gtk_widget_show(ret->background_layout); bg_gtk_slider_set_state(ret, BG_GTK_SLIDER_ACTIVE); return ret; } void bg_gtk_slider_set_state(bg_gtk_slider_t * s, bg_gtk_slider_state_t state) { s->state = state; switch(state) { case BG_GTK_SLIDER_ACTIVE: if(s->mouse_inside) gtk_image_set_from_pixbuf(GTK_IMAGE(s->slider_image), s->pixbuf_highlight); else gtk_image_set_from_pixbuf(GTK_IMAGE(s->slider_image), s->pixbuf_normal); gtk_widget_show(s->slider_eventbox); break; case BG_GTK_SLIDER_INACTIVE: gtk_image_set_from_pixbuf(GTK_IMAGE(s->slider_image), s->pixbuf_inactive); gtk_widget_show(s->slider_eventbox); break; case BG_GTK_SLIDER_HIDDEN: gtk_widget_hide(s->slider_eventbox); break; } } void bg_gtk_slider_destroy(bg_gtk_slider_t * s) { g_object_unref(s->pixbuf_background); if(s->pixbuf_background_l) g_object_unref(s->pixbuf_background_l); if(s->pixbuf_background_r) g_object_unref(s->pixbuf_background_r); g_object_unref(s->pixbuf_normal); g_object_unref(s->pixbuf_highlight); g_object_unref(s->pixbuf_pressed); g_object_unref(s->pixbuf_inactive); free(s); } /* Set attributes */ void bg_gtk_slider_set_change_callback(bg_gtk_slider_t * s, void (*func)(bg_gtk_slider_t *, float perc, void * data), void * data) { s->change_callback = func; s->change_callback_data = data; } void bg_gtk_slider_set_release_callback(bg_gtk_slider_t * s, void (*func)(bg_gtk_slider_t *, float perc, void * data), void * data) { s->release_callback = func; s->release_callback_data = data; } static GdkPixbuf * make_pixbuf(GdkPixbuf * old, const char * filename) { GdkPixbuf * ret; if(old) g_object_unref(G_OBJECT(old)); ret = gdk_pixbuf_new_from_file(filename, NULL); return ret; } void bg_gtk_slider_set_skin(bg_gtk_slider_t * s, bg_gtk_slider_skin_t * skin, const char * directory) { char * tmp_string = NULL; s->x = skin->x; s->y = skin->y; tmp_string = bg_sprintf("%s/%s", directory, skin->pixmap_normal); s->pixbuf_normal = make_pixbuf(s->pixbuf_normal, tmp_string); free(tmp_string); tmp_string = bg_sprintf("%s/%s", directory, skin->pixmap_highlight); s->pixbuf_highlight = make_pixbuf(s->pixbuf_highlight, tmp_string); free(tmp_string); tmp_string = bg_sprintf("%s/%s", directory, skin->pixmap_pressed); s->pixbuf_pressed = make_pixbuf(s->pixbuf_pressed, tmp_string); free(tmp_string); tmp_string = bg_sprintf("%s/%s", directory, skin->pixmap_inactive); s->pixbuf_inactive = make_pixbuf(s->pixbuf_inactive, tmp_string); free(tmp_string); tmp_string = bg_sprintf("%s/%s", directory, skin->pixmap_background); s->pixbuf_background = make_pixbuf(s->pixbuf_background, tmp_string); free(tmp_string); if(skin->pixmap_background_l) { tmp_string = bg_sprintf("%s/%s", directory, skin->pixmap_background_l); s->pixbuf_background_l = make_pixbuf(s->pixbuf_background_l, tmp_string); free(tmp_string); } if(skin->pixmap_background_r) { tmp_string = bg_sprintf("%s/%s", directory, skin->pixmap_background_r); s->pixbuf_background_r = make_pixbuf(s->pixbuf_background_r, tmp_string); free(tmp_string); } if(GTK_LAYOUT(s->background_layout)->bin_window) set_background(s); if(s->slider_eventbox->window) set_shape(s); gtk_image_set_from_pixbuf(GTK_IMAGE(s->slider_image), s->pixbuf_normal); /* Determine if it's a vertical or horizontal layout */ if(gdk_pixbuf_get_width(s->pixbuf_background) == gdk_pixbuf_get_width(s->pixbuf_normal)) { s->vertical = 1; s->total_size = gdk_pixbuf_get_height(s->pixbuf_background); s->slider_size = gdk_pixbuf_get_height(s->pixbuf_normal); } else { s->vertical = 0; s->total_size = gdk_pixbuf_get_width(s->pixbuf_background); s->slider_size = gdk_pixbuf_get_width(s->pixbuf_normal); } gtk_widget_set_size_request(s->slider_eventbox, gdk_pixbuf_get_width(s->pixbuf_normal), gdk_pixbuf_get_height(s->pixbuf_normal)); /* Request minimum size */ if(s->pixbuf_background_l && s->pixbuf_background_r) { if(s->vertical) { gtk_widget_set_size_request(s->background_layout, gdk_pixbuf_get_width(s->pixbuf_background), gdk_pixbuf_get_height(s->pixbuf_background_l)+ gdk_pixbuf_get_height(s->pixbuf_background_r)); } else { gtk_widget_set_size_request(s->background_layout, gdk_pixbuf_get_width(s->pixbuf_background_l)+ gdk_pixbuf_get_width(s->pixbuf_background_r), gdk_pixbuf_get_height(s->pixbuf_background)); } } else gtk_widget_set_size_request(s->background_layout, gdk_pixbuf_get_width(s->pixbuf_background), gdk_pixbuf_get_height(s->pixbuf_background)); } /* Get stuff */ void bg_gtk_slider_get_coords(bg_gtk_slider_t * s, int * x, int * y) { *x = s->x; *y = s->y; } GtkWidget * bg_gtk_slider_get_widget(bg_gtk_slider_t * s) { return s->background_layout; } GtkWidget * bg_gtk_slider_get_slider_widget(bg_gtk_slider_t * s) { return s->slider_eventbox; } void bg_gtk_slider_skin_load(bg_gtk_slider_skin_t * s, xmlDocPtr doc, xmlNodePtr node) { char * tmp_string; node = node->children; while(node) { if(!node->name) { node = node->next; continue; } tmp_string = (char*)xmlNodeListGetString(doc, node->children, 1); if(!BG_XML_STRCMP(node->name, "X")) s->x = atoi(tmp_string); else if(!BG_XML_STRCMP(node->name, "Y")) s->y = atoi(tmp_string); else if(!BG_XML_STRCMP(node->name, "NORMAL")) s->pixmap_normal = bg_strdup(s->pixmap_normal, tmp_string); else if(!BG_XML_STRCMP(node->name, "HIGHLIGHT")) s->pixmap_highlight = bg_strdup(s->pixmap_highlight, tmp_string); else if(!BG_XML_STRCMP(node->name, "PRESSED")) s->pixmap_pressed = bg_strdup(s->pixmap_pressed, tmp_string); else if(!BG_XML_STRCMP(node->name, "INACTIVE")) s->pixmap_inactive = bg_strdup(s->pixmap_inactive, tmp_string); else if(!BG_XML_STRCMP(node->name, "BACKGROUND")) s->pixmap_background = bg_strdup(s->pixmap_background, tmp_string); else if(!BG_XML_STRCMP(node->name, "BACKGROUND_L")) s->pixmap_background_l = bg_strdup(s->pixmap_background_l, tmp_string); else if(!BG_XML_STRCMP(node->name, "BACKGROUND_R")) s->pixmap_background_r = bg_strdup(s->pixmap_background_r, tmp_string); node = node->next; xmlFree(tmp_string); } } #define MY_FREE(ptr) if(ptr){free(ptr);ptr=NULL;} void bg_gtk_slider_skin_free(bg_gtk_slider_skin_t * s) { MY_FREE(s->pixmap_normal); MY_FREE(s->pixmap_highlight); MY_FREE(s->pixmap_pressed); MY_FREE(s->pixmap_inactive); MY_FREE(s->pixmap_background); MY_FREE(s->pixmap_background_l); MY_FREE(s->pixmap_background_r); } #undef MY_FREE void bg_gtk_slider_set_pos(bg_gtk_slider_t * s, float position) { if(s->action) return; if(s->vertical) s->pos = (int)((1.0 - position) * (float)(s->total_size - s->slider_size) + 0.5); else s->pos = (int)(position * (float)(s->total_size - s->slider_size) + 0.5); if(s->pos < 0) s->pos = 0; else if(s->pos > s->total_size - s->slider_size) s->pos = s->total_size - s->slider_size; if(s->vertical) gtk_layout_move(GTK_LAYOUT(s->background_layout), s->slider_eventbox, 0, s->pos); else gtk_layout_move(GTK_LAYOUT(s->background_layout), s->slider_eventbox, s->pos, 0); } void bg_gtk_slider_set_scroll_callback(bg_gtk_slider_t * s, void (*func)(bg_gtk_slider_t*, int up, void*), void* data) { s->scroll_callback = func; s->scroll_callback_data = data; } gmerlin-1.2.0~dfsg/lib/gtk/cfg_multi_menu.c0000644000175000017500000001710211764363406020600 0ustar alessioalessio/***************************************************************** * gmerlin - a general purpose multimedia framework and applications * * Copyright (c) 2001 - 2011 Members of the Gmerlin project * gmerlin-general@lists.sourceforge.net * http://gmerlin.sourceforge.net * * 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 of the License, 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 this program. If not, see . * *****************************************************************/ #include #include #include "gtk_dialog.h" #include #include #include typedef struct { GtkWidget * label; GtkWidget * combo; GtkWidget * config_button; GtkWidget * info_button; bg_set_parameter_func_t set_param; bg_get_parameter_func_t get_param; void * data; int selected; const char * translation_domain; } multi_menu_t; static void get_value(bg_gtk_widget_t * w) { int i; multi_menu_t * priv; priv = (multi_menu_t*)(w->priv); if(w->info->multi_names) { i = bg_parameter_get_selected(w->info, w->value.val_str); gtk_combo_box_set_active(GTK_COMBO_BOX(priv->combo), i); } } static void set_value(bg_gtk_widget_t * w) { multi_menu_t * priv; priv = (multi_menu_t*)(w->priv); if(w->info->multi_names) { w->value.val_str = bg_strdup(w->value.val_str, w->info->multi_names[priv->selected]); } else w->value.val_str = bg_strdup(w->value.val_str, NULL); } static void destroy(bg_gtk_widget_t * w) { multi_menu_t * priv = (multi_menu_t*)(w->priv); free(priv); } static void attach(void * priv, GtkWidget * table, int * row, int * num_columns) { GtkWidget * box; multi_menu_t * s = (multi_menu_t*)priv; if(*num_columns < 3) *num_columns = 3; box = gtk_hbox_new(0, 5); gtk_table_resize(GTK_TABLE(table), *row+1, *num_columns); // gtk_table_attach_defaults(GTK_TABLE(table), b->button, // 0, 1, *row, *row+1); gtk_table_attach(GTK_TABLE(table), s->label, 0, 1, *row, *row+1, GTK_FILL, GTK_SHRINK, 0, 0); gtk_table_attach(GTK_TABLE(table), s->combo, 1, 2, *row, *row+1, GTK_FILL|GTK_EXPAND, GTK_SHRINK, 0, 0); bg_gtk_box_pack_start_defaults(GTK_BOX(box), s->config_button); bg_gtk_box_pack_start_defaults(GTK_BOX(box), s->info_button); gtk_widget_show(box); gtk_table_attach(GTK_TABLE(table), box, 2, 3, *row, *row+1, GTK_FILL, GTK_SHRINK, 0, 0); (*row)++; } static const gtk_widget_funcs_t funcs = { .get_value = get_value, .set_value = set_value, .destroy = destroy, .attach = attach }; static GtkWidget * create_pixmap_button(const char * filename) { GtkWidget * button; GtkWidget * image; char * path; path = bg_search_file_read("icons", filename); if(path) { image = gtk_image_new_from_file(path); free(path); } else image = gtk_image_new(); gtk_widget_show(image); button = gtk_button_new(); gtk_container_add(GTK_CONTAINER(button), image); return button; } static void combo_box_change_callback(GtkWidget * wid, gpointer data) { bg_gtk_widget_t * w; multi_menu_t * priv; w = (bg_gtk_widget_t *)data; priv = (multi_menu_t *)(w->priv); priv->selected = gtk_combo_box_get_active(GTK_COMBO_BOX(priv->combo)); if(w->info->multi_parameters && w->info->multi_parameters[priv->selected]) gtk_widget_set_sensitive(priv->config_button, 1); else gtk_widget_set_sensitive(priv->config_button, 0); if(w->info->flags & BG_PARAMETER_SYNC) bg_gtk_change_callback(NULL, w); } static void button_callback(GtkWidget * wid, gpointer data) { bg_gtk_widget_t * w; multi_menu_t * priv; bg_dialog_t * dialog; const char * label; bg_cfg_section_t * subsection; w = (bg_gtk_widget_t *)data; priv = (multi_menu_t *)(w->priv); if(wid == priv->info_button) { bg_gtk_multi_info_show(w->info, priv->selected, priv->translation_domain, priv->info_button); } else if(wid == priv->config_button) { subsection = bg_cfg_section_find_subsection(w->cfg_section, w->info->name); subsection = bg_cfg_section_find_subsection(subsection, w->info->multi_names[priv->selected]); if(w->info->multi_labels && w->info->multi_labels[priv->selected]) label = TRD(w->info->multi_labels[priv->selected], priv->translation_domain); else label = w->info->multi_names[priv->selected]; if(priv->get_param) bg_cfg_section_get(subsection, w->info->multi_parameters[priv->selected], priv->get_param, priv->data); dialog = bg_dialog_create(subsection, priv->set_param, priv->get_param, priv->data, w->info->multi_parameters[priv->selected], label); bg_dialog_show(dialog, priv->config_button); } } void bg_gtk_create_multi_menu(bg_gtk_widget_t * w, bg_set_parameter_func_t set_param, bg_get_parameter_func_t get_param, void * data, const char * translation_domain) { int i; multi_menu_t * priv = calloc(1, sizeof(*priv)); priv->set_param = set_param; priv->get_param = get_param; priv->data = data; priv->translation_domain = translation_domain; w->funcs = &funcs; w->priv = priv; priv->config_button = create_pixmap_button("config_16.png"); priv->info_button = create_pixmap_button("info_16.png"); g_signal_connect(G_OBJECT(priv->config_button), "clicked", G_CALLBACK(button_callback), w); g_signal_connect(G_OBJECT(priv->info_button), "clicked", G_CALLBACK(button_callback), w); gtk_widget_show(priv->config_button); gtk_widget_show(priv->info_button); priv->combo = bg_gtk_combo_box_new_text(); if(w->info->help_string) { bg_gtk_tooltips_set_tip(priv->combo, w->info->help_string, translation_domain); } i = 0; if(w->info->multi_names) { while(w->info->multi_names[i]) { if(w->info->multi_labels && w->info->multi_labels[i]) bg_gtk_combo_box_append_text(priv->combo, TR_DOM(w->info->multi_labels[i])); else bg_gtk_combo_box_append_text(priv->combo, w->info->multi_names[i]); i++; } g_signal_connect(G_OBJECT(priv->combo), "changed", G_CALLBACK(combo_box_change_callback), (gpointer)w); } else { gtk_widget_set_sensitive(priv->config_button, 0); gtk_widget_set_sensitive(priv->info_button, 0); } gtk_widget_show(priv->combo); priv->label = gtk_label_new(TR_DOM(w->info->long_name)); gtk_misc_set_alignment(GTK_MISC(priv->label), 0.0, 0.5); gtk_widget_show(priv->label); } gmerlin-1.2.0~dfsg/lib/gtk/cfg_stringlist.c0000644000175000017500000001166211764363406020631 0ustar alessioalessio/***************************************************************** * gmerlin - a general purpose multimedia framework and applications * * Copyright (c) 2001 - 2011 Members of the Gmerlin project * gmerlin-general@lists.sourceforge.net * http://gmerlin.sourceforge.net * * 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 of the License, 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 this program. If not, see . * *****************************************************************/ #include #include #include #include "gtk_dialog.h" #include typedef struct { GtkWidget * label; GtkWidget * combo; int selected; const char * translation_domain; } stringlist_t; static void get_value(bg_gtk_widget_t * w) { stringlist_t * priv; priv = (stringlist_t*)(w->priv); priv->selected = bg_parameter_get_selected(w->info, w->value.val_str); gtk_combo_box_set_active(GTK_COMBO_BOX(priv->combo), priv->selected); } static void set_value(bg_gtk_widget_t * w) { stringlist_t * priv; priv = (stringlist_t*)(w->priv); w->value.val_str = bg_strdup(w->value.val_str, w->info->multi_names[priv->selected]); } static void destroy(bg_gtk_widget_t * w) { stringlist_t * priv = (stringlist_t*)(w->priv); free(priv); } static void attach(void * priv, GtkWidget * table, int * row, int * num_columns) { stringlist_t * s = (stringlist_t*)priv; if(*num_columns < 2) *num_columns = 2; gtk_table_resize(GTK_TABLE(table), *row+1, *num_columns); gtk_table_attach(GTK_TABLE(table), s->label, 0, 1, *row, *row+1, GTK_FILL, GTK_SHRINK, 0, 0); gtk_table_attach(GTK_TABLE(table), s->combo, 1, 2, *row, *row+1, GTK_FILL | GTK_EXPAND, GTK_SHRINK, 0, 0); (*row)++; } static const gtk_widget_funcs_t funcs = { .get_value = get_value, .set_value = set_value, .destroy = destroy, .attach = attach }; static void change_callback(GtkWidget * wid, gpointer data) { bg_gtk_widget_t * w; stringlist_t * priv; w = (bg_gtk_widget_t *)data; priv = (stringlist_t *)w->priv; priv->selected = gtk_combo_box_get_active(GTK_COMBO_BOX(priv->combo)); if(w->info->flags & BG_PARAMETER_SYNC) bg_gtk_change_callback(wid, data); } /* * Really dirty trick to get tooltips for a GtkComboBox working: * loop through all container children and set the tooltip for * the child, which is a button */ static void set_combo_tooltip(GtkWidget *widget, gpointer data) { bg_gtk_widget_t * w = (bg_gtk_widget_t *)data; stringlist_t * priv; priv = (stringlist_t *)w->priv; if(GTK_IS_BUTTON (widget)) bg_gtk_tooltips_set_tip(widget, w->info->help_string, priv->translation_domain); } static void realize_combo(GtkWidget *combo, gpointer data) { bg_gtk_widget_t * w = (bg_gtk_widget_t *)data; gtk_container_forall (GTK_CONTAINER (combo), set_combo_tooltip, w); } void bg_gtk_create_stringlist(bg_gtk_widget_t * w, const char * translation_domain) { int i; stringlist_t * priv = calloc(1, sizeof(*priv)); w->funcs = &funcs; w->priv = priv; priv->translation_domain = translation_domain; priv->combo = bg_gtk_combo_box_new_text(); i = 0; if(w->info->help_string) { g_signal_connect (priv->combo, "realize", G_CALLBACK (realize_combo), w); } if(w->info->multi_labels) { while(w->info->multi_labels[i]) { bg_gtk_combo_box_append_text(priv->combo, TR_DOM(w->info->multi_labels[i])); i++; } } else { while(w->info->multi_names[i]) { bg_gtk_combo_box_append_text(priv->combo, w->info->multi_names[i]); i++; } } w->callback_widget = priv->combo; w->callback_id = g_signal_connect(G_OBJECT(w->callback_widget), "changed", G_CALLBACK(change_callback), (gpointer)w); // GTK_WIDGET_UNSET_FLAGS(priv->combo, GTK_CAN_DEFAULT); gtk_widget_show(priv->combo); priv->label = gtk_label_new(TR_DOM(w->info->long_name)); gtk_misc_set_alignment(GTK_MISC(priv->label), 0.0, 0.5); gtk_widget_show(priv->label); } gmerlin-1.2.0~dfsg/lib/gtk/Makefile.in0000644000175000017500000006051511764363424017512 0ustar alessioalessio# Makefile.in generated by automake 1.11.1 from Makefile.am. # @configure_input@ # Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, # 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation, # Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ VPATH = @srcdir@ pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ subdir = lib/gtk DIST_COMMON = $(noinst_HEADERS) $(srcdir)/Makefile.am \ $(srcdir)/Makefile.in ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/m4/check_funcs.m4 \ $(top_srcdir)/m4/gavl_simd.m4 $(top_srcdir)/m4/gettext.m4 \ $(top_srcdir)/m4/iconv.m4 $(top_srcdir)/m4/lib-ld.m4 \ $(top_srcdir)/m4/lib-link.m4 $(top_srcdir)/m4/lib-prefix.m4 \ $(top_srcdir)/m4/lqt_opt_cflags.m4 $(top_srcdir)/m4/nls.m4 \ $(top_srcdir)/m4/po.m4 $(top_srcdir)/m4/progtest.m4 \ $(top_srcdir)/acinclude.m4 $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/include/config.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; am__vpath_adj = case $$p in \ $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ *) f=$$p;; \ esac; am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; am__install_max = 40 am__nobase_strip_setup = \ srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` am__nobase_strip = \ for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" am__nobase_list = $(am__nobase_strip_setup); \ for p in $$list; do echo "$$p $$p"; done | \ sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ if (++n[$$2] == $(am__install_max)) \ { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ END { for (dir in files) print dir, files[dir] }' am__base_list = \ sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' am__installdirs = "$(DESTDIR)$(libdir)" LTLIBRARIES = $(lib_LTLIBRARIES) libgmerlin_gtk_la_DEPENDENCIES = $(top_builddir)/lib/libgmerlin.la am_libgmerlin_gtk_la_OBJECTS = aboutwindow.lo albumentry.lo \ albumwidget.lo albumwindow.lo auth.lo button.lo cfg_button.lo \ cfg_checkbutton.lo cfg_color.lo cfg_device.lo cfg_dialog.lo \ cfg_file.lo cfg_font.lo cfg_multi_list.lo cfg_multi_menu.lo \ cfg_position.lo cfg_slider.lo cfg_spinbutton.lo cfg_string.lo \ cfg_stringlist.lo cfg_time.lo chapterdialog.lo display.lo \ driveselect.lo fileselect.lo fileentry.lo gtkutils.lo \ infowindow.lo logwindow.lo message.lo multiinfo.lo \ plugininfo.lo plugin_multi.lo plugin_single.lo pluginmenu.lo \ presetmenu.lo question.lo slider.lo scrolltext.lo textview.lo \ textwindow.lo treewidget.lo treewindow.lo urllink.lo \ urlselect.lo vumeter.lo libgmerlin_gtk_la_OBJECTS = $(am_libgmerlin_gtk_la_OBJECTS) libgmerlin_gtk_la_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ $(libgmerlin_gtk_la_LDFLAGS) $(LDFLAGS) -o $@ DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)/include depcomp = $(SHELL) $(top_srcdir)/depcomp am__depfiles_maybe = depfiles am__mv = mv -f COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) LTCOMPILE = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \ --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) CCLD = $(CC) LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \ --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \ $(LDFLAGS) -o $@ SOURCES = $(libgmerlin_gtk_la_SOURCES) DIST_SOURCES = $(libgmerlin_gtk_la_SOURCES) HEADERS = $(noinst_HEADERS) ETAGS = etags CTAGS = ctags DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ ALSA_CFLAGS = @ALSA_CFLAGS@ ALSA_LIBS = @ALSA_LIBS@ ALSA_REQUIRED = @ALSA_REQUIRED@ AMTAR = @AMTAR@ AR = @AR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ BG_VERSION = @BG_VERSION@ BG_VERSION_MAJOR = @BG_VERSION_MAJOR@ BG_VERSION_MICRO = @BG_VERSION_MICRO@ BG_VERSION_MINOR = @BG_VERSION_MINOR@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CDDB_CFLAGS = @CDDB_CFLAGS@ CDDB_LIBS = @CDDB_LIBS@ CDIO_CDDA_CFLAGS = @CDIO_CDDA_CFLAGS@ CDIO_CDDA_LIBS = @CDIO_CDDA_LIBS@ CDIO_CFLAGS = @CDIO_CFLAGS@ CDIO_LIBS = @CDIO_LIBS@ CDIO_PARANOIA_CFLAGS = @CDIO_PARANOIA_CFLAGS@ CDIO_PARANOIA_LIBS = @CDIO_PARANOIA_LIBS@ CDIO_REQUIRED = @CDIO_REQUIRED@ CFLAGS = @CFLAGS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CYGPATH_W = @CYGPATH_W@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DOXYGEN = @DOXYGEN@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ ESD_CFLAGS = @ESD_CFLAGS@ ESD_CONFIG = @ESD_CONFIG@ ESD_LIBS = @ESD_LIBS@ ESD_REQUIRED = @ESD_REQUIRED@ EXEEXT = @EXEEXT@ FGREP = @FGREP@ FONTCONFIG_CFLAGS = @FONTCONFIG_CFLAGS@ FONTCONFIG_LIBS = @FONTCONFIG_LIBS@ FREETYPE_CFLAGS = @FREETYPE_CFLAGS@ FREETYPE_LIBS = @FREETYPE_LIBS@ GAVL_CFLAGS = @GAVL_CFLAGS@ GAVL_LIBS = @GAVL_LIBS@ GAVL_REQUIRED = @GAVL_REQUIRED@ GLX_CFLAGS = @GLX_CFLAGS@ GLX_LIBS = @GLX_LIBS@ GL_CFLAGS = @GL_CFLAGS@ GL_LIBS = @GL_LIBS@ GMERLIN_DEP_LIBS = @GMERLIN_DEP_LIBS@ GMERLIN_PLUGIN_LDFLAGS = @GMERLIN_PLUGIN_LDFLAGS@ GMSGFMT = @GMSGFMT@ GMSGFMT_015 = @GMSGFMT_015@ GREP = @GREP@ GTK_CFLAGS = @GTK_CFLAGS@ GTK_LIBS = @GTK_LIBS@ GTK_REQUIRED = @GTK_REQUIRED@ ICONV_LIBS = @ICONV_LIBS@ INCLUDES = -I$(top_srcdir)/include INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ INTLLIBS = @INTLLIBS@ INTL_MACOSX_LIBS = @INTL_MACOSX_LIBS@ JACK_CFLAGS = @JACK_CFLAGS@ JACK_LIBS = @JACK_LIBS@ JACK_REQUIRED = @JACK_REQUIRED@ JPEG_CFLAGS = @JPEG_CFLAGS@ JPEG_LIBS = @JPEG_LIBS@ JPEG_REQUIRED = @JPEG_REQUIRED@ LD = @LD@ LDFLAGS = @LDFLAGS@ LIBCDDB_REQUIRED = @LIBCDDB_REQUIRED@ LIBEXIF_CFLAGS = @LIBEXIF_CFLAGS@ LIBEXIF_LIBS = @LIBEXIF_LIBS@ LIBICONV = @LIBICONV@ LIBINTL = @LIBINTL@ LIBM = @LIBM@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIPO = @LIPO@ LN_S = @LN_S@ LQT_CFLAGS = @LQT_CFLAGS@ LQT_LIBS = @LQT_LIBS@ LQT_REQUIRED = @LQT_REQUIRED@ LTLIBICONV = @LTLIBICONV@ LTLIBINTL = @LTLIBINTL@ LTLIBOBJS = @LTLIBOBJS@ LTVERSION_AGE = @LTVERSION_AGE@ LTVERSION_CURRENT = @LTVERSION_CURRENT@ LTVERSION_REVISION = @LTVERSION_REVISION@ LV_CFLAGS = @LV_CFLAGS@ LV_LIBS = @LV_LIBS@ LV_REQUIRED = @LV_REQUIRED@ MAKEINFO = @MAKEINFO@ MKDIR_P = @MKDIR_P@ MODULE_LIBADD = @MODULE_LIBADD@ MSGFMT = @MSGFMT@ MSGFMT_015 = @MSGFMT_015@ MSGMERGE = @MSGMERGE@ MUSICBRAINZ_CFLAGS = @MUSICBRAINZ_CFLAGS@ MUSICBRAINZ_LIBS = @MUSICBRAINZ_LIBS@ MUSICBRAINZ_REQUIRED = @MUSICBRAINZ_REQUIRED@ NM = @NM@ NMEDIT = @NMEDIT@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OTOOL = @OTOOL@ OTOOL64 = @OTOOL64@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PKG_CONFIG = @PKG_CONFIG@ PNG_CFLAGS = @PNG_CFLAGS@ PNG_LIBS = @PNG_LIBS@ PNG_REQUIRED = @PNG_REQUIRED@ POSUB = @POSUB@ PULSEAUDIO_CFLAGS = @PULSEAUDIO_CFLAGS@ PULSEAUDIO_LIBS = @PULSEAUDIO_LIBS@ PULSEAUDIO_REQUIRED = @PULSEAUDIO_REQUIRED@ RANLIB = @RANLIB@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ SQLITE3_LIBS = @SQLITE3_LIBS@ STRIP = @STRIP@ TEXINFO = @TEXINFO@ TIFF_CFLAGS = @TIFF_CFLAGS@ TIFF_LIBS = @TIFF_LIBS@ TIFF_REQUIRED = @TIFF_REQUIRED@ TOP_SRCDIR = @TOP_SRCDIR@ USE_NLS = @USE_NLS@ V4LCONVERT_CFLAGS = @V4LCONVERT_CFLAGS@ V4LCONVERT_LIBS = @V4LCONVERT_LIBS@ V4LCONVERT_REQUIRED = @V4LCONVERT_REQUIRED@ VERSION = @VERSION@ XDPMS_LIBS = @XDPMS_LIBS@ XFIXES_LIBS = @XFIXES_LIBS@ XGETTEXT = @XGETTEXT@ XGETTEXT_015 = @XGETTEXT_015@ XINERAMA_LIBS = @XINERAMA_LIBS@ XMKMF = @XMKMF@ XML2_CFLAGS = @XML2_CFLAGS@ XML2_LIBS = @XML2_LIBS@ XML2_REQUIRED = @XML2_REQUIRED@ XTEST_LIBS = @XTEST_LIBS@ XV_LIBS = @XV_LIBS@ X_CFLAGS = @X_CFLAGS@ X_LIBS = @X_LIBS@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_CC = @ac_ct_CC@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_vendor = @build_vendor@ builddir = @builddir@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ lt_ECHO = @lt_ECHO@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ plugindir = $(pkglibdir)/plugins AM_CFLAGS = \ @GTK_CFLAGS@ \ @FREETYPE_CFLAGS@ \ @FONTCONFIG_CFLAGS@ \ -DLOCALE_DIR=\"$(localedir)\" \ -DPLUGIN_DIR=\"$(plugindir)\" \ -DDOC_DIR=\"$(docdir)\" \ -DDATA_DIR=\"$(pkgdatadir)\" libgmerlin_gtk_la_LDFLAGS = -version-info @LTVERSION_CURRENT@:@LTVERSION_REVISION@:@LTVERSION_AGE@ lib_LTLIBRARIES = libgmerlin_gtk.la noinst_HEADERS = gtk_dialog.h libgmerlin_gtk_la_SOURCES = \ aboutwindow.c \ albumentry.c \ albumwidget.c \ albumwindow.c \ auth.c \ button.c \ cfg_button.c \ cfg_checkbutton.c \ cfg_color.c \ cfg_device.c \ cfg_dialog.c \ cfg_file.c \ cfg_font.c \ cfg_multi_list.c \ cfg_multi_menu.c \ cfg_position.c \ cfg_slider.c \ cfg_spinbutton.c \ cfg_string.c \ cfg_stringlist.c \ cfg_time.c \ chapterdialog.c \ display.c \ driveselect.c \ fileselect.c \ fileentry.c \ gtkutils.c \ infowindow.c \ logwindow.c \ message.c \ multiinfo.c \ plugininfo.c \ plugin_multi.c \ plugin_single.c \ pluginmenu.c \ presetmenu.c \ question.c \ slider.c \ scrolltext.c \ textview.c \ textwindow.c \ treewidget.c \ treewindow.c \ urllink.c \ urlselect.c \ vumeter.c libgmerlin_gtk_la_LIBADD = @GTK_LIBS@ $(top_builddir)/lib/libgmerlin.la @XML2_LIBS@ @LIBM@ all: all-am .SUFFIXES: .SUFFIXES: .c .lo .o .obj $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ && { if test -f $@; then exit 0; else break; fi; }; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu lib/gtk/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --gnu lib/gtk/Makefile .PRECIOUS: Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): install-libLTLIBRARIES: $(lib_LTLIBRARIES) @$(NORMAL_INSTALL) test -z "$(libdir)" || $(MKDIR_P) "$(DESTDIR)$(libdir)" @list='$(lib_LTLIBRARIES)'; test -n "$(libdir)" || list=; \ list2=; for p in $$list; do \ if test -f $$p; then \ list2="$$list2 $$p"; \ else :; fi; \ done; \ test -z "$$list2" || { \ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(libdir)'"; \ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(libdir)"; \ } uninstall-libLTLIBRARIES: @$(NORMAL_UNINSTALL) @list='$(lib_LTLIBRARIES)'; test -n "$(libdir)" || list=; \ for p in $$list; do \ $(am__strip_dir) \ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(libdir)/$$f'"; \ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(libdir)/$$f"; \ done clean-libLTLIBRARIES: -test -z "$(lib_LTLIBRARIES)" || rm -f $(lib_LTLIBRARIES) @list='$(lib_LTLIBRARIES)'; for p in $$list; do \ dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \ test "$$dir" != "$$p" || dir=.; \ echo "rm -f \"$${dir}/so_locations\""; \ rm -f "$${dir}/so_locations"; \ done libgmerlin_gtk.la: $(libgmerlin_gtk_la_OBJECTS) $(libgmerlin_gtk_la_DEPENDENCIES) $(libgmerlin_gtk_la_LINK) -rpath $(libdir) $(libgmerlin_gtk_la_OBJECTS) $(libgmerlin_gtk_la_LIBADD) $(LIBS) mostlyclean-compile: -rm -f *.$(OBJEXT) distclean-compile: -rm -f *.tab.c @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/aboutwindow.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/albumentry.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/albumwidget.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/albumwindow.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/auth.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/button.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cfg_button.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cfg_checkbutton.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cfg_color.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cfg_device.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cfg_dialog.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cfg_file.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cfg_font.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cfg_multi_list.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cfg_multi_menu.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cfg_position.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cfg_slider.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cfg_spinbutton.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cfg_string.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cfg_stringlist.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cfg_time.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/chapterdialog.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/display.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/driveselect.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fileentry.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fileselect.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gtkutils.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/infowindow.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/logwindow.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/message.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/multiinfo.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/plugin_multi.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/plugin_single.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/plugininfo.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pluginmenu.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/presetmenu.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/question.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/scrolltext.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/slider.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/textview.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/textwindow.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/treewidget.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/treewindow.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/urllink.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/urlselect.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/vumeter.Plo@am__quote@ .c.o: @am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(COMPILE) -c $< .c.obj: @am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(COMPILE) -c `$(CYGPATH_W) '$<'` .c.lo: @am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(LTCOMPILE) -c -o $@ $< mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | \ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in files) print i; }; }'`; \ mkid -fID $$unique tags: TAGS TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ $(TAGS_FILES) $(LISP) set x; \ here=`pwd`; \ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | \ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in files) print i; }; }'`; \ shift; \ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ test -n "$$unique" || unique=$$empty_fix; \ if test $$# -gt 0; then \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ "$$@" $$unique; \ else \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ $$unique; \ fi; \ fi ctags: CTAGS CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ $(TAGS_FILES) $(LISP) list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | \ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in files) print i; }; }'`; \ test -z "$(CTAGS_ARGS)$$unique" \ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ $$unique GTAGS: here=`$(am__cd) $(top_builddir) && pwd` \ && $(am__cd) $(top_srcdir) \ && gtags -i $(GTAGS_ARGS) "$$here" distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags distdir: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done check-am: all-am check: check-am all-am: Makefile $(LTLIBRARIES) $(HEADERS) installdirs: for dir in "$(DESTDIR)$(libdir)"; do \ test -z "$$dir" || $(MKDIR_P) "$$dir"; \ done install: install-am install-exec: install-exec-am install-data: install-data-am uninstall: uninstall-am install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-am install-strip: $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ `test -z '$(STRIP)' || \ echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install mostlyclean-generic: clean-generic: distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." clean: clean-am clean-am: clean-generic clean-libLTLIBRARIES clean-libtool \ mostlyclean-am distclean: distclean-am -rm -rf ./$(DEPDIR) -rm -f Makefile distclean-am: clean-am distclean-compile distclean-generic \ distclean-tags dvi: dvi-am dvi-am: html: html-am html-am: info: info-am info-am: install-data-am: install-dvi: install-dvi-am install-dvi-am: install-exec-am: install-libLTLIBRARIES install-html: install-html-am install-html-am: install-info: install-info-am install-info-am: install-man: install-pdf: install-pdf-am install-pdf-am: install-ps: install-ps-am install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-am -rm -rf ./$(DEPDIR) -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-compile mostlyclean-generic \ mostlyclean-libtool pdf: pdf-am pdf-am: ps: ps-am ps-am: uninstall-am: uninstall-libLTLIBRARIES .MAKE: install-am install-strip .PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \ clean-libLTLIBRARIES clean-libtool ctags distclean \ distclean-compile distclean-generic distclean-libtool \ distclean-tags distdir dvi dvi-am html html-am info info-am \ install install-am install-data install-data-am install-dvi \ install-dvi-am install-exec install-exec-am install-html \ install-html-am install-info install-info-am \ install-libLTLIBRARIES install-man install-pdf install-pdf-am \ install-ps install-ps-am install-strip installcheck \ installcheck-am installdirs maintainer-clean \ maintainer-clean-generic mostlyclean mostlyclean-compile \ mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ tags uninstall uninstall-am uninstall-libLTLIBRARIES # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: gmerlin-1.2.0~dfsg/lib/gtk/cfg_spinbutton.c0000644000175000017500000001232011764363406020624 0ustar alessioalessio/***************************************************************** * gmerlin - a general purpose multimedia framework and applications * * Copyright (c) 2001 - 2011 Members of the Gmerlin project * gmerlin-general@lists.sourceforge.net * http://gmerlin.sourceforge.net * * 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 of the License, 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 this program. If not, see . * *****************************************************************/ #include #include "gtk_dialog.h" #include typedef struct { GtkWidget * label; GtkWidget * spinbutton; GtkObject * adj; } spinbutton_t; /* typedef enum { GTK_EXPAND = 1 << 0, GTK_SHRINK = 1 << 1, GTK_FILL = 1 << 2 } GtkAttachOptions; */ static void destroy(bg_gtk_widget_t * w) { spinbutton_t * s = (spinbutton_t*)(w->priv); free(s); } static void get_value_int(bg_gtk_widget_t * w) { spinbutton_t * s = (spinbutton_t*)(w->priv); gtk_spin_button_set_value(GTK_SPIN_BUTTON(s->spinbutton), (gdouble)(w->value.val_i)); } static void set_value_int(bg_gtk_widget_t * w) { spinbutton_t * s = (spinbutton_t*)(w->priv); w->value.val_i = gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(s->spinbutton)); } static void get_value_float(bg_gtk_widget_t * w) { spinbutton_t * s = (spinbutton_t*)(w->priv); gtk_spin_button_set_value(GTK_SPIN_BUTTON(s->spinbutton), w->value.val_f); } static void set_value_float(bg_gtk_widget_t * w) { spinbutton_t * s = (spinbutton_t*)(w->priv); w->value.val_f = gtk_spin_button_get_value(GTK_SPIN_BUTTON(s->spinbutton)); } static void attach(void * priv, GtkWidget * table, int * row, int * num_columns) { spinbutton_t * s = (spinbutton_t*)priv; if(*num_columns < 2) *num_columns = 2; gtk_table_resize(GTK_TABLE(table), *row + 1, *num_columns); gtk_table_attach(GTK_TABLE(table), s->label, 0, 1, *row, *row+1, GTK_FILL, GTK_SHRINK, 0, 0); gtk_table_attach(GTK_TABLE(table), s->spinbutton, 1, 2, *row, *row+1, GTK_FILL | GTK_EXPAND, GTK_SHRINK, 0, 0); *row += 1; } static const gtk_widget_funcs_t int_funcs = { .get_value = get_value_int, .set_value = set_value_int, .destroy = destroy, .attach = attach }; static const gtk_widget_funcs_t float_funcs = { .get_value = get_value_float, .set_value = set_value_float, .destroy = destroy, .attach = attach }; static void create_common(bg_gtk_widget_t * w, const bg_parameter_info_t * info, float min_value, float max_value, const char * translation_domain) { spinbutton_t * s = calloc(1, sizeof(*s)); s->label = gtk_label_new(TR_DOM(info->long_name)); gtk_widget_show(s->label); gtk_misc_set_alignment(GTK_MISC(s->label), 0.0, 0.5); s->adj = gtk_adjustment_new(min_value, min_value, max_value, 1.0, 0.0, 0.0); s->spinbutton = gtk_spin_button_new(GTK_ADJUSTMENT(s->adj), 0.1, 0); if(info->flags & BG_PARAMETER_SYNC) { w->callback_id = g_signal_connect(G_OBJECT(s->spinbutton), "value-changed", G_CALLBACK(bg_gtk_change_callback), (gpointer)w); w->callback_widget = s->spinbutton; } if(info->help_string) { bg_gtk_tooltips_set_tip(s->spinbutton, info->help_string, translation_domain); } gtk_widget_show(s->spinbutton); gtk_widget_show(s->label); w->priv = s; } void bg_gtk_create_int(bg_gtk_widget_t * w, const char * translation_domain) { float min_value; float max_value; spinbutton_t * s; min_value = (float)(w->info->val_min.val_i); max_value = (float)(w->info->val_max.val_i); if(min_value >= max_value) { min_value = -1.0; max_value = 1.0e9; } w->funcs = &int_funcs; create_common(w, w->info, min_value, max_value, translation_domain ); s = (spinbutton_t *)(w->priv); } void bg_gtk_create_float(bg_gtk_widget_t * w, const char * translation_domain) { float min_value; float max_value; spinbutton_t * s; min_value = (float)(w->info->val_min.val_f); max_value = (float)(w->info->val_max.val_f); if(min_value >= max_value) { min_value = 0.0; max_value = 100000.0; } w->funcs = &float_funcs; create_common(w, w->info, min_value, max_value, translation_domain ); s = (spinbutton_t *)(w->priv); bg_gtk_change_callback_block(w, 1); gtk_spin_button_set_digits(GTK_SPIN_BUTTON(s->spinbutton), w->info->num_digits); bg_gtk_change_callback_block(w, 0); } gmerlin-1.2.0~dfsg/lib/gtk/scrolltext.c0000644000175000017500000002612011764363406020006 0ustar alessioalessio/***************************************************************** * gmerlin - a general purpose multimedia framework and applications * * Copyright (c) 2001 - 2011 Members of the Gmerlin project * gmerlin-general@lists.sourceforge.net * http://gmerlin.sourceforge.net * * 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 of the License, 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 this program. If not, see . * *****************************************************************/ #include #include #include #include #include #include #include #define TIMEOUT_INTERVAL 30 #define SCROLL_ADVANCE 1 struct bg_gtk_scrolltext_s { int width; int height; int offset; int text_width; int is_realized; char * text; float foreground_color[3]; float background_color[3]; int do_scroll; gulong timeout_tag; PangoFontDescription* font_desc; GtkWidget * drawingarea; GdkPixmap * pixmap_string; /* Pixmap for the whole string */ GdkPixmap * pixmap_da; /* Pixmap for the drawingarea */ GdkGC * gc; int pixmap_width; int pixmap_height; }; static void set_color(bg_gtk_scrolltext_t * st, float * color, GdkColor * gdk_color) { if(!st->is_realized) return; gdk_color->red = (guint16)(color[0] * 65535.0); gdk_color->green = (guint16)(color[1] * 65535.0); gdk_color->blue = (guint16)(color[2] * 65535.0); gdk_color->pixel = ((gdk_color->red >> 8) << 16) | ((gdk_color->green >> 8) << 8) | ((gdk_color->blue >> 8)); gdk_color_alloc(gdk_window_get_colormap(st->drawingarea->window), gdk_color); } static void create_text_pixmap(bg_gtk_scrolltext_t * st); static gboolean expose_callback(GtkWidget * w, GdkEventExpose * evt, gpointer data) { bg_gtk_scrolltext_t * st = (bg_gtk_scrolltext_t *)data; if(st->pixmap_da) gdk_draw_drawable(st->drawingarea->window, st->gc, st->pixmap_da, 0, 0, 0, 0, st->width, st->height); return TRUE; } static void size_allocate_callback(GtkWidget * w, GtkAllocation * evt, gpointer data) //static gboolean configure_callback(GtkWidget * w, GdkEventConfigure * evt, // gpointer data) { GdkColor bg; bg_gtk_scrolltext_t * st = (bg_gtk_scrolltext_t *)data; if((st->width == evt->width) && (st->height == evt->height) && (st->pixmap_da)) return; st->width = evt->width; st->height = evt->height; if(!st->is_realized) return; if(st->pixmap_da) { if((st->pixmap_width < evt->width) || (st->pixmap_height < evt->height)) { /* Enlarge pixmap */ st->pixmap_width = evt->width + 10; st->pixmap_height = evt->height + 10; g_object_unref(st->pixmap_da); st->pixmap_da = gdk_pixmap_new(st->drawingarea->window, st->pixmap_width, st->pixmap_height, -1); } /* Put pixmap_string onto pixmap_da if we won't scroll */ if(st->width >= st->text_width) { set_color(st, st->background_color, &bg); gdk_gc_set_foreground(st->gc, &bg); gdk_draw_rectangle(st->pixmap_da, st->gc, TRUE, 0, 0, st->width, st->height); if(st->pixmap_string) gdk_draw_drawable(st->pixmap_da, st->gc, st->pixmap_string, 0, 0, (st->width - st->text_width)/2, 0, st->text_width, st->height); } } else { st->pixmap_width = evt->width + 10; st->pixmap_height = evt->height + 10; st->pixmap_da = gdk_pixmap_new(st->drawingarea->window, st->pixmap_width, st->pixmap_height, -1); if(st->text) create_text_pixmap(st); } if(((st->width < st->text_width) && !st->do_scroll) || ((st->width >= st->text_width) && st->do_scroll) || !st->pixmap_string) { create_text_pixmap(st); } // expose_callback(w, NULL, data); return; } static gboolean timeout_func(gpointer data) { bg_gtk_scrolltext_t * st = (bg_gtk_scrolltext_t*)data; if(!st->do_scroll) return FALSE; st->offset += SCROLL_ADVANCE; if(st->offset > st->text_width) st->offset = 0; if(st->text_width - st->offset < st->width) { gdk_draw_drawable(st->pixmap_da, st->gc, st->pixmap_string, st->offset, 0, 0, 0, st->text_width - st->offset, st->height); gdk_draw_drawable(st->pixmap_da, st->gc, st->pixmap_string, 0, 0, st->text_width - st->offset, 0, st->width - (st->text_width - st->offset), st->height); } else { gdk_draw_drawable(st->pixmap_da, st->gc, st->pixmap_string, st->offset, 0, 0, 0, st->width, st->height); } expose_callback(st->drawingarea, NULL, st); return TRUE; } static void create_text_pixmap(bg_gtk_scrolltext_t * st) { char * tmp_string; PangoLayout * layout; GdkColor fg; GdkColor bg; PangoRectangle ink_rect; PangoRectangle logical_rect; int height; if(!st->is_realized || !st->width || ! st->height) return; /* Create pango layout */ layout = gtk_widget_create_pango_layout(st->drawingarea, st->text); if(st->font_desc) pango_layout_set_font_description(layout, st->font_desc); /* Set Colors */ set_color(st, st->foreground_color, &fg); set_color(st, st->background_color, &bg); /* Remove previous timeout callbacks */ if(st->do_scroll) { g_source_remove(st->timeout_tag); st->do_scroll = 0; st->timeout_tag = 0; } /* Set up pixmap */ pango_layout_get_extents(layout, &ink_rect, &logical_rect); st->text_width = logical_rect.width / PANGO_SCALE; height = logical_rect.height / PANGO_SCALE; /* Change string if necessary */ if(st->text_width > st->width) { st->do_scroll = 1; tmp_string = bg_sprintf("%s * * * ", st->text); pango_layout_set_text(layout, tmp_string, -1); pango_layout_get_extents(layout, &ink_rect, &logical_rect); st->text_width = logical_rect.width / PANGO_SCALE; height = logical_rect.height / PANGO_SCALE; free(tmp_string); } else st->do_scroll = 0; /* Set up Pixmap */ if(st->pixmap_string) g_object_unref(G_OBJECT(st->pixmap_string)); st->pixmap_string = gdk_pixmap_new(st->drawingarea->window, st->text_width, st->height, -1); gdk_gc_set_foreground(st->gc, &bg); gdk_draw_rectangle(st->pixmap_string, st->gc, TRUE, 0, 0, st->text_width, st->height); gdk_gc_set_foreground(st->gc, &fg); gdk_draw_layout(st->pixmap_string, st->gc, 0, (st->height - height)/2, layout); if(!st->do_scroll) { gdk_gc_set_foreground(st->gc, &bg); gdk_draw_rectangle(st->pixmap_da, st->gc, TRUE, 0, 0, st->width, st->height); gdk_draw_drawable(st->pixmap_da, st->gc, st->pixmap_string, 0, 0, (st->width - st->text_width)/2, 0, st->text_width, st->height); } else { st->timeout_tag = g_timeout_add(TIMEOUT_INTERVAL, timeout_func, st); } g_object_unref(layout); expose_callback(st->drawingarea, NULL, st); } static void realize_callback(GtkWidget * w, gpointer data) { bg_gtk_scrolltext_t * st = (bg_gtk_scrolltext_t *)data; st->is_realized = 1; st->gc = gdk_gc_new(st->drawingarea->window); if(!st->pixmap_da) { GtkAllocation a; a.width = st->width; a.height = st->height; size_allocate_callback(w, &a, data); } } bg_gtk_scrolltext_t * bg_gtk_scrolltext_create(int width, int height) { bg_gtk_scrolltext_t * ret; ret = calloc(1, sizeof(*ret)); ret->drawingarea = gtk_drawing_area_new(); if((width >= 0) && (height >= 0)) { // ret->width = width; // ret->height = height; gtk_widget_set_size_request(ret->drawingarea, width, height); } else { gtk_widget_set_size_request(ret->drawingarea, 16, 16); } g_signal_connect(G_OBJECT(ret->drawingarea), "realize", G_CALLBACK(realize_callback), ret); g_signal_connect(G_OBJECT(ret->drawingarea), "expose-event", G_CALLBACK(expose_callback), ret); // g_signal_connect(G_OBJECT(ret->drawingarea), // "configure-event", G_CALLBACK(configure_callback), // ret); g_signal_connect(G_OBJECT(ret->drawingarea), "size-allocate", G_CALLBACK(size_allocate_callback), ret); gtk_widget_show(ret->drawingarea); return ret; } void bg_gtk_scrolltext_set_text(bg_gtk_scrolltext_t * d, const char * text, const float * foreground_color, const float * background_color) { d->text = bg_strdup(d->text, text); memcpy(d->foreground_color, foreground_color, 3 * sizeof(float)); memcpy(d->background_color, background_color, 3 * sizeof(float)); create_text_pixmap(d); } void bg_gtk_scrolltext_set_colors(bg_gtk_scrolltext_t * d, const float * fg_color, const float * bg_color) { memcpy(d->foreground_color, fg_color, 3 * sizeof(float)); memcpy(d->background_color, bg_color, 3 * sizeof(float)); create_text_pixmap(d); } void bg_gtk_scrolltext_set_font(bg_gtk_scrolltext_t * d, const char * font) { char * tmp; if(d->font_desc) pango_font_description_free(d->font_desc); tmp = bg_gtk_convert_font_name_to_pango(font); d->font_desc = pango_font_description_from_string(tmp); free(tmp); } void bg_gtk_scrolltext_destroy(bg_gtk_scrolltext_t * d) { if(d->timeout_tag) g_source_remove(d->timeout_tag); if(d->font_desc) pango_font_description_free(d->font_desc); if(d->text) free(d->text); if(d->pixmap_string) g_object_unref(d->pixmap_string); if(d->pixmap_da) g_object_unref(d->pixmap_da); if(d->gc) g_object_unref(d->gc); free(d); } GtkWidget * bg_gtk_scrolltext_get_widget(bg_gtk_scrolltext_t * d) { return d->drawingarea; } gmerlin-1.2.0~dfsg/lib/gtk/cfg_device.c0000644000175000017500000002300511764363406017660 0ustar alessioalessio/***************************************************************** * gmerlin - a general purpose multimedia framework and applications * * Copyright (c) 2001 - 2011 Members of the Gmerlin project * gmerlin-general@lists.sourceforge.net * http://gmerlin.sourceforge.net * * 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 of the License, 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 this program. If not, see . * *****************************************************************/ #include #include #include #include #include "gtk_dialog.h" #include enum { COLUMN_DEVICE, NUM_COLUMNS }; typedef struct { GtkWidget * treeview; GtkWidget * add_button; GtkWidget * delete_button; GtkWidget * scrolled; GtkWidget * fileselect; int selected; } device_t; static void get_value(bg_gtk_widget_t * w) { int i; device_t * priv; GtkTreeSelection * selection; GtkTreeIter iter; GtkTreeModel * model; char ** tmp_items; priv = (device_t*)(w->priv); model = gtk_tree_view_get_model(GTK_TREE_VIEW(priv->treeview)); selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(priv->treeview)); gtk_list_store_clear(GTK_LIST_STORE(model)); if(!w->value.val_str || (*w->value.val_str == '\0')) return; tmp_items = bg_strbreak(w->value.val_str, ' '); i = 0; while(tmp_items[i]) { gtk_list_store_append(GTK_LIST_STORE(model), &iter); gtk_list_store_set(GTK_LIST_STORE(model), &iter, COLUMN_DEVICE, tmp_items[i], -1); if(!i) gtk_tree_selection_select_iter(selection, &iter); i++; } bg_strbreak_free(tmp_items); } static void set_value(bg_gtk_widget_t * w) { device_t * priv; GtkTreeSelection * selection; GtkTreeIter iter; GtkTreeModel * model; int num_entries; int selected; char ** strings; int len; int index; int i, imax; priv = (device_t*)(w->priv); model = gtk_tree_view_get_model(GTK_TREE_VIEW(priv->treeview)); if(!gtk_tree_model_get_iter_first(model, &iter)) { if(w->value.val_str) { free(w->value.val_str); w->value.val_str = NULL; } return; } num_entries = 1; while(gtk_tree_model_iter_next(model, &iter)) num_entries++; /* Copy the strings */ selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(priv->treeview)); strings = malloc(num_entries * sizeof(char*)); len = 0; selected = -1; gtk_tree_model_get_iter_first(model, &iter); for(i = 0; i < num_entries; i++) { gtk_tree_model_get(model, &iter, COLUMN_DEVICE, &strings[i], -1); if(gtk_tree_selection_iter_is_selected(selection, &iter)) { selected = i; } gtk_tree_model_iter_next(model, &iter); len += strlen(strings[i])+1; } /* Copy to the value */ if(w->value.val_str) free(w->value.val_str); w->value.val_str = malloc(len); w->value.val_str[0] = '\0'; if(selected >= 0) { strcat(w->value.val_str, strings[selected]); if(num_entries > 1) strcat(w->value.val_str, " "); imax = num_entries-1; } else imax = num_entries; index = 0; for(i = 0; i < imax; i++) { if(index == selected) index++; strcat(w->value.val_str, strings[index]); if(i < imax - 1) strcat(w->value.val_str, ":"); index++; } for(i = 0; i < num_entries; i++) { g_free(strings[i]); } free(strings); } static void destroy(bg_gtk_widget_t * w) { device_t * priv = (device_t*)w->priv; if(priv->fileselect) gtk_widget_destroy(priv->fileselect); free(priv); } static void attach(void * priv, GtkWidget * table, int * row, int * num_columns) { device_t * f = (device_t*)priv; if(*num_columns < 3) *num_columns = 3; gtk_table_resize(GTK_TABLE(table), *row+3, *num_columns); gtk_table_attach_defaults(GTK_TABLE(table), f->scrolled, 0, 2, *row, *row+3); gtk_table_attach(GTK_TABLE(table), f->add_button, 2, 3, *row, *row+1, GTK_FILL, GTK_SHRINK, 0, 0); gtk_table_attach(GTK_TABLE(table), f->delete_button, 2, 3, *row+1, *row+2, GTK_FILL, GTK_SHRINK, 0, 0); *row += 3; } static const gtk_widget_funcs_t funcs = { .get_value = get_value, .set_value = set_value, .destroy = destroy, .attach = attach }; static void fileselect_callback(GtkWidget *chooser, gint response_id, gpointer data) { device_t * priv; GtkTreeIter iter; gchar *uri; priv = (device_t*)data; if(response_id == GTK_RESPONSE_OK) { GtkTreeModel * model; uri = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER (chooser)); model = gtk_tree_view_get_model(GTK_TREE_VIEW(priv->treeview)); gtk_list_store_append(GTK_LIST_STORE(model), &iter); gtk_list_store_set(GTK_LIST_STORE(model), &iter, COLUMN_DEVICE, uri, -1); g_free (uri); } // gtk_widget_destroy (chooser); gtk_widget_hide(priv->fileselect); gtk_main_quit(); } static gboolean fileselect_delete_callback(GtkWidget * w, GdkEventAny * event, gpointer data) { fileselect_callback(w, GTK_RESPONSE_CANCEL, data); return TRUE; } static void button_callback(GtkWidget * w, gpointer data) { device_t * priv; GtkTreeSelection * selection; GtkTreeModel * model; GtkWidget * toplevel; GtkTreeIter iter; priv = (device_t*)data; if(w == priv->add_button) { if(!priv->fileselect) { toplevel = bg_gtk_get_toplevel(w); priv->fileselect = gtk_file_chooser_dialog_new (TRD("Select a device", PACKAGE), GTK_WINDOW(toplevel), GTK_FILE_CHOOSER_ACTION_OPEN, GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, GTK_STOCK_OK, GTK_RESPONSE_OK, NULL); gtk_window_set_modal(GTK_WINDOW(priv->fileselect), TRUE); g_signal_connect(priv->fileselect, "response", G_CALLBACK(fileselect_callback), (gpointer)priv); g_signal_connect(G_OBJECT(priv->fileselect), "delete_event", G_CALLBACK(fileselect_delete_callback), (gpointer)priv); } gtk_widget_show(priv->fileselect); gtk_main(); } else if(w == priv->delete_button) { selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(priv->treeview)); if(!gtk_tree_selection_get_selected(selection, &model, &iter)) return; gtk_list_store_remove(GTK_LIST_STORE(model), &iter); } } void bg_gtk_create_device(bg_gtk_widget_t * w, const char * translation_domain) { GtkListStore *store; GtkCellRenderer *renderer; GtkTreeViewColumn *column; GtkTreeSelection * selection; device_t * priv = calloc(1, sizeof(*priv)); priv->selected = -1; store = gtk_list_store_new (NUM_COLUMNS, G_TYPE_STRING); priv->treeview = gtk_tree_view_new_with_model(GTK_TREE_MODEL(store)); if(w->info->help_string) { bg_gtk_tooltips_set_tip(priv->treeview, w->info->help_string, translation_domain); } /* Add the columns */ renderer = gtk_cell_renderer_text_new (); column = gtk_tree_view_column_new_with_attributes ("Devices", renderer, "text", COLUMN_DEVICE, NULL); gtk_tree_view_column_set_sort_column_id (column, COLUMN_DEVICE); gtk_tree_view_append_column (GTK_TREE_VIEW(priv->treeview), column); /* Set Selection mode */ selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(priv->treeview)); gtk_tree_selection_set_mode(selection, GTK_SELECTION_SINGLE); priv->add_button = gtk_button_new_with_label(TR("Add...")); priv->delete_button = gtk_button_new_with_label(TR("Delete")); g_signal_connect(G_OBJECT(priv->add_button), "clicked", G_CALLBACK(button_callback), (gpointer)priv); g_signal_connect(G_OBJECT(priv->delete_button), "clicked", G_CALLBACK(button_callback), (gpointer)priv); gtk_widget_show(priv->add_button); gtk_widget_show(priv->delete_button); gtk_widget_show(priv->treeview); priv->scrolled = gtk_scrolled_window_new(gtk_tree_view_get_hadjustment(GTK_TREE_VIEW(priv->treeview)), gtk_tree_view_get_vadjustment(GTK_TREE_VIEW(priv->treeview))); gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(priv->scrolled), GTK_POLICY_NEVER, GTK_POLICY_ALWAYS); gtk_container_add(GTK_CONTAINER(priv->scrolled), priv->treeview); gtk_widget_show(priv->scrolled); w->funcs = &funcs; w->priv = priv; } gmerlin-1.2.0~dfsg/lib/searchpath.c0000644000175000017500000001371611764363410017142 0ustar alessioalessio/***************************************************************** * gmerlin - a general purpose multimedia framework and applications * * Copyright (c) 2001 - 2011 Members of the Gmerlin project * gmerlin-general@lists.sourceforge.net * http://gmerlin.sourceforge.net * * 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 of the License, 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 this program. If not, see . * *****************************************************************/ #include #include #include #include #include #include #include #include #include #include #include #include #define LOG_DOMAIN "utils" char * bg_search_file_read(const char * directory, const char * file) { char * testpath; char * home_dir; FILE * testfile; if(!file) return NULL; testpath = malloc(FILENAME_MAX * sizeof(char)); /* First step: Try home directory */ home_dir = getenv("HOME"); if(home_dir) { sprintf(testpath, "%s/.%s/%s/%s", home_dir, PACKAGE, directory, file); testfile = fopen(testpath, "r"); if(testfile) { fclose(testfile); return testpath; } } /* Second step: Try Data directory */ sprintf(testpath, "%s/%s/%s", DATA_DIR, directory, file); testfile = fopen(testpath, "r"); if(testfile) { fclose(testfile); return testpath; } free(testpath); return NULL; } char * bg_search_file_write(const char * directory, const char * file) { char * home_dir; char * testpath; char * testdir; FILE * testfile; if(!file) return NULL; home_dir = getenv("HOME"); /* Try to open the file */ testdir = bg_sprintf("%s/.%s/%s", home_dir, PACKAGE, directory); if(!bg_ensure_directory(testdir)) { free(testdir); return NULL; } testpath = bg_sprintf("%s/%s", testdir, file); testfile = fopen(testpath, "a"); if(testfile) { fclose(testfile); free(testdir); return testpath; } else { free(testpath); free(testdir); return NULL; } } int bg_ensure_directory(const char * dir) { char ** directories; char * subpath = NULL; int i, ret; int absolute; /* Return early */ if(!access(dir, R_OK|W_OK|X_OK)) return 1; if(dir[0] == '/') absolute = 1; else absolute = 0; /* We omit the first slash */ if(absolute) directories = bg_strbreak(dir+1, '/'); else directories = bg_strbreak(dir, '/'); i = 0; ret = 1; while(directories[i]) { if(i || absolute) subpath = bg_strcat(subpath, "/"); subpath = bg_strcat(subpath, directories[i]); if(access(subpath, R_OK) && (errno == ENOENT)) { if(mkdir(subpath, S_IRUSR|S_IWUSR|S_IXUSR) == -1) { bg_log(BG_LOG_ERROR, LOG_DOMAIN, "Creating directory %s failed: %s", subpath, strerror(errno)); ret = 0; break; } else bg_log(BG_LOG_INFO, LOG_DOMAIN, "Created directory %s", subpath); } i++; } if(subpath) free(subpath); bg_strbreak_free(directories); return ret; } int bg_search_file_exec(const char * file, char ** _path) { int i; char * path; char ** searchpaths; char * test_filename; struct stat st; /* Try the dependencies path first */ test_filename = bg_sprintf("/opt/gmerlin/bin/%s", file); if(!stat(test_filename, &st) && (st.st_mode & S_IXOTH)) { if(_path) *_path = test_filename; else free(test_filename); return 1; } free(test_filename); path = getenv("PATH"); if(!path) return 0; searchpaths = bg_strbreak(path, ':'); i = 0; while(searchpaths[i]) { test_filename = bg_sprintf("%s/%s", searchpaths[i], file); if(!stat(test_filename, &st) && (st.st_mode & S_IXOTH)) { if(_path) *_path = test_filename; else free(test_filename); bg_strbreak_free(searchpaths); return 1; } free(test_filename); i++; } bg_strbreak_free(searchpaths); return 0; } static const struct { char * command; char * template; } webbrowsers[] = { { "firefox", "firefox %s" }, { "mozilla", "mozilla %s" }, }; char * bg_find_url_launcher() { int i; char * ret = NULL; int ret_alloc = 0; bg_subprocess_t * proc; /* Try to get the default url handler from gnome */ if(bg_search_file_exec("gconftool-2", NULL)) { proc = bg_subprocess_create("gconftool-2 -g /desktop/gnome/url-handlers/http/command", 0, 1, 0); if(bg_subprocess_read_line(proc->stdout_fd, &ret, &ret_alloc, -1)) { bg_subprocess_close(proc); return ret; } else if(ret) free(ret); bg_subprocess_close(proc); } for(i = 0; i < sizeof(webbrowsers)/sizeof(webbrowsers[0]); i++) { if(bg_search_file_exec(webbrowsers[i].command, NULL)) { return bg_strdup(NULL, webbrowsers[i].template); } } return NULL; } void bg_display_html_help(const char * path) { char * url_launcher; char * complete_path; char * command; url_launcher = bg_find_url_launcher(); if(!url_launcher) return; complete_path = bg_sprintf("file://%s/%s", DOC_DIR, path); command = bg_sprintf(url_launcher, complete_path); command = bg_strcat(command, " &"); bg_system(command); free(command); free(url_launcher); free(complete_path); } gmerlin-1.2.0~dfsg/lib/device.c0000644000175000017500000000416311764363410016253 0ustar alessioalessio/***************************************************************** * gmerlin - a general purpose multimedia framework and applications * * Copyright (c) 2001 - 2011 Members of the Gmerlin project * gmerlin-general@lists.sourceforge.net * http://gmerlin.sourceforge.net * * 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 of the License, 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 this program. If not, see . * *****************************************************************/ /* Handling of input devices */ #include #include #include #include #include #include #include #include bg_device_info_t * bg_device_info_append(bg_device_info_t * arr, const char * device, const char * name) { int i, size = 0; char * real_device; if(arr) { while(arr[size].device) size++; } real_device = bg_canonical_filename(device); for(i = 0; i < size; i++) { if(!strcmp(arr[i].device, real_device)) { free(real_device); return arr; } } size++; arr = realloc(arr, (size+1) * sizeof(*arr)); arr[size-1].device = real_device; arr[size-1].name = bg_strdup(NULL, name); /* Zero terminate */ memset(&arr[size], 0, sizeof(arr[size])); return arr; } void bg_device_info_destroy(bg_device_info_t * arr) { int i = 0; if(!arr) return; while(arr[i].device) { free(arr[i].device); if(arr[i].name) free(arr[i].name); i++; } free(arr); } gmerlin-1.2.0~dfsg/lib/ocr.c0000644000175000017500000002260611764363410015601 0ustar alessioalessio/***************************************************************** * gmerlin - a general purpose multimedia framework and applications * * Copyright (c) 2001 - 2011 Members of the Gmerlin project * gmerlin-general@lists.sourceforge.net * http://gmerlin.sourceforge.net * * 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 of the License, 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 this program. If not, see . * *****************************************************************/ #include #include #include #include #include #include #include #include #include #define LOG_DOMAIN "ocr" typedef struct { const char * name; int (*supported)(bg_plugin_registry_t * plugin_reg); int (*init)(bg_ocr_t * ocr, gavl_video_format_t*); int (*run)(bg_ocr_t * ocr, const gavl_video_format_t*,gavl_video_frame_t*,char ** ret); } ocr_funcs_t; static int supported_tesseract(bg_plugin_registry_t * plugin_reg); static int init_tesseract(bg_ocr_t *, gavl_video_format_t *); static int run_tesseract(bg_ocr_t *, const gavl_video_format_t *, gavl_video_frame_t*,char ** ret); static ocr_funcs_t ocr_funcs[] = { { .name = "tesseract", .supported = supported_tesseract, .init = init_tesseract, .run = run_tesseract, }, { /* */ } }; struct bg_ocr_s { gavl_video_converter_t * cnv; gavl_video_options_t * opt; bg_plugin_registry_t * plugin_reg; int do_convert; char lang[4]; gavl_video_format_t in_format; gavl_video_format_t out_format; ocr_funcs_t * funcs; bg_plugin_handle_t * iw_handle; bg_image_writer_plugin_t * iw_plugin; gavl_video_frame_t * out_frame; bg_iw_callbacks_t cb; char * image_file; char * tmpdir; }; static int create_output_file(void * priv, const char * name) { bg_ocr_t * ocr = priv; ocr->image_file = bg_strdup(ocr->image_file, name); bg_log(BG_LOG_DEBUG, LOG_DOMAIN, "Writing image file %s", name); return 1; } static int load_image_writer(bg_ocr_t * ocr, const char * plugin) { const bg_plugin_info_t * info; if(ocr->iw_handle) { bg_plugin_unref(ocr->iw_handle); ocr->iw_handle = NULL; } info = bg_plugin_find_by_name(ocr->plugin_reg, plugin); ocr->iw_handle = bg_plugin_load(ocr->plugin_reg, info); if(!ocr->iw_handle) return 0; ocr->iw_plugin = (bg_image_writer_plugin_t*)ocr->iw_handle->plugin; if(ocr->iw_plugin->set_callbacks) ocr->iw_plugin->set_callbacks(ocr->iw_handle->priv, &ocr->cb); return 1; } bg_ocr_t * bg_ocr_create(bg_plugin_registry_t * plugin_reg) { int i; bg_ocr_t * ret; ocr_funcs_t * funcs = NULL; i = 0; while(ocr_funcs[i].name) { if(ocr_funcs[i].supported(plugin_reg)) funcs = &ocr_funcs[i]; i++; } if(!funcs) { bg_log(BG_LOG_ERROR, LOG_DOMAIN, "No engine found"); return NULL; } ret = calloc(1, sizeof(*ret)); ret->cb.data = ret; ret->cb.create_output_file = create_output_file; ret->cnv = gavl_video_converter_create(); ret->opt = gavl_video_converter_get_options(ret->cnv); gavl_video_options_set_alpha_mode(ret->opt, GAVL_ALPHA_BLEND_COLOR); ret->plugin_reg = plugin_reg; ret->funcs = funcs; return ret; } const bg_parameter_info_t parameters[] = { { \ .name = "background_color", \ .long_name = TRS("Background color"), \ .type = BG_PARAMETER_COLOR_RGB, \ .val_default = { .val_color = { 0.0, 0.0, 0.0 } }, \ .help_string = TRS("Background color to use, when converting formats with transparency to grayscale"), \ }, { \ .name = "tmpdir", \ .long_name = TRS("Temporary directory"), \ .type = BG_PARAMETER_DIRECTORY, \ .val_default = { .val_str = "/tmp" }, \ .help_string = TRS("Temporary directory for image files"), \ }, { /* End */ } }; const bg_parameter_info_t * bg_ocr_get_parameters() { return parameters; } int bg_ocr_set_parameter(void * data, const char * name, const bg_parameter_value_t * val) { bg_ocr_t * ocr = data; if(!name) return 1; else if(!strcmp(name, "background_color")) { gavl_video_options_set_background_color(ocr->opt, val->val_color); return 1; } else if(!strcmp(name, "tmpdir")) { ocr->tmpdir = bg_strdup(ocr->tmpdir, val->val_str); return 1; } return 0; } int bg_ocr_init(bg_ocr_t * ocr, const gavl_video_format_t * format, const char * language) { if(ocr->out_frame) { gavl_video_frame_destroy(ocr->out_frame); ocr->out_frame = NULL; } gavl_video_format_copy(&ocr->in_format, format); gavl_video_format_copy(&ocr->out_format, format); /* Get pixelformat for conversion */ if(language && (language[0] != '\0')) strncpy(ocr->lang, language, 3); if(!ocr->funcs->init(ocr, &ocr->out_format)) return 0; /* Initialize converter */ ocr->do_convert = gavl_video_converter_init(ocr->cnv, &ocr->in_format, &ocr->out_format); if(ocr->do_convert) ocr->out_frame = gavl_video_frame_create(&ocr->out_format); return 1; } int bg_ocr_run(bg_ocr_t * ocr, const gavl_video_format_t * format, gavl_video_frame_t * frame, char ** ret) { int result; gavl_video_format_t tmp_format; if(ocr->do_convert) { gavl_video_format_copy(&tmp_format, format); tmp_format.pixelformat = ocr->out_format.pixelformat; gavl_video_converter_init(ocr->cnv, &ocr->in_format, &tmp_format); gavl_video_convert(ocr->cnv, frame, ocr->out_frame); result = ocr->funcs->run(ocr, &tmp_format, ocr->out_frame, ret); } else result = ocr->funcs->run(ocr, format, frame, ret); if(!result || (**ret == '\0')) { if(*ret) free(*ret); bg_log(BG_LOG_WARNING, LOG_DOMAIN, "OCR failed, keeping %s", ocr->image_file); *ret = ocr->image_file; ocr->image_file = NULL; } else { if(ocr->image_file) { bg_log(BG_LOG_DEBUG, LOG_DOMAIN, "Removing %s", ocr->image_file); remove(ocr->image_file); free(ocr->image_file); ocr->image_file = NULL; } } return result; } void bg_ocr_destroy(bg_ocr_t * ocr) { if(ocr->cnv) gavl_video_converter_destroy(ocr->cnv); if(ocr->out_frame) gavl_video_frame_destroy(ocr->out_frame); if(ocr->iw_handle) bg_plugin_unref(ocr->iw_handle); if(ocr->image_file) free(ocr->image_file); if(ocr->tmpdir) free(ocr->tmpdir); free(ocr); } /* Tesseract */ static int supported_tesseract(bg_plugin_registry_t * plugin_reg) { if(!bg_search_file_exec("tesseract", NULL)) return 0; if(!bg_plugin_find_by_name(plugin_reg, "iw_tiff")) return 0; return 1; } static int init_tesseract(bg_ocr_t * ocr, gavl_video_format_t * format) { format->pixelformat = GAVL_GRAY_8; if(!ocr->iw_handle) { if(!load_image_writer(ocr, "iw_tiff")) return 0; } return 1; } static int run_tesseract(bg_ocr_t * ocr, const gavl_video_format_t * format, gavl_video_frame_t * frame, char ** ret) { char * pos; char * commandline = NULL; gavl_video_format_t tmp_format; char * tiff_file = NULL; char * text_file = NULL; char * base = NULL; int result = 0; char * template = bg_sprintf("%s/gmerlin_ocr_%%05d.tif", ocr->tmpdir); /* Create name for tiff file */ tiff_file = bg_create_unique_filename(template); free(template); if(!tiff_file) return 0; base = bg_strdup(NULL, tiff_file); pos = strrchr(base, '.'); if(!pos) return 0; *pos = '\0'; /* Create name for text file */ text_file = bg_sprintf("%s.txt", base); /* Save image */ gavl_video_format_copy(&tmp_format, format); if(!ocr->iw_plugin->write_header(ocr->iw_handle->priv, base, &tmp_format, NULL)) goto fail; if(!ocr->iw_plugin->write_image(ocr->iw_handle->priv, frame)) goto fail; commandline = bg_sprintf("tesseract %s %s", ocr->image_file, base); if(ocr->lang[0] != '\0') { commandline = bg_strcat(commandline, " -l "); commandline = bg_strcat(commandline, bg_iso639_b_to_t(ocr->lang)); } if(bg_system(commandline)) goto fail; *ret = bg_read_file(text_file, NULL); if(!(*ret)) goto fail; pos = (*ret) + (strlen(*ret)-1); while(isspace(*pos) && (pos >= *ret)) { *pos = '\0'; pos--; } result = 1; fail: if(tiff_file) free(tiff_file); if(base) free(base); if(text_file) { remove(text_file); free(text_file); } if(commandline) free(commandline); return result; } gmerlin-1.2.0~dfsg/lib/player_ov.c0000644000175000017500000003155611764363410017022 0ustar alessioalessio/***************************************************************** * gmerlin - a general purpose multimedia framework and applications * * Copyright (c) 2001 - 2011 Members of the Gmerlin project * gmerlin-general@lists.sourceforge.net * http://gmerlin.sourceforge.net * * 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 of the License, 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 this program. If not, see . * *****************************************************************/ #include #include #include #include #include #include #include #include #define LOG_DOMAIN "player.video_output" // #define DUMP_TIMESTAMPS static int accel_callback(void * data, int id) { bg_player_t * p = data; bg_player_accel_pressed(p, id); return 1; } static int button_callback(void * data, int x, int y, int button, int mask) { bg_player_t * p = data; if(button == 4) { bg_player_seek_rel(p, 2 * GAVL_TIME_SCALE ); return 1; } else if(button == 5) { bg_player_seek_rel(p, - 2 * GAVL_TIME_SCALE ); return 1; } return 0; } static void brightness_callback(void * data, float val) { bg_player_t * p = data; bg_osd_set_brightness_changed(p->video_stream.osd, val, p->video_stream.frame_time); } static void saturation_callback(void * data, float val) { bg_player_t * p = data; bg_osd_set_saturation_changed(p->video_stream.osd, val, p->video_stream.frame_time); } static void contrast_callback(void * data, float val) { bg_player_t * p = data; bg_osd_set_contrast_changed(p->video_stream.osd, val, p->video_stream.frame_time); } static void handle_messages(bg_player_video_stream_t * ctx, gavl_time_t time) { bg_msg_t * msg; int id; float arg_f; while((msg = bg_msg_queue_try_lock_read(ctx->msg_queue))) { id = bg_msg_get_id(msg); switch(id) { case BG_PLAYER_MSG_VOLUME_CHANGED: arg_f = bg_msg_get_arg_float(msg, 0); if(ctx->osd_ovl) bg_osd_set_volume_changed(ctx->osd, (arg_f - BG_PLAYER_VOLUME_MIN)/ (-BG_PLAYER_VOLUME_MIN), time); break; default: break; } bg_msg_queue_unlock_read(ctx->msg_queue); } } void bg_player_ov_create(bg_player_t * player) { bg_player_video_stream_t * s = &player->video_stream; s->callbacks.accel_callback = accel_callback; s->callbacks.button_callback = button_callback; s->callbacks.brightness_callback = brightness_callback; s->callbacks.saturation_callback = saturation_callback; s->callbacks.contrast_callback = contrast_callback; s->callbacks.data = player; s->callbacks.accel_map = s->accel_map; } void bg_player_add_accelerators(bg_player_t * player, const bg_accelerator_t * list) { bg_accelerator_map_append_array(player->video_stream.accel_map, list); } void bg_player_ov_standby(bg_player_video_stream_t * ctx) { if(!ctx->ov) return; bg_ov_show_window(ctx->ov, 0); } void bg_player_ov_set_plugin(bg_player_t * player, bg_plugin_handle_t * handle) { bg_player_video_stream_t * ctx; ctx = &player->video_stream; if(ctx->ov) { bg_ov_destroy(ctx->ov); ctx->ov = NULL; } if(handle) { ctx->ov = bg_ov_create(handle); bg_ov_set_callbacks(ctx->ov, &ctx->callbacks); /* ov holds a private reference */ bg_plugin_unref(handle); } } void bg_player_ov_destroy(bg_player_t * player) { bg_player_video_stream_t * ctx = &player->video_stream; if(ctx->ov) bg_ov_destroy(ctx->ov); } int bg_player_ov_init(bg_player_video_stream_t * vs) { int result; result = bg_ov_open(vs->ov, &vs->output_format, 1); bg_ov_set_window_title(vs->ov, "Video output"); if(result) bg_ov_show_window(vs->ov, 1); else if(!result) return result; memset(&vs->osd_format, 0, sizeof(vs->osd_format)); bg_osd_init(vs->osd, &vs->output_format, &vs->osd_format); /* Fixme: Lets just hope, that the OSD format doesn't get changed by this call. Otherwise, we would need a gavl_video_converter */ vs->osd_id = bg_ov_add_overlay_stream(vs->ov, &vs->osd_format); /* create_overlay needs the lock again */ /* Create frame */ if(vs->osd_id >= 0) { vs->osd_ovl = bg_ov_create_overlay(vs->ov, vs->osd_id); bg_osd_set_overlay(vs->osd, vs->osd_ovl); } vs->frames_written = 0; return result; } static int overlay_is_expired(gavl_overlay_t * ovl, gavl_time_t frame_time) { if((ovl->frame->duration > 0) && (ovl->frame->timestamp + ovl->frame->duration < frame_time)) { return 1; } return 0; } static int overlay_is_early(gavl_overlay_t * ovl, gavl_time_t frame_time) { if(ovl->frame->timestamp > frame_time) return 1; return 0; } static void handle_subtitle(bg_player_t * p) { bg_player_video_stream_t * s = &p->video_stream; gavl_overlay_t * swp; /* Check if subtitle expired */ if(s->subtitle_active && overlay_is_expired(s->ss->current_subtitle, s->frame_time)) { bg_ov_set_overlay(s->ov, s->subtitle_id, NULL); /* Make invalid */ s->ss->current_subtitle->frame->timestamp = GAVL_TIME_UNDEFINED; s->subtitle_active = 0; /* Swap */ swp = s->ss->current_subtitle; s->ss->current_subtitle = s->ss->next_subtitle; s->ss->next_subtitle = swp; } /* Try to read as many subtitles as possible */ if((s->ss->current_subtitle->frame->timestamp == GAVL_TIME_UNDEFINED) && bg_player_has_subtitle(p) && !s->ss->eof) { if(!bg_player_read_subtitle(p, s->ss->current_subtitle)) s->ss->eof = 1; } if((s->ss->next_subtitle->frame->timestamp == GAVL_TIME_UNDEFINED) && bg_player_has_subtitle(p) && !s->ss->eof) { if(!bg_player_read_subtitle(p, s->ss->next_subtitle)) s->ss->eof = 1; } /* Check if the current subtitle became valid */ if(!s->subtitle_active && (s->ss->current_subtitle->frame->timestamp != GAVL_TIME_UNDEFINED) && !overlay_is_early(s->ss->current_subtitle, s->frame_time)) { bg_ov_set_overlay(s->ov, s->subtitle_id, s->ss->current_subtitle); s->subtitle_active = 1; } /* Check if the next subtitle became valid */ else if((s->ss->next_subtitle->frame->timestamp != GAVL_TIME_UNDEFINED) && !overlay_is_early(s->ss->next_subtitle, s->frame_time)) { if(s->subtitle_active) { s->ss->current_subtitle->frame->timestamp = GAVL_TIME_UNDEFINED; } /* Swap */ swp = s->ss->current_subtitle; s->ss->current_subtitle = s->ss->next_subtitle; s->ss->next_subtitle = swp; bg_ov_set_overlay(s->ov, s->subtitle_id, s->ss->current_subtitle); s->subtitle_active = 1; } } void bg_player_ov_update_still(bg_player_t * p) { gavl_video_frame_t * frame; bg_player_video_stream_t * s = &p->video_stream; frame = bg_ov_get_frame(s->ov); if(!bg_player_read_video(p, frame)) return; s->frame_time = gavl_time_unscale(s->output_format.timescale, frame->timestamp); if(DO_SUBTITLE(p->flags)) handle_subtitle(p); handle_messages(s, s->frame_time); bg_ov_put_still(s->ov, frame); bg_ov_handle_events(s->ov); } void bg_player_ov_cleanup(bg_player_video_stream_t * s) { if(s->osd_ovl) { bg_ov_destroy_overlay(s->ov, s->osd_id, s->osd_ovl); s->osd_ovl = NULL; } // destroy_frame(s, s->frame); // s->frame = NULL; if(s->ss->subtitles[0]) { bg_ov_destroy_overlay(s->ov, s->subtitle_id, s->ss->subtitles[0]); s->ss->subtitles[0] = NULL; } if(s->ss->subtitles[1]) { bg_ov_destroy_overlay(s->ov, s->subtitle_id, s->ss->subtitles[1]); s->ss->subtitles[1] = NULL; } bg_ov_close(s->ov); } void bg_player_ov_reset(bg_player_t * p) { bg_player_video_stream_t * s = &p->video_stream; if(DO_SUBTITLE(p->flags)) { if(s->subtitle_active) bg_ov_set_overlay(s->ov, s->subtitle_id, NULL); s->subtitle_active = 0; s->ss->current_subtitle->frame->timestamp = GAVL_TIME_UNDEFINED; s->ss->next_subtitle->frame->timestamp = GAVL_TIME_UNDEFINED; } } void bg_player_ov_update_aspect(bg_player_video_stream_t * ctx, int pixel_width, int pixel_height) { bg_ov_update_aspect(ctx->ov, pixel_width, pixel_height); } /* Set this extra because we must initialize subtitles after the video output */ void bg_player_ov_set_subtitle_format(bg_player_video_stream_t * s) { gavl_video_format_copy(&s->ss->output_format, &s->ss->input_format); /* Add subtitle stream for plugin */ s->subtitle_id = bg_ov_add_overlay_stream(s->ov, &s->ss->output_format); /* Allocate overlay frames */ s->ss->subtitles[0] = bg_ov_create_overlay(s->ov, s->subtitle_id); s->ss->subtitles[1] = bg_ov_create_overlay(s->ov, s->subtitle_id); s->ss->subtitles[0]->frame->timestamp = GAVL_TIME_UNDEFINED; s->ss->subtitles[1]->frame->timestamp = GAVL_TIME_UNDEFINED; s->ss->current_subtitle = s->ss->subtitles[0]; s->ss->next_subtitle = s->ss->subtitles[1]; } void bg_player_ov_handle_events(bg_player_video_stream_t * s) { bg_ov_handle_events(s->ov); handle_messages(s, s->frame_time); } static void wait_or_skip(bg_player_t * p, gavl_time_t diff_time) { bg_player_video_stream_t * s; s = &p->video_stream; if(diff_time > 0) { gavl_time_delay(&diff_time); if(s->skip) { s->skip -= diff_time; if(s->skip < 0) s->skip = 0; // fprintf(stderr, "Diff time: %ld, skip: %ld\n", diff_time, s->skip); } } /* TODO: Drop frames */ else if(diff_time < -100000) // 100 ms { s->skip -= diff_time; // fprintf(stderr, "Diff time: %ld, skip: %ld\n", diff_time, s->skip); } } void * bg_player_ov_thread(void * data) { bg_player_video_stream_t * s; gavl_time_t diff_time; gavl_time_t current_time; bg_player_t * p = data; gavl_video_frame_t * frame; s = &p->video_stream; bg_player_add_message_queue(p, s->msg_queue); bg_player_thread_wait_for_start(s->th); while(1) { if(!bg_player_thread_check(s->th)) { break; } frame = bg_ov_get_frame(s->ov); if(!bg_player_read_video(p, frame)) { bg_player_video_set_eof(p); if(!bg_player_thread_wait_for_start(s->th)) { break; } continue; } /* Get frame time */ s->frame_time = gavl_time_unscale(s->output_format.timescale, frame->timestamp); pthread_mutex_lock(&p->config_mutex); s->frame_time += p->sync_offset; pthread_mutex_unlock(&p->config_mutex); /* Subtitle handling */ if(DO_SUBTITLE(p->flags)) { handle_subtitle(p); } /* Handle message */ handle_messages(s, s->frame_time); /* Display OSD */ if(s->osd_id >= 0) { if(bg_osd_overlay_valid(s->osd, s->frame_time)) bg_ov_set_overlay(s->ov, s->osd_id, s->osd_ovl); else bg_ov_set_overlay(s->ov, s->osd_id, NULL); } /* Check Timing */ bg_player_time_get(p, 1, ¤t_time); diff_time = s->frame_time - current_time; #ifdef DUMP_TIMESTAMPS bg_debug("C: %"PRId64", F: %"PRId64", D: %"PRId64"\n", current_time, s->frame_time, diff_time); #endif /* Wait until we can display the frame */ wait_or_skip(p, diff_time); if(p->time_update_mode == TIME_UPDATE_FRAME) { bg_player_broadcast_time(p, s->frame_time); } bg_ov_put_video(s->ov, frame); bg_ov_handle_events(s->ov); s->frames_written++; } bg_player_delete_message_queue(p, s->msg_queue); return NULL; } const bg_parameter_info_t * bg_player_get_osd_parameters(bg_player_t * p) { return bg_osd_get_parameters(p->video_stream.osd); } void bg_player_set_osd_parameter(void * data, const char * name, const bg_parameter_value_t*val) { bg_player_t * p = data; bg_osd_set_parameter(p->video_stream.osd, name, val); } gmerlin-1.2.0~dfsg/lib/chapterlist_xml.c0000644000175000017500000000736611764363410020226 0ustar alessioalessio/***************************************************************** * gmerlin - a general purpose multimedia framework and applications * * Copyright (c) 2001 - 2011 Members of the Gmerlin project * gmerlin-general@lists.sourceforge.net * http://gmerlin.sourceforge.net * * 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 of the License, 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 this program. If not, see . * *****************************************************************/ #include #include #include #include #include #include #define CHAPTER_KEY "CHAPTER" #define CHAPTERS_KEY "CHAPTERS" #define NAME_KEY "name" void bg_chapter_list_2_xml(bg_chapter_list_t * list, xmlNodePtr xml_list) { char * tmp_string; int i; xmlNodePtr xml_chapter; tmp_string = bg_sprintf("%d", list->timescale); BG_XML_SET_PROP(xml_list, "timescale", tmp_string); free(tmp_string); xmlAddChild(xml_list, BG_XML_NEW_TEXT("\n")); for(i = 0; i < list->num_chapters; i++) { xml_chapter = xmlNewTextChild(xml_list, NULL, (xmlChar*)CHAPTER_KEY, NULL); if(list->chapters[i].name) BG_XML_SET_PROP(xml_chapter, NAME_KEY, list->chapters[i].name); tmp_string = bg_sprintf("%" PRId64, list->chapters[i].time); xmlAddChild(xml_chapter, BG_XML_NEW_TEXT(tmp_string)); free(tmp_string); xmlAddChild(xml_list, BG_XML_NEW_TEXT("\n")); } } bg_chapter_list_t * bg_xml_2_chapter_list(xmlDocPtr xml_doc, xmlNodePtr xml_list) { int index; bg_chapter_list_t * ret; char * tmp_string; gavl_time_t time; xmlNodePtr node; ret = bg_chapter_list_create(0); ret->timescale = GAVL_TIME_SCALE; tmp_string = (char*)BG_XML_GET_PROP(xml_list, "timescale"); if(tmp_string) { ret->timescale = atoi(tmp_string); xmlFree(tmp_string); } node = xml_list->children; index = 0; while(node) { if(node->name && !BG_XML_STRCMP(node->name, CHAPTER_KEY)) { tmp_string = (char*)xmlNodeListGetString(xml_doc, node->children, 1); sscanf(tmp_string, "%" PRId64, &time); xmlFree(tmp_string); tmp_string = BG_XML_GET_PROP(node, NAME_KEY); bg_chapter_list_insert(ret, index, time, tmp_string); if(tmp_string) xmlFree(tmp_string); index++; } node = node->next; } return ret; } void bg_chapter_list_save(bg_chapter_list_t * list, const char * filename) { xmlDocPtr xml_doc; xmlNodePtr xml_list; xml_doc = xmlNewDoc((xmlChar*)"1.0"); xml_list = xmlNewDocRawNode(xml_doc, NULL, (xmlChar*)CHAPTERS_KEY, NULL); xmlDocSetRootElement(xml_doc, xml_list); bg_chapter_list_2_xml(list, xml_list); xmlSaveFile(filename, xml_doc); xmlFreeDoc(xml_doc); } bg_chapter_list_t * bg_chapter_list_load(const char * filename) { xmlDocPtr xml_doc; xmlNodePtr node; bg_chapter_list_t * ret; xml_doc = bg_xml_parse_file(filename); if(!xml_doc) return NULL; node = xml_doc->children; if(BG_XML_STRCMP(node->name, CHAPTERS_KEY)) { xmlFreeDoc(xml_doc); return NULL; } ret = bg_xml_2_chapter_list(xml_doc, node); xmlFreeDoc(xml_doc); return ret; } gmerlin-1.2.0~dfsg/lib/playercmd.c0000644000175000017500000002257611764363410017004 0ustar alessioalessio/***************************************************************** * gmerlin - a general purpose multimedia framework and applications * * Copyright (c) 2001 - 2011 Members of the Gmerlin project * gmerlin-general@lists.sourceforge.net * http://gmerlin.sourceforge.net * * 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 of the License, 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 this program. If not, see . * *****************************************************************/ #include #include #include void bg_player_set_oa_plugin(bg_player_t * p, bg_plugin_handle_t * handle) { bg_msg_t * msg; if(handle) bg_plugin_ref(handle); msg = bg_msg_queue_lock_write(p->command_queue); bg_msg_set_id(msg, BG_PLAYER_CMD_SET_OA_PLUGIN); bg_msg_set_arg_ptr_nocopy(msg, 0, handle); bg_msg_queue_unlock_write(p->command_queue); } void bg_player_set_ov_plugin(bg_player_t * p, bg_plugin_handle_t * handle) { bg_msg_t * msg; if(handle) bg_plugin_ref(handle); msg = bg_msg_queue_lock_write(p->command_queue); bg_msg_set_id(msg, BG_PLAYER_CMD_SET_OV_PLUGIN); bg_msg_set_arg_ptr_nocopy(msg, 0, handle); bg_msg_queue_unlock_write(p->command_queue); } void bg_player_play(bg_player_t * p, bg_plugin_handle_t * handle, int track, int ignore_flags, const char * track_name) { bg_msg_t * msg; bg_plugin_ref(handle); msg = bg_msg_queue_lock_write(p->command_queue); bg_msg_set_id(msg, BG_PLAYER_CMD_PLAY); bg_msg_set_arg_ptr_nocopy(msg, 0, handle); bg_msg_set_arg_int(msg, 1, track); bg_msg_set_arg_int(msg, 2, ignore_flags); bg_msg_set_arg_string(msg, 3, track_name); bg_msg_queue_unlock_write(p->command_queue); } void bg_player_stop(bg_player_t * p) { bg_msg_t * msg; msg = bg_msg_queue_lock_write(p->command_queue); bg_msg_set_id(msg, BG_PLAYER_CMD_STOP); bg_msg_queue_unlock_write(p->command_queue); } void bg_player_toggle_mute(bg_player_t * p) { bg_msg_t * msg; msg = bg_msg_queue_lock_write(p->command_queue); bg_msg_set_id(msg, BG_PLAYER_CMD_TOGGLE_MUTE); bg_msg_queue_unlock_write(p->command_queue); } void bg_player_pause(bg_player_t * p) { bg_msg_t * msg; msg = bg_msg_queue_lock_write(p->command_queue); bg_msg_set_id(msg, BG_PLAYER_CMD_PAUSE); bg_msg_queue_unlock_write(p->command_queue); } void bg_player_set_audio_stream(bg_player_t * p, int index) { bg_msg_t * msg; msg = bg_msg_queue_lock_write(p->command_queue); bg_msg_set_id(msg, BG_PLAYER_CMD_SET_AUDIO_STREAM); bg_msg_set_arg_int(msg, 0, index); bg_msg_queue_unlock_write(p->command_queue); } void bg_player_set_video_stream(bg_player_t * p, int index) { bg_msg_t * msg; msg = bg_msg_queue_lock_write(p->command_queue); bg_msg_set_id(msg, BG_PLAYER_CMD_SET_VIDEO_STREAM); bg_msg_set_arg_int(msg, 0, index); bg_msg_queue_unlock_write(p->command_queue); } void bg_player_set_subtitle_stream(bg_player_t * p, int index) { bg_msg_t * msg; msg = bg_msg_queue_lock_write(p->command_queue); bg_msg_set_id(msg, BG_PLAYER_CMD_SET_SUBTITLE_STREAM); bg_msg_set_arg_int(msg, 0, index); bg_msg_queue_unlock_write(p->command_queue); } static void msg_name(bg_msg_t * msg, const void * data) { const char * name = (const char*)(data); bg_msg_set_id(msg, BG_PLAYER_MSG_TRACK_NAME); bg_msg_set_arg_string(msg, 0, name); } void bg_player_set_track_name(bg_player_t * p, const char * name) { bg_msg_queue_list_send(p->message_queues, msg_name, name); } typedef struct { gavl_time_t duration; int can_seek; } duration_struct; static void msg_duration(bg_msg_t * msg, const void * data) { duration_struct * d; d = (duration_struct*)data; bg_msg_set_id(msg, BG_PLAYER_MSG_TRACK_DURATION); bg_msg_set_arg_time(msg, 0, d->duration); bg_msg_set_arg_int(msg, 1, d->can_seek); } void bg_player_set_duration(bg_player_t * p, gavl_time_t duration, int can_seek) { duration_struct d; d.duration = duration; d.can_seek = can_seek; bg_msg_queue_list_send(p->message_queues, msg_duration, &d); } static void msg_metadata(bg_msg_t * msg, const void * data) { const gavl_metadata_t * m = data; bg_msg_set_id(msg, BG_PLAYER_MSG_METADATA); bg_msg_set_arg_metadata(msg, 0, m); } void bg_player_set_metadata(bg_player_t * p, const gavl_metadata_t * m) { bg_msg_queue_list_send(p->message_queues, msg_metadata, m); } typedef struct { int id; } key_struct; static void msg_accel(bg_msg_t * msg, const void * data) { const key_struct * s = (const key_struct *)(data); bg_msg_set_id(msg, BG_PLAYER_MSG_ACCEL); bg_msg_set_arg_int(msg, 0, s->id); } void bg_player_accel_pressed(bg_player_t * p, int id) { key_struct s; s.id = id; bg_msg_queue_list_send(p->message_queues, msg_accel, &s); } void bg_player_seek(bg_player_t * p, gavl_time_t time, int scale) { bg_msg_t * msg; msg = bg_msg_queue_lock_write(p->command_queue); bg_msg_set_id(msg, BG_PLAYER_CMD_SEEK); bg_msg_set_arg_time(msg, 0, time); bg_msg_set_arg_int(msg, 1, scale); bg_msg_queue_unlock_write(p->command_queue); } void bg_player_seek_rel(bg_player_t * p, gavl_time_t t) { bg_msg_t * msg; msg = bg_msg_queue_lock_write(p->command_queue); bg_msg_set_id(msg, BG_PLAYER_CMD_SEEK_REL); bg_msg_set_arg_time(msg, 0, t); bg_msg_queue_unlock_write(p->command_queue); } void bg_player_set_volume(bg_player_t * p, float volume) { bg_msg_t * msg; msg = bg_msg_queue_lock_write(p->command_queue); bg_msg_set_id(msg, BG_PLAYER_CMD_SET_VOLUME); bg_msg_set_arg_float(msg, 0, volume); bg_msg_queue_unlock_write(p->command_queue); } void bg_player_set_volume_rel(bg_player_t * p, float volume) { bg_msg_t * msg; msg = bg_msg_queue_lock_write(p->command_queue); bg_msg_set_id(msg, BG_PLAYER_CMD_SET_VOLUME_REL); bg_msg_set_arg_float(msg, 0, volume); bg_msg_queue_unlock_write(p->command_queue); } void bg_player_error(bg_player_t * p) { bg_msg_t * msg; msg = bg_msg_queue_lock_write(p->command_queue); bg_msg_set_id(msg, BG_PLAYER_CMD_SETSTATE); bg_msg_set_arg_int(msg, 0, BG_PLAYER_STATE_ERROR); bg_msg_queue_unlock_write(p->command_queue); } void bg_player_change(bg_player_t * p, int flags) { bg_msg_queue_t * q; bg_msg_t * msg; q = bg_msg_queue_create(); bg_player_add_message_queue(p, q); msg = bg_msg_queue_lock_write(p->command_queue); bg_msg_set_id(msg, BG_PLAYER_CMD_CHANGE); bg_msg_set_arg_int(msg, 0, flags); bg_msg_queue_unlock_write(p->command_queue); while((msg = bg_msg_queue_lock_read(q)) && (bg_msg_get_id(msg) != BG_PLAYER_MSG_CLEANUP)) { bg_msg_queue_unlock_read(q); } bg_player_delete_message_queue(p, q); bg_msg_queue_destroy(q); } void bg_player_interrupt(bg_player_t * p) { bg_msg_queue_t * q; bg_msg_t * msg; /* Create message queue and connect to player */ q = bg_msg_queue_create(); bg_player_add_message_queue(p, q); /* Tell player to interrupt */ msg = bg_msg_queue_lock_write(p->command_queue); bg_msg_set_id(msg, BG_PLAYER_CMD_INTERRUPT); bg_msg_queue_unlock_write(p->command_queue); /* Wait for confirmation */ while((msg = bg_msg_queue_lock_read(q)) && (bg_msg_get_id(msg) != BG_PLAYER_MSG_INTERRUPT)) { bg_msg_queue_unlock_read(q); } bg_msg_queue_unlock_read(q); /* Cleanup */ bg_player_delete_message_queue(p, q); bg_msg_queue_destroy(q); } void bg_player_interrupt_resume(bg_player_t * p) { bg_msg_t * msg; bg_msg_queue_t * q; /* Create message queue and connect to player */ q = bg_msg_queue_create(); bg_player_add_message_queue(p, q); /* Tell player to resume */ msg = bg_msg_queue_lock_write(p->command_queue); bg_msg_set_id(msg, BG_PLAYER_CMD_INTERRUPT_RESUME); bg_msg_queue_unlock_write(p->command_queue); /* Wait for confirmation */ while((msg = bg_msg_queue_lock_read(q)) && (bg_msg_get_id(msg) != BG_PLAYER_MSG_INTERRUPT_RESUME)) { bg_msg_queue_unlock_read(q); } bg_msg_queue_unlock_read(q); /* Cleanup */ bg_player_delete_message_queue(p, q); bg_msg_queue_destroy(q); } void bg_player_next_chapter(bg_player_t * p) { bg_msg_t * msg; msg = bg_msg_queue_lock_write(p->command_queue); bg_msg_set_id(msg, BG_PLAYER_CMD_NEXT_CHAPTER); bg_msg_queue_unlock_write(p->command_queue); } void bg_player_prev_chapter(bg_player_t * p) { bg_msg_t * msg; msg = bg_msg_queue_lock_write(p->command_queue); bg_msg_set_id(msg, BG_PLAYER_CMD_PREV_CHAPTER); bg_msg_queue_unlock_write(p->command_queue); } void bg_player_set_chapter(bg_player_t * p, int chapter) { bg_msg_t * msg; msg = bg_msg_queue_lock_write(p->command_queue); bg_msg_set_id(msg, BG_PLAYER_CMD_SET_CHAPTER); bg_msg_set_arg_int(msg, 0, chapter); bg_msg_queue_unlock_write(p->command_queue); } gmerlin-1.2.0~dfsg/lib/metadata_xml.c0000644000175000017500000000750011764363410017452 0ustar alessioalessio/***************************************************************** * gmerlin - a general purpose multimedia framework and applications * * Copyright (c) 2001 - 2011 Members of the Gmerlin project * gmerlin-general@lists.sourceforge.net * http://gmerlin.sourceforge.net * * 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 of the License, 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 this program. If not, see . * *****************************************************************/ #include #include #include #include #include #include #include #include #include #include static const struct { const char * xml_name; const char * gavl_name; } tags[] = { { "track", GAVL_META_TRACKNUMBER }, { "artist", GAVL_META_ARTIST }, { "title", GAVL_META_TITLE }, { "album", GAVL_META_ALBUM }, { "date", GAVL_META_DATE }, { "genre", GAVL_META_GENRE }, { "comment", GAVL_META_COMMENT }, { "author", GAVL_META_AUTHOR }, { "copyright", GAVL_META_COPYRIGHT }, { /* End */ } }; void bg_xml_2_metadata(xmlDocPtr xml_doc, xmlNodePtr xml_metadata, gavl_metadata_t * ret) { int i; char * tmp_string; xmlNodePtr node; node = xml_metadata->children; while(node) { if(!node->name) { node = node->next; continue; } tmp_string = (char*)xmlNodeListGetString(xml_doc, node->children, 1); i = 0; while(tags[i].xml_name) { if(!BG_XML_STRCMP(node->name, tags[i].xml_name)) { gavl_metadata_set(ret, tags[i].gavl_name, tmp_string); break; } i++; } xmlFree(tmp_string); node = node->next; } } #define STRING_2_XML(key) \ if(m->key) \ { \ child = xmlNewTextChild(xml_metadata, NULL, (xmlChar*)#key, NULL); \ xmlAddChild(child, BG_XML_NEW_TEXT(m->key)); \ xmlAddChild(xml_metadata, BG_XML_NEW_TEXT("\n")); \ } #define INT_2_XML(key) \ if(m->key) \ { \ tmp_string = bg_sprintf("%d", m->key); \ child = xmlNewTextChild(xml_metadata, NULL, (xmlChar*)#key, NULL); \ xmlAddChild(child, BG_XML_NEW_TEXT(tmp_string)); \ free(tmp_string); \ xmlAddChild(xml_metadata, BG_XML_NEW_TEXT("\n")); \ } void bg_metadata_2_xml(xmlNodePtr xml_metadata, gavl_metadata_t * m) { int i, j; xmlNodePtr child; for(i = 0; i < m->num_tags; i++) { j = 0; while(tags[j].gavl_name) { if(!strcmp(m->tags[i].key, tags[j].gavl_name)) { child = xmlNewTextChild(xml_metadata, NULL, (xmlChar*)tags[j].xml_name, NULL); xmlAddChild(child, BG_XML_NEW_TEXT(m->tags[i].val)); xmlAddChild(xml_metadata, BG_XML_NEW_TEXT("\n")); break; } j++; } } } gmerlin-1.2.0~dfsg/lib/converters.c0000644000175000017500000003476211764363410017216 0ustar alessioalessio/***************************************************************** * gmerlin - a general purpose multimedia framework and applications * * Copyright (c) 2001 - 2011 Members of the Gmerlin project * gmerlin-general@lists.sourceforge.net * http://gmerlin.sourceforge.net * * 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 of the License, 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 this program. If not, see . * *****************************************************************/ #include #include #include #include #include #define LOG_DOMAIN "converters" #define ABSDIFF(x,y) ((x)>(y)?(x)-(y):(y)-(x)) #define TIME_UNDEFINED 0x8000000000000000LL struct bg_audio_converter_s { gavl_audio_converter_t * cnv; const gavl_audio_options_t * opt; gavl_audio_frame_t * in_frame; gavl_audio_frame_t * out_frame; /* Input stuff */ bg_read_audio_func_t read_func; void * read_priv; int read_stream; bg_read_audio_func_t read_func_1; void * read_priv_1; int read_stream_1; /* Output stuff */ int (*read_func_out)(bg_audio_converter_t*, gavl_audio_frame_t * frame, int num_samples); gavl_audio_format_t in_format; gavl_audio_format_t out_format; int in_rate; int out_rate; int last_samples; int64_t out_pts; }; bg_audio_converter_t * bg_audio_converter_create(const gavl_audio_options_t * opt) { bg_audio_converter_t * ret; ret = calloc(1, sizeof(*ret)); ret->opt = opt; ret->cnv = gavl_audio_converter_create(); ret->out_pts = TIME_UNDEFINED; return ret; } void bg_audio_converter_reset(bg_audio_converter_t * cnv) { if(cnv->out_frame) cnv->out_frame->valid_samples = 0; cnv->out_pts = TIME_UNDEFINED; } static int read_audio_priv(void * priv, gavl_audio_frame_t * frame, int stream, int num_samples) { int ret; bg_audio_converter_t * cnv = (bg_audio_converter_t *)priv; ret = cnv->read_func_1(cnv->read_priv_1, frame, cnv->read_stream_1, num_samples); if(cnv->out_pts == TIME_UNDEFINED) cnv->out_pts = gavl_time_rescale(cnv->in_format.samplerate, cnv->out_format.samplerate, frame->timestamp); return ret; } void bg_audio_converter_connect_input(bg_audio_converter_t * cnv, bg_read_audio_func_t func, void * priv, int stream) { cnv->read_func = read_audio_priv; cnv->read_priv = cnv; cnv->read_stream = 0; cnv->read_func_1 = func; cnv->read_priv_1 = priv; cnv->read_stream_1 = stream; } static int audio_converter_read_noresample(bg_audio_converter_t * cnv, gavl_audio_frame_t* frame, int num_samples) { if(cnv->in_format.samples_per_frame < num_samples) { if(cnv->in_frame) { gavl_audio_frame_destroy(cnv->in_frame); cnv->in_frame = NULL; } cnv->in_format.samples_per_frame = num_samples + 1024; } if(!cnv->in_frame) cnv->in_frame = gavl_audio_frame_create(&cnv->in_format); if(!cnv->read_func(cnv->read_priv, cnv->in_frame, cnv->read_stream, num_samples)) return 0; gavl_audio_convert(cnv->cnv, cnv->in_frame, frame); return frame->valid_samples; } static int audio_converter_read_resample(bg_audio_converter_t * cnv, gavl_audio_frame_t* frame, int num_samples) { int samples_copied; frame->valid_samples = 0; while(frame->valid_samples < num_samples) { /* Read samples */ if(!cnv->out_frame->valid_samples) { if(!cnv->read_func(cnv->read_priv, cnv->in_frame, cnv->read_stream, cnv->in_format.samples_per_frame)) return frame->valid_samples; gavl_audio_convert(cnv->cnv, cnv->in_frame, cnv->out_frame); cnv->last_samples = cnv->out_frame->valid_samples; } /* Copy samples */ samples_copied = gavl_audio_frame_copy(&cnv->out_format, frame, cnv->out_frame, frame->valid_samples, cnv->last_samples - cnv->out_frame->valid_samples, num_samples - frame->valid_samples, cnv->out_frame->valid_samples); cnv->out_frame->valid_samples -= samples_copied; frame->valid_samples += samples_copied; } return frame->valid_samples; } int bg_audio_converter_init(bg_audio_converter_t * cnv, const gavl_audio_format_t * in_format, const gavl_audio_format_t * out_format) { int result; gavl_audio_options_t * cnv_opt; /* Free previous stuff */ if(cnv->in_frame) { gavl_audio_frame_destroy(cnv->in_frame); cnv->in_frame = NULL; } if(cnv->out_frame) { gavl_audio_frame_destroy(cnv->out_frame); cnv->out_frame = NULL; } /* Set options */ cnv_opt = gavl_audio_converter_get_options(cnv->cnv); gavl_audio_options_copy(cnv_opt, cnv->opt); result = gavl_audio_converter_init(cnv->cnv, in_format, out_format); if(result) { gavl_audio_format_copy(&cnv->in_format, in_format); gavl_audio_format_copy(&cnv->out_format, out_format); if(cnv->out_format.samplerate != cnv->in_format.samplerate) { cnv->out_format.samples_per_frame = (cnv->in_format.samples_per_frame * cnv->out_format.samplerate) / cnv->in_format.samplerate + 10; cnv->in_frame = gavl_audio_frame_create(&cnv->in_format); cnv->out_frame = gavl_audio_frame_create(&cnv->out_format); cnv->read_func_out = audio_converter_read_resample; } else cnv->read_func_out = audio_converter_read_noresample; cnv->last_samples = 0; } cnv->out_pts = TIME_UNDEFINED; return result; } int bg_audio_converter_read(void * priv, gavl_audio_frame_t* frame, int stream, int num_samples) { bg_audio_converter_t * cnv = (bg_audio_converter_t*)priv; int result; result = cnv->read_func_out(cnv, frame, num_samples); if(result) { frame->timestamp = cnv->out_pts; cnv->out_pts += frame->valid_samples; } return result; } void bg_audio_converter_destroy(bg_audio_converter_t * cnv) { if(cnv->in_frame) gavl_audio_frame_destroy(cnv->in_frame); if(cnv->out_frame) gavl_audio_frame_destroy(cnv->out_frame); if(cnv->cnv) gavl_audio_converter_destroy(cnv->cnv); free(cnv); } /* Video */ struct bg_video_converter_s { gavl_video_converter_t * cnv; const gavl_video_options_t * opt; gavl_video_frame_t * frame; gavl_video_frame_t * next_frame; /* Input stuff */ bg_read_video_func_t read_func; void * read_priv; int read_stream; bg_read_video_func_t read_func_1; void * read_priv_1; int read_stream_1; int64_t out_pts; int convert_gavl; int convert_framerate; int rescale_timestamps; gavl_video_format_t in_format; gavl_video_format_t out_format; int eof; }; bg_video_converter_t * bg_video_converter_create(const gavl_video_options_t * opt) { bg_video_converter_t * ret; ret = calloc(1, sizeof(*ret)); ret->opt = opt; ret->cnv = gavl_video_converter_create(); return ret; } int bg_video_converter_init(bg_video_converter_t * cnv, const gavl_video_format_t * in_format, const gavl_video_format_t * out_format) { gavl_video_options_t * cnv_opt; int ret; cnv->convert_framerate = 0; cnv->convert_gavl = 0; cnv->rescale_timestamps = 0; /* Free previous stuff */ if(cnv->frame) { gavl_video_frame_destroy(cnv->frame); cnv->frame = NULL; } if(cnv->next_frame) { gavl_video_frame_destroy(cnv->next_frame); cnv->next_frame = NULL; } /* Copy format */ gavl_video_format_copy(&cnv->in_format, in_format); gavl_video_format_copy(&cnv->out_format, out_format); /* Set options */ cnv_opt = gavl_video_converter_get_options(cnv->cnv); gavl_video_options_copy(cnv_opt, cnv->opt); cnv->convert_gavl = gavl_video_converter_init(cnv->cnv, in_format, out_format); if(out_format->framerate_mode == GAVL_FRAMERATE_CONSTANT) { if( (in_format->framerate_mode != GAVL_FRAMERATE_CONSTANT) || (in_format->timescale * out_format->frame_duration != out_format->timescale * in_format->frame_duration) ) { char * str1, *str2; cnv->convert_framerate = 1; if(cnv->in_format.framerate_mode == GAVL_FRAMERATE_VARIABLE) str1 = bg_strdup(NULL, TR("variable")); else str1 = bg_sprintf("%5.2f", (float)(cnv->in_format.timescale) / (float)(cnv->in_format.frame_duration)); if(cnv->out_format.framerate_mode == GAVL_FRAMERATE_VARIABLE) str2 = bg_strdup(NULL, TR("variable")); else str2 = bg_sprintf("%5.2f", (float)(cnv->out_format.timescale) / (float)(cnv->out_format.frame_duration)); bg_log(BG_LOG_INFO, LOG_DOMAIN, "Doing framerate conversion %s -> %s", str1, str2); free(str1); free(str2); } } if(!cnv->convert_framerate) { if(in_format->timescale != out_format->timescale) cnv->rescale_timestamps = 1; } if(cnv->convert_gavl || cnv->convert_framerate) { cnv->frame = gavl_video_frame_create(in_format); gavl_video_frame_clear(cnv->frame, in_format); cnv->frame->timestamp = GAVL_TIME_UNDEFINED; } if(cnv->convert_framerate) { cnv->next_frame = gavl_video_frame_create(in_format); gavl_video_frame_clear(cnv->next_frame, in_format); cnv->next_frame->timestamp = GAVL_TIME_UNDEFINED; } cnv->out_pts = 0; cnv->eof = 0; ret = cnv->convert_framerate + cnv->convert_gavl + cnv->rescale_timestamps; bg_log(BG_LOG_DEBUG, LOG_DOMAIN, "Initialized video converter, %d steps", ret); return ret; } static int read_video_priv(void * priv, gavl_video_frame_t * frame, int stream) { int ret; bg_video_converter_t * cnv = (bg_video_converter_t *)priv; ret = cnv->read_func_1(cnv->read_priv_1, frame, cnv->read_stream_1); if(cnv->out_pts == TIME_UNDEFINED) cnv->out_pts = gavl_time_rescale(cnv->in_format.timescale, cnv->out_format.timescale, frame->timestamp); return ret; } void bg_video_converter_connect_input(bg_video_converter_t * cnv, bg_read_video_func_t func, void * priv, int stream) { cnv->read_func = read_video_priv; cnv->read_priv = cnv; cnv->read_stream = 0; cnv->read_func_1 = func; cnv->read_priv_1 = priv; cnv->read_stream_1 = stream; } int bg_video_converter_read(void * priv, gavl_video_frame_t* frame, int stream) { int64_t in_pts; int result; bg_video_converter_t * cnv = (bg_video_converter_t *)priv; gavl_video_frame_t * tmp_frame; if(!cnv->convert_framerate) { if(cnv->convert_gavl) { result = cnv->read_func(cnv->read_priv, cnv->frame, cnv->read_stream); if(result) gavl_video_convert(cnv->cnv, cnv->frame, frame); } else result = cnv->read_func(cnv->read_priv, frame, cnv->read_stream); if(cnv->rescale_timestamps) { frame->timestamp = gavl_time_rescale(cnv->in_format.timescale, cnv->out_format.timescale, frame->timestamp); frame->duration = gavl_time_rescale(cnv->in_format.timescale, cnv->out_format.timescale, frame->duration); } return result; } else { /* Read first frames */ if((cnv->frame->timestamp == GAVL_TIME_UNDEFINED) && !cnv->read_func(cnv->read_priv, cnv->frame, cnv->read_stream)) return 0; if((cnv->next_frame->timestamp == GAVL_TIME_UNDEFINED) && !cnv->read_func(cnv->read_priv, cnv->next_frame, cnv->read_stream)) return 0; in_pts = gavl_time_rescale(cnv->out_format.timescale, cnv->in_format.timescale, cnv->out_pts); /* Last frame was already returned */ if(cnv->eof) return 0; while(in_pts >= cnv->next_frame->timestamp) { tmp_frame = cnv->frame; cnv->frame = cnv->next_frame; cnv->next_frame = tmp_frame; result = cnv->read_func(cnv->read_priv, cnv->next_frame, cnv->read_stream); if(!result) { cnv->eof = 1; break; } } if(cnv->eof) tmp_frame = cnv->next_frame; else if(ABSDIFF(cnv->next_frame->timestamp, in_pts) < ABSDIFF(cnv->frame->timestamp, in_pts)) tmp_frame = cnv->next_frame; else tmp_frame = cnv->frame; if(cnv->convert_gavl) gavl_video_convert(cnv->cnv, tmp_frame, frame); else gavl_video_frame_copy(&cnv->out_format, frame, tmp_frame); frame->timestamp = cnv->out_pts; cnv->out_pts += cnv->out_format.frame_duration; /* Clear timecode */ frame->timecode = GAVL_TIMECODE_UNDEFINED; } return 1; } void bg_video_converter_destroy(bg_video_converter_t * cnv) { if(cnv->frame) gavl_video_frame_destroy(cnv->frame); if(cnv->next_frame) gavl_video_frame_destroy(cnv->next_frame); if(cnv->cnv) gavl_video_converter_destroy(cnv->cnv); free(cnv); } void bg_video_converter_reset(bg_video_converter_t * cnv) { if(cnv->frame) cnv->frame->timestamp = GAVL_TIME_UNDEFINED; if(cnv->next_frame) cnv->next_frame->timestamp = GAVL_TIME_UNDEFINED; cnv->eof = 0; cnv->out_pts = TIME_UNDEFINED; } gmerlin-1.2.0~dfsg/lib/filters.c0000644000175000017500000006060611764363410016470 0ustar alessioalessio/***************************************************************** * gmerlin - a general purpose multimedia framework and applications * * Copyright (c) 2001 - 2011 Members of the Gmerlin project * gmerlin-general@lists.sourceforge.net * http://gmerlin.sourceforge.net * * 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 of the License, 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 this program. If not, see . * *****************************************************************/ #include #include #include #include #include #include #include #include #include #include #define LOG_DOMAIN "filters" /* Audio */ typedef struct { bg_plugin_handle_t * handle; bg_fa_plugin_t * plugin; bg_audio_converter_t * cnv; int do_convert; } audio_filter_t; struct bg_audio_filter_chain_s { int num_filters; audio_filter_t * filters; const bg_gavl_audio_options_t * opt; bg_plugin_registry_t * plugin_reg; bg_parameter_info_t * parameters; char * filter_string; int need_rebuild; int need_restart; bg_audio_converter_t * cnv_out; gavl_audio_frame_t * frame; gavl_audio_format_t out_format_1; gavl_audio_format_t in_format_1; gavl_audio_format_t in_format_2; gavl_audio_format_t in_format; /* Input format of first filter */ gavl_audio_format_t out_format; /* Output format of chain */ pthread_mutex_t mutex; bg_read_audio_func_t in_func; void * in_data; int in_stream; bg_read_audio_func_t read_func; void * read_data; int read_stream; }; int bg_audio_filter_chain_need_restart(bg_audio_filter_chain_t * ch) { gavl_audio_format_t test_format; if(!ch->need_restart) { gavl_audio_format_copy(&test_format, &ch->in_format_1); bg_gavl_audio_options_set_format(ch->opt, &ch->in_format_1, &test_format); if(!gavl_audio_formats_equal(&test_format, &ch->in_format_2)) ch->need_restart = 1; } return ch->need_restart || ch->need_rebuild; } static int audio_filter_create(audio_filter_t * f, bg_audio_filter_chain_t * ch, const char * name) { const bg_plugin_info_t * info; info = bg_plugin_find_by_name(ch->plugin_reg, name); if(!info) return 0; f->handle = bg_plugin_load(ch->plugin_reg, info); if(!f->handle) return 0; f->plugin = (bg_fa_plugin_t*)(f->handle->plugin); f->cnv = bg_audio_converter_create(ch->opt->opt); return 1; } void bg_audio_filter_chain_lock(bg_audio_filter_chain_t * cnv) { pthread_mutex_lock(&cnv->mutex); } void bg_audio_filter_chain_unlock(bg_audio_filter_chain_t * cnv) { pthread_mutex_unlock(&cnv->mutex); } static void audio_filter_destroy(audio_filter_t * f) { bg_audio_converter_destroy(f->cnv); if(f->handle) bg_plugin_unref_nolock(f->handle); } static void destroy_audio_chain(bg_audio_filter_chain_t * ch) { int i; /* Destroy previous filters */ for(i = 0; i < ch->num_filters; i++) audio_filter_destroy(&ch->filters[i]); if(ch->filters) { free(ch->filters); ch->filters = NULL; } ch->num_filters = 0; } static void bg_audio_filter_chain_rebuild(bg_audio_filter_chain_t * ch) { int i; char ** filter_names; ch->need_rebuild = 0; filter_names = bg_strbreak(ch->filter_string, ','); destroy_audio_chain(ch); if(!filter_names) return; while(filter_names[ch->num_filters]) ch->num_filters++; ch->filters = calloc(ch->num_filters, sizeof(*ch->filters)); for(i = 0; i < ch->num_filters; i++) { audio_filter_create(&ch->filters[i], ch, filter_names[i]); } bg_strbreak_free(filter_names); } bg_audio_filter_chain_t * bg_audio_filter_chain_create(const bg_gavl_audio_options_t * opt, bg_plugin_registry_t * plugin_reg) { bg_audio_filter_chain_t * ret; ret = calloc(1, sizeof(*ret)); ret->opt = opt; ret->plugin_reg = plugin_reg; ret->cnv_out = bg_audio_converter_create(opt->opt); pthread_mutex_init(&ret->mutex, NULL); return ret; } static void create_audio_parameters(bg_audio_filter_chain_t * ch) { ch->parameters = calloc(2, sizeof(*ch->parameters)); ch->parameters->name = bg_strdup(NULL, "audio_filters"); ch->parameters->long_name = bg_strdup(NULL, TRS("Audio Filters")); ch->parameters->preset_path = bg_strdup(NULL, "audiofilters"); ch->parameters->gettext_domain = bg_strdup(NULL, PACKAGE); ch->parameters->gettext_directory = bg_strdup(NULL, LOCALE_DIR); ch->parameters->type = BG_PARAMETER_MULTI_CHAIN; ch->parameters->flags |= BG_PARAMETER_SYNC; bg_plugin_registry_set_parameter_info(ch->plugin_reg, BG_PLUGIN_FILTER_AUDIO, BG_PLUGIN_FILTER_1, ch->parameters); } const bg_parameter_info_t * bg_audio_filter_chain_get_parameters(bg_audio_filter_chain_t * ch) { if(!ch->parameters) create_audio_parameters(ch); return ch->parameters; } void bg_audio_filter_chain_set_parameter(void * data, const char * name, const bg_parameter_value_t * val) { bg_audio_filter_chain_t * ch; int i; char * pos; audio_filter_t * f; ch = (bg_audio_filter_chain_t *)data; if(!name) { for(i = 0; i < ch->num_filters; i++) { if(ch->filters[i].plugin->common.set_parameter) ch->filters[i].plugin->common.set_parameter(ch->filters[i].handle->priv, NULL, NULL); } return; } if(!strcmp(name, "audio_filters")) { if(!ch->filter_string && !val->val_str) goto the_end; if(ch->filter_string && val->val_str && !strcmp(ch->filter_string, val->val_str)) { goto the_end; } /* Rebuild chain */ ch->filter_string = bg_strdup(ch->filter_string, val->val_str); ch->need_rebuild = 1; } else if(!strncmp(name, "audio_filters.", 14)) { if(ch->need_rebuild) bg_audio_filter_chain_rebuild(ch); pos = strchr(name, '.'); pos++; i = atoi(pos); f = ch->filters + i; pos = strchr(pos, '.'); if(!pos) goto the_end; pos++; if(f->plugin->common.set_parameter) { f->plugin->common.set_parameter(f->handle->priv, pos, val); if(f->plugin->need_restart && f->plugin->need_restart(f->handle->priv)) ch->need_restart = 1; } } the_end: return; } int bg_audio_filter_chain_init(bg_audio_filter_chain_t * ch, const gavl_audio_format_t * in_format, gavl_audio_format_t * out_format) { int i; gavl_audio_format_t format_1; gavl_audio_format_t format_2; audio_filter_t * f; ch->need_restart = 0; if(ch->need_rebuild) bg_audio_filter_chain_rebuild(ch); // if(!ch->num_filters) // return 0; gavl_audio_format_copy(&format_1, in_format); gavl_audio_format_copy(&ch->out_format_1, in_format); /* Set user defined format */ bg_gavl_audio_options_set_format(ch->opt, in_format, &format_1); gavl_audio_format_copy(&ch->in_format_1, in_format); gavl_audio_format_copy(&ch->in_format_2, &format_1); f = ch->filters; if(ch->opt->force_format != GAVL_SAMPLE_NONE) format_1.sample_format = ch->opt->force_format; ch->read_func = ch->in_func; ch->read_data = ch->in_data; ch->read_stream = ch->in_stream; for(i = 0; i < ch->num_filters; i++) { gavl_audio_format_copy(&format_2, &format_1); if(!i && (ch->opt->force_format != GAVL_SAMPLE_NONE)) format_2.sample_format = ch->opt->force_format; f->plugin->set_input_format(f->handle->priv, &format_2, 0); if(!i) { f->do_convert = bg_audio_converter_init(f->cnv, in_format, &format_2); gavl_audio_format_copy(&ch->in_format, &format_2); } else f->do_convert = bg_audio_converter_init(f->cnv, &format_1, &format_2); if(f->do_convert) { bg_audio_converter_connect_input(f->cnv, ch->read_func, ch->read_data, ch->read_stream); f->plugin->connect_input_port(f->handle->priv, bg_audio_converter_read, f->cnv, 0, 0); } else f->plugin->connect_input_port(f->handle->priv, ch->read_func, ch->read_data, ch->read_stream, 0); ch->read_func = f->plugin->read_audio; ch->read_data = f->handle->priv; ch->read_stream = 0; // if(f->plugin->init) // f->plugin->init(f->handle->priv); f->plugin->get_output_format(f->handle->priv, &format_1); bg_log(BG_LOG_INFO, LOG_DOMAIN, "Initialized audio filter %s", TRD(f->handle->info->long_name, f->handle->info->gettext_domain)); f++; } gavl_audio_format_copy(out_format, &format_1); gavl_audio_format_copy(&ch->out_format, &format_1); if(ch->num_filters) gavl_audio_format_copy(&ch->out_format_1, &format_1); else gavl_audio_format_copy(&ch->out_format_1, in_format); return ch->num_filters; } void bg_audio_filter_chain_set_input_format(bg_audio_filter_chain_t * ch, const gavl_audio_format_t * format) { if(!ch->num_filters) { int do_convert_out; do_convert_out = bg_audio_converter_init(ch->cnv_out, &ch->out_format_1, &ch->out_format); if(do_convert_out) { bg_audio_converter_connect_input(ch->cnv_out, ch->in_func, ch->in_data, ch->in_stream); ch->read_func = bg_audio_converter_read; ch->read_data = ch->cnv_out; ch->read_stream = 0; } } else { audio_filter_t * f = ch->filters; f->do_convert = bg_audio_converter_init(f->cnv, format, &ch->in_format); if(f->do_convert) { bg_audio_converter_connect_input(f->cnv, ch->in_func, ch->in_data, ch->in_stream); f->plugin->connect_input_port(f->handle->priv, bg_audio_converter_read, f->cnv, 0, 0); } else f->plugin->connect_input_port(f->handle->priv, ch->in_func, ch->in_data, ch->in_stream, 0); } } int bg_audio_filter_chain_set_out_format(bg_audio_filter_chain_t * ch, const gavl_audio_format_t * out_format) { int do_convert_out; do_convert_out = bg_audio_converter_init(ch->cnv_out, &ch->out_format_1, out_format); if(do_convert_out) { bg_audio_converter_connect_input(ch->cnv_out, ch->read_func, ch->read_data, ch->read_stream); ch->read_func = bg_audio_converter_read; ch->read_data = ch->cnv_out; ch->read_stream = 0; } gavl_audio_format_copy(&ch->out_format, out_format); return do_convert_out; } void bg_audio_filter_chain_connect_input(bg_audio_filter_chain_t * ch, bg_read_audio_func_t func, void * priv, int stream) { ch->in_func = func; ch->in_data = priv; ch->in_stream = stream; } int bg_audio_filter_chain_read(void * priv, gavl_audio_frame_t* frame, int stream, int num_samples) { int ret; bg_audio_filter_chain_t * ch; ch = (bg_audio_filter_chain_t *)priv; bg_audio_filter_chain_lock(ch); ret = ch->read_func(ch->read_data, frame, ch->read_stream, num_samples); bg_audio_filter_chain_unlock(ch); return ret; } void bg_audio_filter_chain_destroy(bg_audio_filter_chain_t * ch) { if(ch->parameters) bg_parameter_info_destroy_array(ch->parameters); if(ch->filter_string) free(ch->filter_string); bg_audio_converter_destroy(ch->cnv_out); destroy_audio_chain(ch); pthread_mutex_destroy(&ch->mutex); free(ch); } void bg_audio_filter_chain_reset(bg_audio_filter_chain_t * ch) { int i; for(i = 0; i < ch->num_filters; i++) { if(ch->filters[i].plugin->reset) ch->filters[i].plugin->reset(ch->filters[i].handle->priv); bg_audio_converter_reset(ch->filters[i].cnv); } bg_audio_converter_reset(ch->cnv_out); } /* Video */ typedef struct { bg_plugin_handle_t * handle; bg_fv_plugin_t * plugin; bg_video_converter_t * cnv; int do_convert; } video_filter_t; struct bg_video_filter_chain_s { int num_filters; video_filter_t * filters; const bg_gavl_video_options_t * opt; bg_plugin_registry_t * plugin_reg; bg_parameter_info_t * parameters; char * filter_string; int need_rebuild; int need_restart; bg_video_converter_t * cnv_out; gavl_video_frame_t * frame; gavl_video_format_t out_format_1; gavl_video_format_t in_format_1; gavl_video_format_t in_format_2; gavl_video_format_t out_format; /* Final output format */ gavl_video_format_t in_format; /* Input format of first filter */ bg_read_video_func_t in_func; void * in_data; int in_stream; bg_read_video_func_t read_func; void * read_data; int read_stream; pthread_mutex_t mutex; }; int bg_video_filter_chain_need_restart(bg_video_filter_chain_t * ch) { gavl_video_format_t test_format; if(!ch->need_restart) { gavl_video_format_copy(&test_format, &ch->in_format_1); bg_gavl_video_options_set_format(ch->opt, &ch->in_format_1, &test_format); if(!gavl_video_formats_equal(&test_format, &ch->in_format_2)) ch->need_restart = 1; } return ch->need_restart || ch->need_rebuild; } static int video_filter_create(video_filter_t * f, bg_video_filter_chain_t * ch, const char * name) { const bg_plugin_info_t * info; info = bg_plugin_find_by_name(ch->plugin_reg, name); if(!info) return 0; f->handle = bg_plugin_load(ch->plugin_reg, info); if(!f->handle) return 0; f->plugin = (bg_fv_plugin_t*)(f->handle->plugin); f->cnv = bg_video_converter_create(ch->opt->opt); return 1; } static void video_filter_destroy(video_filter_t * f) { bg_video_converter_destroy(f->cnv); if(f->handle) bg_plugin_unref_nolock(f->handle); } static void destroy_video_chain(bg_video_filter_chain_t * ch) { int i; /* Destroy previous filters */ for(i = 0; i < ch->num_filters; i++) video_filter_destroy(&ch->filters[i]); if(ch->filters) { free(ch->filters); ch->filters = NULL; } ch->num_filters = 0; } static void bg_video_filter_chain_rebuild(bg_video_filter_chain_t * ch) { int i; char ** filter_names; filter_names = bg_strbreak(ch->filter_string, ','); destroy_video_chain(ch); if(!filter_names) return; while(filter_names[ch->num_filters]) ch->num_filters++; ch->filters = calloc(ch->num_filters, sizeof(*ch->filters)); for(i = 0; i < ch->num_filters; i++) { video_filter_create(&ch->filters[i], ch, filter_names[i]); } bg_strbreak_free(filter_names); ch->need_rebuild = 0; } bg_video_filter_chain_t * bg_video_filter_chain_create(const bg_gavl_video_options_t * opt, bg_plugin_registry_t * plugin_reg) { bg_video_filter_chain_t * ret; ret = calloc(1, sizeof(*ret)); ret->opt = opt; ret->plugin_reg = plugin_reg; ret->cnv_out = bg_video_converter_create(opt->opt); pthread_mutex_init(&ret->mutex, NULL); return ret; } static void create_video_parameters(bg_video_filter_chain_t * ch) { ch->parameters = calloc(2, sizeof(*ch->parameters)); ch->parameters->name = bg_strdup(NULL, "video_filters"); ch->parameters->long_name = bg_strdup(NULL, TRS("Video Filters")); ch->parameters->preset_path = bg_strdup(NULL, "videofilters"); ch->parameters->gettext_domain = bg_strdup(NULL, PACKAGE); ch->parameters->gettext_directory = bg_strdup(NULL, LOCALE_DIR); ch->parameters->type = BG_PARAMETER_MULTI_CHAIN; ch->parameters->flags |= BG_PARAMETER_SYNC; bg_plugin_registry_set_parameter_info(ch->plugin_reg, BG_PLUGIN_FILTER_VIDEO, BG_PLUGIN_FILTER_1, ch->parameters); } const bg_parameter_info_t * bg_video_filter_chain_get_parameters(bg_video_filter_chain_t * ch) { if(!ch->parameters) create_video_parameters(ch); return ch->parameters; } void bg_video_filter_chain_set_parameter(void * data, const char * name, const bg_parameter_value_t * val) { int i; char * pos; video_filter_t * f; bg_video_filter_chain_t * ch; ch = (bg_video_filter_chain_t *)data; if(!name) { for(i = 0; i < ch->num_filters; i++) { if(ch->filters[i].plugin->common.set_parameter) ch->filters[i].plugin->common.set_parameter(ch->filters[i].handle->priv, NULL, NULL); } return; } if(!strcmp(name, "video_filters")) { if(!ch->filter_string && !val->val_str) goto the_end; if(ch->filter_string && val->val_str && !strcmp(ch->filter_string, val->val_str)) { goto the_end; } /* Rebuild chain */ ch->filter_string = bg_strdup(ch->filter_string, val->val_str); ch->need_rebuild = 1; } else if(!strncmp(name, "video_filters.", 14)) { if(ch->need_rebuild) bg_video_filter_chain_rebuild(ch); pos = strchr(name, '.'); pos++; i = atoi(pos); f = ch->filters + i; pos = strchr(pos, '.'); if(!pos) goto the_end; pos++; if(f->plugin->common.set_parameter) { f->plugin->common.set_parameter(f->handle->priv, pos, val); if(f->plugin->need_restart && f->plugin->need_restart(f->handle->priv)) ch->need_restart = 1; } } the_end: return; } int bg_video_filter_chain_init(bg_video_filter_chain_t * ch, const gavl_video_format_t * in_format, gavl_video_format_t * out_format) { int i; gavl_video_options_t * opt; gavl_video_format_t format_1; gavl_video_format_t format_2; video_filter_t * f; ch->need_restart = 0; if(ch->need_rebuild) bg_video_filter_chain_rebuild(ch); gavl_video_format_copy(&format_1, in_format); f = ch->filters; /* Set user defined format */ bg_gavl_video_options_set_format(ch->opt, in_format, &format_1); gavl_video_format_copy(&ch->in_format_1, in_format); gavl_video_format_copy(&ch->in_format_2, &format_1); ch->read_func = ch->in_func; ch->read_data = ch->in_data; ch->read_stream = ch->in_stream; for(i = 0; i < ch->num_filters; i++) { gavl_video_format_copy(&format_2, &format_1); if(f->plugin->get_options) { opt = f->plugin->get_options(f->handle->priv); gavl_video_options_copy(opt, ch->opt->opt); } f->plugin->set_input_format(f->handle->priv, &format_2, 0); if(!i) { f->do_convert = bg_video_converter_init(f->cnv, in_format, &format_2); gavl_video_format_copy(&ch->in_format, &format_2); } else f->do_convert = bg_video_converter_init(f->cnv, &format_1, &format_2); if(f->do_convert) { bg_video_converter_connect_input(f->cnv, ch->read_func, ch->read_data, ch->read_stream); f->plugin->connect_input_port(f->handle->priv, bg_video_converter_read, f->cnv, 0, 0); } else f->plugin->connect_input_port(f->handle->priv, ch->read_func, ch->read_data, ch->read_stream, 0); ch->read_func = f->plugin->read_video; ch->read_data = f->handle->priv; ch->read_stream = 0; // if(f->plugin->init) // f->plugin->init(f->handle->priv); f->plugin->get_output_format(f->handle->priv, &format_1); bg_log(BG_LOG_INFO, LOG_DOMAIN, "Initialized video filter %s", TRD(f->handle->info->long_name, f->handle->info->gettext_domain)); f++; } gavl_video_format_copy(&ch->out_format, &format_1); gavl_video_format_copy(out_format, &format_1); if(ch->num_filters) gavl_video_format_copy(&ch->out_format_1, &format_1); else gavl_video_format_copy(&ch->out_format_1, in_format); return ch->num_filters; } void bg_video_filter_chain_set_input_format(bg_video_filter_chain_t * ch, const gavl_video_format_t * format) { if(!ch->num_filters) { int do_convert_out; do_convert_out = bg_video_converter_init(ch->cnv_out, &ch->out_format_1, &ch->out_format); if(do_convert_out) { bg_video_converter_connect_input(ch->cnv_out, ch->in_func, ch->in_data, ch->in_stream); ch->read_func = bg_video_converter_read; ch->read_data = ch->cnv_out; ch->read_stream = 0; } } else { video_filter_t * f = ch->filters; f->do_convert = bg_video_converter_init(f->cnv, format, &ch->in_format); if(f->do_convert) { bg_video_converter_connect_input(f->cnv, ch->in_func, ch->in_data, ch->in_stream); f->plugin->connect_input_port(f->handle->priv, bg_video_converter_read, f->cnv, 0, 0); } else f->plugin->connect_input_port(f->handle->priv, ch->in_func, ch->in_data, ch->in_stream, 0); } } void bg_video_filter_chain_connect_input(bg_video_filter_chain_t * ch, bg_read_video_func_t func, void * priv, int stream) { ch->in_func = func; ch->in_data = priv; ch->in_stream = stream; } int bg_video_filter_chain_read(void * priv, gavl_video_frame_t* frame, int stream) { bg_video_filter_chain_t * ch; int ret; ch = (bg_video_filter_chain_t *)priv; bg_video_filter_chain_lock(ch); ret = ch->read_func(ch->read_data, frame, ch->read_stream); bg_video_filter_chain_unlock(ch); return ret; } int bg_video_filter_chain_set_out_format(bg_video_filter_chain_t * ch, const gavl_video_format_t * out_format) { int do_convert; do_convert = bg_video_converter_init(ch->cnv_out, &ch->out_format_1, out_format); if(do_convert) { bg_video_converter_connect_input(ch->cnv_out, ch->read_func, ch->read_data, ch->read_stream); ch->read_func = bg_video_converter_read; ch->read_data = ch->cnv_out; ch->read_stream = 0; } gavl_video_format_copy(&ch->out_format, out_format); return do_convert; } void bg_video_filter_chain_destroy(bg_video_filter_chain_t * ch) { if(ch->parameters) bg_parameter_info_destroy_array(ch->parameters); if(ch->filter_string) free(ch->filter_string); destroy_video_chain(ch); pthread_mutex_destroy(&ch->mutex); bg_video_converter_destroy(ch->cnv_out); free(ch); } void bg_video_filter_chain_lock(bg_video_filter_chain_t * cnv) { pthread_mutex_lock(&cnv->mutex); } void bg_video_filter_chain_unlock(bg_video_filter_chain_t * cnv) { pthread_mutex_unlock(&cnv->mutex); } void bg_video_filter_chain_reset(bg_video_filter_chain_t * ch) { int i; for(i = 0; i < ch->num_filters; i++) { if(ch->filters[i].plugin->reset) ch->filters[i].plugin->reset(ch->filters[i].handle->priv); bg_video_converter_reset(ch->filters[i].cnv); } bg_video_converter_reset(ch->cnv_out); } gmerlin-1.2.0~dfsg/lib/cfg_registry.c0000644000175000017500000000647011764363410017506 0ustar alessioalessio/***************************************************************** * gmerlin - a general purpose multimedia framework and applications * * Copyright (c) 2001 - 2011 Members of the Gmerlin project * gmerlin-general@lists.sourceforge.net * http://gmerlin.sourceforge.net * * 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 of the License, 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 this program. If not, see . * *****************************************************************/ #include #include #include #include #include #include bg_cfg_registry_t * bg_cfg_registry_create() { bg_cfg_registry_t * ret = calloc(1, sizeof(*ret)); return ret; } void bg_cfg_registry_destroy(bg_cfg_registry_t * r) { bg_cfg_section_t * next_section; while(r->sections) { next_section = r->sections->next; bg_cfg_section_destroy(r->sections); r->sections = next_section; } free(r); } /* * Path looks like "section:subsection:subsubsection" */ bg_cfg_section_t * bg_cfg_registry_find_section(bg_cfg_registry_t * r, const char * path) { int depth; int i, len; char * tmp_path; char ** tmp_sections; char * pos; bg_cfg_section_t * section; bg_cfg_section_t * prev_section; depth = 1; len = strlen(path); for(i = 0; i < len; i++) { if(path[i] == ':') depth++; } tmp_path = bg_strdup(NULL, path); tmp_sections = malloc(depth * sizeof(char*)); tmp_sections[0] = tmp_path; if(depth > 1) { pos = strchr(tmp_path, ':'); for(i = 1; i < depth; i++) { *pos = '\0'; pos++; tmp_sections[i] = pos; pos = strchr(pos, ':'); } } /* Find the root section */ section = r->sections; prev_section = NULL; while(section) { if(!strcmp(tmp_sections[0], section->name)) break; prev_section = section; section = section->next; } /* Add new section here, if not present */ if(!section) { if(prev_section) { prev_section->next = bg_cfg_section_create(tmp_sections[0]); section = prev_section->next; } else { r->sections = bg_cfg_section_create(tmp_sections[0]); section = r->sections; } } /* Get the subsections */ for(i = 1; i < depth; i++) { section = bg_cfg_section_find_subsection(section, tmp_sections[i]); } free(tmp_path); free(tmp_sections); return section; } int bg_cfg_registry_has_section(bg_cfg_registry_t * r, const char * name) { bg_cfg_section_t * section; section = r->sections; while(section) { if(!strcmp(section->name, name)) return 1; section = section->next; } return 0; } gmerlin-1.2.0~dfsg/lib/parameter_xml.c0000644000175000017500000007155511764363410017665 0ustar alessioalessio/***************************************************************** * gmerlin - a general purpose multimedia framework and applications * * Copyright (c) 2001 - 2011 Members of the Gmerlin project * gmerlin-general@lists.sourceforge.net * http://gmerlin.sourceforge.net * * 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 of the License, 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 this program. If not, see . * *****************************************************************/ #include #include // #include #include #include #include static const struct { char * name; bg_parameter_type_t type; } type_names[] = { { "section", BG_PARAMETER_SECTION }, { "checkbutton", BG_PARAMETER_CHECKBUTTON }, { "button", BG_PARAMETER_BUTTON }, { "int", BG_PARAMETER_INT }, { "float", BG_PARAMETER_FLOAT }, { "slider_int", BG_PARAMETER_SLIDER_INT }, { "slider_float", BG_PARAMETER_SLIDER_FLOAT }, { "string", BG_PARAMETER_STRING }, { "string_hidden", BG_PARAMETER_STRING_HIDDEN }, { "stringlist", BG_PARAMETER_STRINGLIST }, { "color_rgb", BG_PARAMETER_COLOR_RGB }, { "color_rgba", BG_PARAMETER_COLOR_RGBA }, { "font", BG_PARAMETER_FONT }, { "device", BG_PARAMETER_DEVICE }, { "file", BG_PARAMETER_FILE }, { "directory", BG_PARAMETER_DIRECTORY }, { "multi_menu", BG_PARAMETER_MULTI_MENU }, { "multi_list", BG_PARAMETER_MULTI_LIST }, { "multi_chain", BG_PARAMETER_MULTI_CHAIN }, { "time", BG_PARAMETER_TIME }, { "pos", BG_PARAMETER_POSITION } }; static const char * type_2_name(bg_parameter_type_t type) { int i; for(i = 0; i < sizeof(type_names)/sizeof(type_names[0]); i++) { if(type_names[i].type == type) return type_names[i].name; } return NULL; } static bg_parameter_type_t name_2_type(const char * name) { int i; for(i = 0; i < sizeof(type_names)/sizeof(type_names[0]); i++) { if(!strcmp(type_names[i].name, name)) return type_names[i].type; } return 0; } static const struct { char * name; int flag; } flag_names[] = { { "sync", BG_PARAMETER_SYNC }, { "hide_dialog", BG_PARAMETER_HIDE_DIALOG }, { "no_sort", BG_PARAMETER_NO_SORT }, { "plugin", BG_PARAMETER_PLUGIN }, { "own_section", BG_PARAMETER_OWN_SECTION }, { "global_preset", BG_PARAMETER_GLOBAL_PRESET }, }; static int string_to_flags(const char * str) { int i; int ret = 0; const char * start; const char * end; start = str; end = start; while(1) { while((*end != '\0') && (*end != '|')) end++; for(i = 0; i < sizeof(flag_names)/sizeof(flag_names[0]); i++) { if(!strncmp(flag_names[i].name, start, (int)(end-start))) ret |= flag_names[i].flag; } if(*end == '\0') return ret; end++; start = end; } return ret; } static char * flags_to_string(int flags) { int num = 0; int i; char * ret = NULL; for(i = 0; i < sizeof(flag_names)/sizeof(flag_names[0]); i++) { if(flag_names[i].flag & flags) { if(num) ret = bg_strcat(ret, "|"); ret = bg_strcat(ret, flag_names[i].name); num++; } } return ret; } static const char * const name_key = "NAME"; static const char * const long_name_key = "LONG_NAME"; static const char * const opt_key = "OPT"; static const char * const type_key = "TYPE"; static const char * const flags_key = "FLAGS"; static const char * const help_string_key = "HELP_STRING"; static const char * const default_key = "DEFAULT"; static const char * const range_key = "RANGE"; static const char * const num_digits_key = "NUM_DIGITS"; static const char * const num_key = "NUM"; static const char * const index_key = "INDEX"; static const char * const parameter_key = "PARAMETER"; static const char * const multi_names_key = "MULTI_NAMES"; static const char * const multi_name_key = "MULTI_NAME"; static const char * const multi_descs_key = "MULTI_DESCS"; static const char * const multi_desc_key = "MULTI_DESC"; static const char * const multi_labels_key = "MULTI_LABELS"; static const char * const multi_label_key = "MULTI_LABEL"; static const char * const multi_parameters_key = "MULTI_PARAMETERS"; static const char * const multi_parameter_key = "MULTI_PARAMETER"; static const char * const gettext_domain_key = "GETTEXT_DOMAIN"; static const char * const gettext_directory_key = "GETTEXT_DIRECTORY"; static const char * const preset_path_key = "PRESET_PATH"; /* */ bg_parameter_info_t * bg_xml_2_parameters(xmlDocPtr xml_doc, xmlNodePtr xml_parameters) { xmlNodePtr child, grandchild, cur; int index = 0; int multi_index, multi_num; int num_parameters; char * tmp_string; bg_parameter_info_t * ret = NULL; tmp_string = BG_XML_GET_PROP(xml_parameters, num_key); num_parameters = atoi(tmp_string); free(tmp_string); ret = calloc(num_parameters+1, sizeof(*ret)); cur = xml_parameters->children; while(cur) { if(!cur->name) { cur = cur->next; continue; } if(!BG_XML_STRCMP(cur->name, parameter_key)) { tmp_string = BG_XML_GET_PROP(cur, type_key); ret[index].type = name_2_type(tmp_string); free(tmp_string); tmp_string = BG_XML_GET_PROP(cur, name_key); ret[index].name = bg_strdup(ret[index].name, tmp_string); free(tmp_string); child = cur->children; while(child) { if(!child->name) { child = child->next; continue; } if(!BG_XML_STRCMP(child->name, long_name_key)) { tmp_string = (char*)xmlNodeListGetString(xml_doc, child->children, 1); ret[index].long_name = bg_strdup(ret[index].long_name, tmp_string); free(tmp_string); } else if(!BG_XML_STRCMP(child->name, flags_key)) { tmp_string = (char*)xmlNodeListGetString(xml_doc, child->children, 1); ret[index].flags = string_to_flags(tmp_string); free(tmp_string); } else if(!BG_XML_STRCMP(child->name, opt_key)) { tmp_string = (char*)xmlNodeListGetString(xml_doc, child->children, 1); ret[index].opt = bg_strdup(ret[index].opt, tmp_string); free(tmp_string); } else if(!BG_XML_STRCMP(child->name, help_string_key)) { tmp_string = (char*)xmlNodeListGetString(xml_doc, child->children, 1); ret[index].help_string = bg_strdup(ret[index].help_string, tmp_string); free(tmp_string); } else if(!BG_XML_STRCMP(child->name, gettext_domain_key)) { tmp_string = (char*)xmlNodeListGetString(xml_doc, child->children, 1); ret[index].gettext_domain = bg_strdup(ret[index].gettext_domain, tmp_string); free(tmp_string); } else if(!BG_XML_STRCMP(child->name, gettext_directory_key)) { tmp_string = (char*)xmlNodeListGetString(xml_doc, child->children, 1); ret[index].gettext_directory = bg_strdup(ret[index].gettext_directory, tmp_string); free(tmp_string); } else if(!BG_XML_STRCMP(child->name, preset_path_key)) { tmp_string = (char*)xmlNodeListGetString(xml_doc, child->children, 1); ret[index].preset_path = bg_strdup(ret[index].preset_path, tmp_string); free(tmp_string); } else if(!BG_XML_STRCMP(child->name, multi_names_key)) { tmp_string = BG_XML_GET_PROP(child, num_key); multi_num = atoi(tmp_string); free(tmp_string); ret[index].multi_names_nc = calloc(multi_num+1, sizeof(*(ret[index].multi_names))); multi_index = 0; grandchild = child->children; while(grandchild) { if(!grandchild->name) { grandchild = grandchild->next; continue; } if(!BG_XML_STRCMP(grandchild->name, multi_name_key)) { tmp_string = (char*)xmlNodeListGetString(xml_doc, grandchild->children, 1); ret[index].multi_names_nc[multi_index] = bg_strdup(ret[index].multi_names_nc[multi_index], tmp_string); free(tmp_string); multi_index++; } grandchild = grandchild->next; } } else if(!BG_XML_STRCMP(child->name, multi_descs_key)) { tmp_string = BG_XML_GET_PROP(child, num_key); multi_num = atoi(tmp_string); free(tmp_string); ret[index].multi_descriptions_nc = calloc(multi_num+1, sizeof(*(ret[index].multi_descriptions_nc))); multi_index = 0; grandchild = child->children; while(grandchild) { if(!grandchild->name) { grandchild = grandchild->next; continue; } if(!BG_XML_STRCMP(grandchild->name, multi_desc_key)) { tmp_string = (char*)xmlNodeListGetString(xml_doc, grandchild->children, 1); ret[index].multi_descriptions_nc[multi_index] = bg_strdup(ret[index].multi_descriptions_nc[multi_index], tmp_string); free(tmp_string); multi_index++; } grandchild = grandchild->next; } } else if(!BG_XML_STRCMP(child->name, multi_labels_key)) { tmp_string = BG_XML_GET_PROP(child, num_key); multi_num = atoi(tmp_string); free(tmp_string); ret[index].multi_labels_nc = calloc(multi_num+1, sizeof(*(ret[index].multi_labels))); multi_index = 0; grandchild = child->children; while(grandchild) { if(!grandchild->name) { grandchild = grandchild->next; continue; } if(!BG_XML_STRCMP(grandchild->name, multi_label_key)) { tmp_string = (char*)xmlNodeListGetString(xml_doc, grandchild->children, 1); ret[index].multi_labels_nc[multi_index] = bg_strdup(ret[index].multi_labels_nc[multi_index], tmp_string); free(tmp_string); multi_index++; } grandchild = grandchild->next; } } else if(!BG_XML_STRCMP(child->name, multi_parameters_key)) { tmp_string = BG_XML_GET_PROP(child, num_key); multi_num = atoi(tmp_string); free(tmp_string); ret[index].multi_parameters_nc = calloc(multi_num+1, sizeof(*(ret[index].multi_labels))); grandchild = child->children; while(grandchild) { if(!grandchild->name) { grandchild = grandchild->next; continue; } if(!BG_XML_STRCMP(grandchild->name, multi_parameter_key)) { tmp_string = BG_XML_GET_PROP(grandchild, index_key); multi_index = atoi(tmp_string); free(tmp_string); ret[index].multi_parameters_nc[multi_index] = bg_xml_2_parameters(xml_doc, grandchild); } grandchild = grandchild->next; } } else if(!BG_XML_STRCMP(child->name, default_key)) { tmp_string = (char*)xmlNodeListGetString(xml_doc, child->children, 1); switch(ret[index].type) { case BG_PARAMETER_STRING_HIDDEN: case BG_PARAMETER_SECTION: case BG_PARAMETER_BUTTON: break; case BG_PARAMETER_SLIDER_INT: case BG_PARAMETER_CHECKBUTTON: case BG_PARAMETER_INT: sscanf(tmp_string, "%d", &ret[index].val_default.val_i); break; case BG_PARAMETER_FLOAT: case BG_PARAMETER_SLIDER_FLOAT: sscanf(tmp_string, "%lf", &ret[index].val_default.val_f); break; case BG_PARAMETER_STRING: case BG_PARAMETER_STRINGLIST: case BG_PARAMETER_FONT: case BG_PARAMETER_DEVICE: case BG_PARAMETER_FILE: case BG_PARAMETER_DIRECTORY: case BG_PARAMETER_MULTI_MENU: case BG_PARAMETER_MULTI_LIST: case BG_PARAMETER_MULTI_CHAIN: ret[index].val_default.val_str = bg_strdup(ret[index].val_default.val_str, tmp_string); break; case BG_PARAMETER_COLOR_RGB: sscanf(tmp_string, "%f %f %f", &ret[index].val_default.val_color[0], &ret[index].val_default.val_color[1], &ret[index].val_default.val_color[2]); break; case BG_PARAMETER_COLOR_RGBA: sscanf(tmp_string, "%f %f %f %f", &ret[index].val_default.val_color[0], &ret[index].val_default.val_color[1], &ret[index].val_default.val_color[2], &ret[index].val_default.val_color[3]); break; case BG_PARAMETER_POSITION: sscanf(tmp_string, "%lf %lf", &ret[index].val_default.val_pos[0], &ret[index].val_default.val_pos[1]); break; case BG_PARAMETER_TIME: sscanf(tmp_string, "%" PRId64, &ret[index].val_default.val_time); break; } free(tmp_string); } else if(!BG_XML_STRCMP(child->name, range_key)) { tmp_string = (char*)xmlNodeListGetString(xml_doc, child->children, 1); switch(ret[index].type) { case BG_PARAMETER_STRING_HIDDEN: case BG_PARAMETER_SECTION: case BG_PARAMETER_CHECKBUTTON: case BG_PARAMETER_STRING: case BG_PARAMETER_STRINGLIST: case BG_PARAMETER_FONT: case BG_PARAMETER_DEVICE: case BG_PARAMETER_FILE: case BG_PARAMETER_DIRECTORY: case BG_PARAMETER_MULTI_MENU: case BG_PARAMETER_MULTI_LIST: case BG_PARAMETER_MULTI_CHAIN: case BG_PARAMETER_COLOR_RGB: case BG_PARAMETER_COLOR_RGBA: case BG_PARAMETER_POSITION: case BG_PARAMETER_BUTTON: break; case BG_PARAMETER_SLIDER_INT: case BG_PARAMETER_INT: sscanf(tmp_string, "%d %d", &ret[index].val_min.val_i, &ret[index].val_max.val_i); break; case BG_PARAMETER_FLOAT: case BG_PARAMETER_SLIDER_FLOAT: sscanf(tmp_string, "%lf %lf", &ret[index].val_min.val_f, &ret[index].val_max.val_f); break; case BG_PARAMETER_TIME: sscanf(tmp_string, "%" PRId64 " %" PRId64, &ret[index].val_min.val_time, &ret[index].val_max.val_time); break; } free(tmp_string); } else if(!BG_XML_STRCMP(child->name, num_digits_key)) { tmp_string = (char*)xmlNodeListGetString(xml_doc, child->children, 1); sscanf(tmp_string, "%d", &ret[index].num_digits); free(tmp_string); } child = child->next; } bg_parameter_info_set_const_ptrs(&ret[index]); index++; } cur = cur->next; } return ret; } /* */ void bg_parameters_2_xml(const bg_parameter_info_t * info, xmlNodePtr xml_parameters) { int multi_num, i; xmlNodePtr xml_info; xmlNodePtr child, grandchild; int num_parameters = 0; char * tmp_string; xmlAddChild(xml_parameters, BG_XML_NEW_TEXT("\n")); while(info[num_parameters].name) { xml_info = xmlNewTextChild(xml_parameters, NULL, (xmlChar*)parameter_key, NULL); BG_XML_SET_PROP(xml_info, name_key, info[num_parameters].name); BG_XML_SET_PROP(xml_info, type_key, type_2_name(info[num_parameters].type)); xmlAddChild(xml_info, BG_XML_NEW_TEXT("\n")); if(info[num_parameters].long_name) { child = xmlNewTextChild(xml_info, NULL, (xmlChar*)long_name_key, NULL); xmlAddChild(child, BG_XML_NEW_TEXT(info[num_parameters].long_name)); xmlAddChild(xml_info, BG_XML_NEW_TEXT("\n")); } if(info[num_parameters].opt) { child = xmlNewTextChild(xml_info, NULL, (xmlChar*)opt_key, NULL); xmlAddChild(child, BG_XML_NEW_TEXT(info[num_parameters].opt)); xmlAddChild(xml_info, BG_XML_NEW_TEXT("\n")); } if(info[num_parameters].flags) { child = xmlNewTextChild(xml_info, NULL, (xmlChar*)flags_key, NULL); tmp_string = flags_to_string(info[num_parameters].flags); xmlAddChild(child, BG_XML_NEW_TEXT(tmp_string)); free(tmp_string); xmlAddChild(xml_info, BG_XML_NEW_TEXT("\n")); } if(info[num_parameters].help_string) { child = xmlNewTextChild(xml_info, NULL, (xmlChar*)help_string_key, NULL); xmlAddChild(child, BG_XML_NEW_TEXT(info[num_parameters].help_string)); xmlAddChild(xml_info, BG_XML_NEW_TEXT("\n")); } if(info[num_parameters].gettext_domain) { child = xmlNewTextChild(xml_info, NULL, (xmlChar*)gettext_domain_key, NULL); xmlAddChild(child, BG_XML_NEW_TEXT(info[num_parameters].gettext_domain)); xmlAddChild(xml_info, BG_XML_NEW_TEXT("\n")); } if(info[num_parameters].gettext_directory) { child = xmlNewTextChild(xml_info, NULL, (xmlChar*)gettext_directory_key, NULL); xmlAddChild(child, BG_XML_NEW_TEXT(info[num_parameters].gettext_directory)); xmlAddChild(xml_info, BG_XML_NEW_TEXT("\n")); } if(info[num_parameters].preset_path) { child = xmlNewTextChild(xml_info, NULL, (xmlChar*)preset_path_key, NULL); xmlAddChild(child, BG_XML_NEW_TEXT(info[num_parameters].preset_path)); xmlAddChild(xml_info, BG_XML_NEW_TEXT("\n")); } multi_num = 0; if(info[num_parameters].multi_names) { while(info[num_parameters].multi_names[multi_num]) multi_num++; child = xmlNewTextChild(xml_info, NULL, (xmlChar*)multi_names_key, NULL); xmlAddChild(child, BG_XML_NEW_TEXT("\n")); tmp_string = bg_sprintf("%d", multi_num); BG_XML_SET_PROP(child, num_key, tmp_string); free(tmp_string); for(i = 0; i < multi_num; i++) { grandchild = xmlNewTextChild(child, NULL, (xmlChar*)multi_name_key, NULL); xmlAddChild(grandchild, BG_XML_NEW_TEXT(info[num_parameters].multi_names[i])); xmlAddChild(child, BG_XML_NEW_TEXT("\n")); } xmlAddChild(xml_info, BG_XML_NEW_TEXT("\n")); } if(info[num_parameters].multi_labels) { child = xmlNewTextChild(xml_info, NULL, (xmlChar*)multi_labels_key, NULL); xmlAddChild(child, BG_XML_NEW_TEXT("\n")); tmp_string = bg_sprintf("%d", multi_num); BG_XML_SET_PROP(child, num_key, tmp_string); free(tmp_string); for(i = 0; i < multi_num; i++) { grandchild = xmlNewTextChild(child, NULL, (xmlChar*)multi_label_key, NULL); xmlAddChild(grandchild, BG_XML_NEW_TEXT(info[num_parameters].multi_labels[i])); xmlAddChild(child, BG_XML_NEW_TEXT("\n")); } xmlAddChild(xml_info, BG_XML_NEW_TEXT("\n")); } if(info[num_parameters].multi_descriptions) { child = xmlNewTextChild(xml_info, NULL, (xmlChar*)multi_descs_key, NULL); xmlAddChild(child, BG_XML_NEW_TEXT("\n")); tmp_string = bg_sprintf("%d", multi_num); BG_XML_SET_PROP(child, num_key, tmp_string); free(tmp_string); for(i = 0; i < multi_num; i++) { grandchild = xmlNewTextChild(child, NULL, (xmlChar*)multi_desc_key, NULL); xmlAddChild(grandchild, BG_XML_NEW_TEXT(info[num_parameters].multi_descriptions[i])); xmlAddChild(child, BG_XML_NEW_TEXT("\n")); } xmlAddChild(xml_info, BG_XML_NEW_TEXT("\n")); } if(info[num_parameters].multi_parameters) { child = xmlNewTextChild(xml_info, NULL, (xmlChar*)multi_parameters_key, NULL); xmlAddChild(child, BG_XML_NEW_TEXT("\n")); tmp_string = bg_sprintf("%d", multi_num); BG_XML_SET_PROP(child, num_key, tmp_string); free(tmp_string); for(i = 0; i < multi_num; i++) { if(info[num_parameters].multi_parameters[i]) { grandchild = xmlNewTextChild(child, NULL, (xmlChar*)multi_parameter_key, NULL); tmp_string = bg_sprintf("%d", i); BG_XML_SET_PROP(grandchild, index_key, tmp_string); free(tmp_string); bg_parameters_2_xml(info[num_parameters].multi_parameters[i], grandchild); xmlAddChild(child, BG_XML_NEW_TEXT("\n")); } } xmlAddChild(xml_info, BG_XML_NEW_TEXT("\n")); } switch(info[num_parameters].type) { case BG_PARAMETER_SECTION: case BG_PARAMETER_BUTTON: break; case BG_PARAMETER_CHECKBUTTON: if(info[num_parameters].val_default.val_i) { child = xmlNewTextChild(xml_info, NULL, (xmlChar*)default_key, NULL); xmlAddChild(child, BG_XML_NEW_TEXT("1")); xmlAddChild(xml_info, BG_XML_NEW_TEXT("\n")); } break; case BG_PARAMETER_INT: case BG_PARAMETER_SLIDER_INT: if(info[num_parameters].val_default.val_i) { child = xmlNewTextChild(xml_info, NULL, (xmlChar*)default_key, NULL); tmp_string = bg_sprintf("%d", info[num_parameters].val_default.val_i); xmlAddChild(child, BG_XML_NEW_TEXT(tmp_string)); free(tmp_string); xmlAddChild(xml_info, BG_XML_NEW_TEXT("\n")); } if(info[num_parameters].val_min.val_i < info[num_parameters].val_max.val_i) { child = xmlNewTextChild(xml_info, NULL, (xmlChar*)range_key, NULL); tmp_string = bg_sprintf("%d %d", info[num_parameters].val_min.val_i, info[num_parameters].val_max.val_i); xmlAddChild(child, BG_XML_NEW_TEXT(tmp_string)); free(tmp_string); xmlAddChild(xml_info, BG_XML_NEW_TEXT("\n")); } break; case BG_PARAMETER_FLOAT: case BG_PARAMETER_SLIDER_FLOAT: if(info[num_parameters].val_default.val_f != 0.0) { child = xmlNewTextChild(xml_info, NULL, (xmlChar*)default_key, NULL); tmp_string = bg_sprintf("%f", info[num_parameters].val_default.val_f); xmlAddChild(child, BG_XML_NEW_TEXT(tmp_string)); free(tmp_string); xmlAddChild(xml_info, BG_XML_NEW_TEXT("\n")); } if(info[num_parameters].val_min.val_f < info[num_parameters].val_max.val_f) { child = xmlNewTextChild(xml_info, NULL, (xmlChar*)range_key, NULL); tmp_string = bg_sprintf("%f %f", info[num_parameters].val_min.val_f, info[num_parameters].val_max.val_f); xmlAddChild(child, BG_XML_NEW_TEXT(tmp_string)); free(tmp_string); xmlAddChild(xml_info, BG_XML_NEW_TEXT("\n")); } break; case BG_PARAMETER_TIME: if(info[num_parameters].val_default.val_time) { child = xmlNewTextChild(xml_info, NULL, (xmlChar*)default_key, NULL); tmp_string = bg_sprintf("%d", info[num_parameters].val_default.val_i); xmlAddChild(child, BG_XML_NEW_TEXT(tmp_string)); free(tmp_string); xmlAddChild(xml_info, BG_XML_NEW_TEXT("\n")); } if(info[num_parameters].val_min.val_time < info[num_parameters].val_max.val_time) { child = xmlNewTextChild(xml_info, NULL, (xmlChar*)range_key, NULL); tmp_string = bg_sprintf("%" PRId64 " %" PRId64, info[num_parameters].val_min.val_time, info[num_parameters].val_max.val_time); xmlAddChild(child, BG_XML_NEW_TEXT(tmp_string)); free(tmp_string); xmlAddChild(xml_info, BG_XML_NEW_TEXT("\n")); } break; case BG_PARAMETER_STRING: case BG_PARAMETER_FONT: case BG_PARAMETER_FILE: case BG_PARAMETER_DIRECTORY: case BG_PARAMETER_DEVICE: case BG_PARAMETER_MULTI_MENU: case BG_PARAMETER_MULTI_LIST: case BG_PARAMETER_MULTI_CHAIN: case BG_PARAMETER_STRINGLIST: if(info[num_parameters].val_default.val_str) { child = xmlNewTextChild(xml_info, NULL, (xmlChar*)default_key, NULL); xmlAddChild(child, BG_XML_NEW_TEXT(info[num_parameters].val_default.val_str)); xmlAddChild(xml_info, BG_XML_NEW_TEXT("\n")); } break; case BG_PARAMETER_STRING_HIDDEN: break; /* Hidden strings never have defaults */ case BG_PARAMETER_COLOR_RGB: if(info[num_parameters].val_default.val_color) { child = xmlNewTextChild(xml_info, NULL, (xmlChar*)default_key, NULL); tmp_string = bg_sprintf("%f %f %f", info[num_parameters].val_default.val_color[0], info[num_parameters].val_default.val_color[1], info[num_parameters].val_default.val_color[2]); xmlAddChild(child, BG_XML_NEW_TEXT(tmp_string)); free(tmp_string); xmlAddChild(xml_info, BG_XML_NEW_TEXT("\n")); } break; case BG_PARAMETER_COLOR_RGBA: if(info[num_parameters].val_default.val_color) { child = xmlNewTextChild(xml_info, NULL, (xmlChar*)default_key, NULL); tmp_string = bg_sprintf("%f %f %f %f", info[num_parameters].val_default.val_color[0], info[num_parameters].val_default.val_color[1], info[num_parameters].val_default.val_color[2], info[num_parameters].val_default.val_color[3]); xmlAddChild(child, BG_XML_NEW_TEXT(tmp_string)); free(tmp_string); xmlAddChild(xml_info, BG_XML_NEW_TEXT("\n")); } break; case BG_PARAMETER_POSITION: if((info[num_parameters].val_default.val_pos[0] != 0.0) || (info[num_parameters].val_default.val_pos[1] != 0.0)) { child = xmlNewTextChild(xml_info, NULL, (xmlChar*)default_key, NULL); tmp_string = bg_sprintf("%f %f", info[num_parameters].val_default.val_pos[0], info[num_parameters].val_default.val_pos[1]); xmlAddChild(child, BG_XML_NEW_TEXT(tmp_string)); free(tmp_string); xmlAddChild(xml_info, BG_XML_NEW_TEXT("\n")); } break; } if(info[num_parameters].num_digits) { child = xmlNewTextChild(xml_info, NULL, (xmlChar*)num_digits_key, NULL); tmp_string = bg_sprintf("%d", info[num_parameters].num_digits); xmlAddChild(child, BG_XML_NEW_TEXT(tmp_string)); free(tmp_string); xmlAddChild(xml_info, BG_XML_NEW_TEXT("\n")); } xmlAddChild(xml_parameters, BG_XML_NEW_TEXT("\n")); num_parameters++; } tmp_string = bg_sprintf("%d", num_parameters); BG_XML_SET_PROP(xml_parameters, num_key, tmp_string); free(tmp_string); } void bg_parameters_dump(const bg_parameter_info_t * info, const char * filename) { xmlDocPtr xml_doc; xmlNodePtr xml_params; xml_doc = xmlNewDoc((xmlChar*)"1.0"); xml_params = xmlNewDocRawNode(xml_doc, NULL, (xmlChar*)"PARAMETERS", NULL); xmlDocSetRootElement(xml_doc, xml_params); bg_parameters_2_xml(info, xml_params); xmlSaveFile(filename, xml_doc); xmlFreeDoc(xml_doc); } gmerlin-1.2.0~dfsg/lib/visualize.c0000644000175000017500000004002411764363410017023 0ustar alessioalessio/***************************************************************** * gmerlin - a general purpose multimedia framework and applications * * Copyright (c) 2001 - 2011 Members of the Gmerlin project * gmerlin-general@lists.sourceforge.net * http://gmerlin.sourceforge.net * * 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 of the License, 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 this program. If not, see . * *****************************************************************/ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #define LOG_DOMAIN "visualizer" /* * gmerlin_visualize_slave * -w "window_id" * -p "plugin_module" * -o "output_module" */ struct bg_visualizer_s { bg_msg_t * msg; bg_plugin_registry_t * plugin_reg; bg_plugin_handle_t * ov_handle; bg_ov_plugin_t * ov_plugin; pthread_mutex_t mutex; int changed; bg_subprocess_t * proc; const bg_plugin_info_t * vis_info; const bg_plugin_info_t * ov_info; int image_width; int image_height; float framerate; float gain; sigset_t oldset; gavl_audio_format_t audio_format; double fps; const char * display_string; bg_ov_callbacks_t * cb; }; static int proc_write_func(void * data, const uint8_t * ptr, int len) { bg_visualizer_t * v = (bg_visualizer_t *)data; return write(v->proc->stdin_fd, ptr, len); } static int proc_read_func(void * data, uint8_t * ptr, int len) { bg_visualizer_t * v = (bg_visualizer_t *)data; return read(v->proc->stdout_fd, ptr, len); } static void write_message(bg_visualizer_t * v) { int result; if(!v->proc) { bg_msg_free(v->msg); return; } //fprintf(stderr, "Write message master...\n"); result = bg_msg_write(v->msg, proc_write_func, v); //fprintf(stderr, "Write message master done %d\n", result); if(!result) { bg_subprocess_close(v->proc); v->proc = NULL; bg_log(BG_LOG_ERROR, LOG_DOMAIN, "Visualization process crashed, restart to try again"); } bg_msg_free(v->msg); } static int read_message(bg_visualizer_t * v) { int result; if(!v->proc) return 0; //fprintf(stderr, "Read message master...\n"); result = bg_msg_read(v->msg, proc_read_func, v); //fprintf(stderr, "Read message master done %d\n", result); if(!result) { bg_subprocess_close(v->proc); v->proc = NULL; bg_log(BG_LOG_ERROR, LOG_DOMAIN, "Visualization process crashed, restart to try again"); return 0; } return 1; } static void set_gain(bg_visualizer_t * v) { bg_msg_set_id(v->msg, BG_VIS_MSG_GAIN); bg_msg_set_arg_float(v->msg, 0, v->gain); write_message(v); } static void set_fps(bg_visualizer_t * v) { bg_msg_set_id(v->msg, BG_VIS_MSG_FPS); bg_msg_set_arg_float(v->msg, 0, v->framerate); write_message(v); } static void set_ov_parameter(void * data, const char * name, const bg_parameter_value_t * val) { const bg_parameter_info_t * info; bg_visualizer_t * v = (bg_visualizer_t*)data; bg_msg_set_id(v->msg, BG_VIS_MSG_OV_PARAM); if(name) { info = bg_parameter_find(v->ov_info->parameters, name); if(!info) return; bg_msg_set_parameter(v->msg, name, info->type, val); } else bg_msg_set_parameter(v->msg, name, 0, NULL); write_message(v); } static void set_vis_parameter(void * data, const char * name, const bg_parameter_value_t * val) { const bg_parameter_info_t * info; bg_visualizer_t * v = (bg_visualizer_t*)data; bg_msg_set_id(v->msg, BG_VIS_MSG_VIS_PARAM); if(name) { info = bg_parameter_find(v->vis_info->parameters, name); if(!info) return; bg_msg_set_parameter(v->msg, name, info->type, val); } else bg_msg_set_parameter(v->msg, name, 0, NULL); write_message(v); } double bg_visualizer_get_fps(bg_visualizer_t * v) { return v->fps; } static int visualizer_start(bg_visualizer_t * v) { char * command; bg_cfg_section_t * section; sigset_t newset; pthread_mutex_lock(&v->mutex); if(v->proc) { pthread_mutex_unlock(&v->mutex); return 0; } if(!v->vis_info) { pthread_mutex_unlock(&v->mutex); return 0; } /* Block SIGPIPE */ sigemptyset(&newset); sigaddset(&newset, SIGPIPE); pthread_sigmask(SIG_BLOCK, &newset, &v->oldset); /* Start process */ if(v->vis_info->flags & BG_PLUGIN_VISUALIZE_FRAME) { command = bg_sprintf("gmerlin_visualizer_slave -w %s -o %s -p ", v->display_string, v->ov_info->module_filename); } else { command = bg_sprintf("gmerlin_visualizer_slave -w %s -p ", v->display_string); } #ifdef HAVE_LV if(v->vis_info->api == BG_PLUGIN_API_LV) command = bg_strcat(command, v->vis_info->name); else #endif command = bg_strcat(command, v->vis_info->module_filename); v->proc = bg_subprocess_create(command, 1, 1, 0); if(!v->proc) return 0; free(command); /* Audio format */ bg_msg_set_id(v->msg, BG_VIS_MSG_AUDIO_FORMAT); bg_msg_set_arg_audio_format(v->msg, 0, &v->audio_format); write_message(v); /* default ov parameters */ if(v->ov_info->parameters && (v->vis_info->flags & BG_PLUGIN_VISUALIZE_FRAME)) { section = bg_plugin_registry_get_section(v->plugin_reg, v->ov_info->name); bg_cfg_section_apply(section, v->ov_info->parameters, set_ov_parameter, v); } /* default vis parameters */ if(v->vis_info->parameters) { section = bg_plugin_registry_get_section(v->plugin_reg, v->vis_info->name); bg_cfg_section_apply(section, v->vis_info->parameters, set_vis_parameter, v); } /* Gain */ set_gain(v); /* Image size */ bg_msg_set_id(v->msg, BG_VIS_MSG_IMAGE_SIZE); bg_msg_set_arg_int(v->msg, 0, v->image_width); bg_msg_set_arg_int(v->msg, 1, v->image_height); write_message(v); /* FPS*/ set_fps(v); /* All done, start */ bg_msg_set_id(v->msg, BG_VIS_MSG_START); bg_msg_set_arg_float(v->msg, 0, v->gain); write_message(v); /* Show window */ if(v->ov_plugin) { v->ov_plugin->show_window(v->ov_handle->priv, 1); v->ov_plugin->set_window_title(v->ov_handle->priv, v->vis_info->long_name); } pthread_mutex_unlock(&v->mutex); return 1; } bg_visualizer_t * bg_visualizer_create(bg_plugin_registry_t * plugin_reg) { bg_visualizer_t * ret; ret = calloc(1, sizeof(*ret)); ret->plugin_reg = plugin_reg; pthread_mutex_init(&ret->mutex, NULL); ret->msg = bg_msg_create(); return ret; } void bg_visualizer_destroy(bg_visualizer_t * v) { pthread_mutex_destroy(&v->mutex); bg_msg_destroy(v->msg); free(v); } static const bg_parameter_info_t parameters[] = { { .name = "width", .long_name = TRS("Width"), .type = BG_PARAMETER_INT, .flags = BG_PARAMETER_SYNC, .val_min = { .val_i = 16 }, .val_max = { .val_i = 32768 }, .val_default = { .val_i = 320 }, .help_string = TRS("Desired image with, the visualization plugin might override this for no apparent reason"), }, { .name = "height", .long_name = TRS("Height"), .type = BG_PARAMETER_INT, .flags = BG_PARAMETER_SYNC, .val_min = { .val_i = 16 }, .val_max = { .val_i = 32768 }, .val_default = { .val_i = 240 }, .help_string = TRS("Desired image height, the visualization plugin might override this for no apparent reason"), }, { .name = "framerate", .long_name = TRS("Framerate"), .type = BG_PARAMETER_FLOAT, .flags = BG_PARAMETER_SYNC, .val_min = { .val_f = 1.0 }, .val_max = { .val_f = 200.0 }, .val_default = { .val_f = 30.0 }, .num_digits = 2, }, { .name = "gain", .long_name = TRS("Gain"), .type = BG_PARAMETER_SLIDER_FLOAT, .flags = BG_PARAMETER_SYNC, .val_min = { .val_f = -10.0 }, .val_max = { .val_f = 10.0 }, .val_default = { .val_f = 0.0 }, .num_digits = 2, .help_string = TRS("Gain (in dB) to apply to the audio samples before it is sent to the visualization plugin"), }, { /* End of parameters */ } }; const bg_parameter_info_t * bg_visualizer_get_parameters(bg_visualizer_t * v) { return parameters; } void bg_visualizer_set_vis_plugin(bg_visualizer_t * v, const bg_plugin_info_t * info) { if(!v->vis_info || strcmp(v->vis_info->name, info->name)) { v->changed = 1; v->vis_info = info; bg_log(BG_LOG_DEBUG, LOG_DOMAIN, "Got visualization plugin %s", v->vis_info->name); } } void bg_visualizer_set_vis_parameter(void * priv, const char * name, const bg_parameter_value_t * val) { bg_visualizer_t * v; v = (bg_visualizer_t *)priv; pthread_mutex_lock(&v->mutex); if(v->proc) set_vis_parameter(v, name, val); pthread_mutex_unlock(&v->mutex); } void bg_visualizer_set_parameter(void * priv, const char * name, const bg_parameter_value_t * val) { bg_visualizer_t * v; if(!name) return; v = (bg_visualizer_t*)priv; if(!strcmp(name, "width")) { if(v->image_width != val->val_i) { v->image_width = val->val_i; v->changed = 1; } } else if(!strcmp(name, "height")) { if(v->image_height != val->val_i) { v->image_height = val->val_i; v->changed = 1; } } else if(!strcmp(name, "framerate")) { v->framerate = val->val_f; pthread_mutex_lock(&v->mutex); if(v->proc) set_fps(v); pthread_mutex_unlock(&v->mutex); } else if(!strcmp(name, "gain")) { v->gain = val->val_f; pthread_mutex_lock(&v->mutex); if(v->proc) set_gain(v); pthread_mutex_unlock(&v->mutex); } } void bg_visualizer_set_audio_format(bg_visualizer_t * v, const gavl_audio_format_t * format) { pthread_mutex_lock(&v->mutex); gavl_audio_format_copy(&v->audio_format, format); if(v->proc) { bg_msg_set_id(v->msg, BG_VIS_MSG_AUDIO_FORMAT); bg_msg_set_arg_audio_format(v->msg, 0, &v->audio_format); write_message(v); } pthread_mutex_unlock(&v->mutex); } void bg_visualizer_open_plugin(bg_visualizer_t * v, const gavl_audio_format_t * format, bg_plugin_handle_t * ov_handle) { /* Set audio format */ gavl_audio_format_copy(&v->audio_format, format); /* Set ov plugin */ v->ov_handle = ov_handle; v->ov_plugin = (bg_ov_plugin_t*)(ov_handle->plugin); v->ov_info = v->ov_handle->info; v->display_string = v->ov_plugin->get_window(v->ov_handle->priv); v->changed = 0; visualizer_start(v); } void bg_visualizer_open_id(bg_visualizer_t * v, const gavl_audio_format_t * format, const bg_plugin_info_t * ov_info, const char * display_name) { /* Set audio format */ gavl_audio_format_copy(&v->audio_format, format); /* Set ov plugin */ v->ov_handle = NULL; v->ov_plugin = NULL; v->ov_info = ov_info; v->display_string = display_name; v->changed = 0; visualizer_start(v); } static int handle_slave_message(bg_visualizer_t * v) { char * domain; char * msg; int id; id = bg_msg_get_id(v->msg); switch(id) { case BG_LOG_INFO: case BG_LOG_ERROR: case BG_LOG_WARNING: case BG_LOG_DEBUG: domain = bg_msg_get_arg_string(v->msg, 0); msg = bg_msg_get_arg_string(v->msg, 1); bg_log_notranslate(id, domain, "%s", msg); free(domain); free(msg); break; case BG_VIS_SLAVE_MSG_FPS: v->fps = bg_msg_get_arg_float(v->msg, 0); break; case BG_VIS_SLAVE_MSG_END: return 0; break; case BG_VIS_MSG_CB_MOTION: // x, y, mask if(v->cb && v->cb->motion_callback) v->cb->motion_callback(v->cb->data, bg_msg_get_arg_int(v->msg, 0), bg_msg_get_arg_int(v->msg, 1), bg_msg_get_arg_int(v->msg, 2)); break; case BG_VIS_MSG_CB_BUTTON: // x, y, button, mask if(v->cb && v->cb->button_callback) v->cb->button_callback(v->cb->data, bg_msg_get_arg_int(v->msg, 0), bg_msg_get_arg_int(v->msg, 1), bg_msg_get_arg_int(v->msg, 2), bg_msg_get_arg_int(v->msg, 3)); break; case BG_VIS_MSG_CB_BUTTON_REL: // x, y, button, mask if(v->cb && v->cb->button_release_callback) v->cb->button_release_callback(v->cb->data, bg_msg_get_arg_int(v->msg, 0), bg_msg_get_arg_int(v->msg, 1), bg_msg_get_arg_int(v->msg, 2), bg_msg_get_arg_int(v->msg, 3)); break; } return 1; } void bg_visualizer_update(bg_visualizer_t * v, const gavl_audio_frame_t * frame) { int keep_going; pthread_mutex_lock(&v->mutex); if(!v->proc) { if(v->ov_plugin) { v->ov_plugin->handle_events(v->ov_handle->priv); } pthread_mutex_unlock(&v->mutex); return; } if(frame) { bg_msg_set_id(v->msg, BG_VIS_MSG_AUDIO_DATA); if(!bg_msg_write_audio_frame(v->msg, &v->audio_format, frame, proc_write_func, v)) { bg_subprocess_close(v->proc); v->proc = NULL; bg_log(BG_LOG_ERROR, LOG_DOMAIN, "Visualization process crashed, restart to try again"); } bg_msg_free(v->msg); } if(v->ov_plugin) { v->ov_plugin->handle_events(v->ov_handle->priv); } /* Handle messages from slave */ bg_msg_set_id(v->msg, BG_VIS_MSG_TELL); write_message(v); bg_msg_free(v->msg); keep_going = 1; while(keep_going) { read_message(v); if(!handle_slave_message(v)) keep_going = 0; bg_msg_free(v->msg); } pthread_mutex_unlock(&v->mutex); } void bg_visualizer_close(bg_visualizer_t * v) { pthread_mutex_lock(&v->mutex); if(!v->proc) { pthread_mutex_unlock(&v->mutex); return; } /* Stop process */ bg_msg_set_id(v->msg, BG_VIS_MSG_QUIT); write_message(v); bg_subprocess_close(v->proc); v->proc = NULL; /* Restore signal mask */ pthread_sigmask(SIG_SETMASK, &v->oldset, NULL); pthread_mutex_unlock(&v->mutex); } int bg_visualizer_need_restart(bg_visualizer_t * v) { return v->proc && v->changed; } void bg_visualizer_set_callbacks(bg_visualizer_t* v, bg_ov_callbacks_t * cb) { v->cb = cb; } gmerlin-1.2.0~dfsg/lib/pluginregistry.c0000644000175000017500000026034611764363410020112 0ustar alessioalessio/***************************************************************** * gmerlin - a general purpose multimedia framework and applications * * Copyright (c) 2001 - 2011 Members of the Gmerlin project * gmerlin-general@lists.sourceforge.net * http://gmerlin.sourceforge.net * * 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 of the License, 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 this program. If not, see . * *****************************************************************/ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #ifdef HAVE_LV #include #endif #define LOG_DOMAIN "pluginregistry" static struct { const char * name; bg_plugin_info_t * (*get_info)(bg_plugin_registry_t * plugin_reg); const bg_plugin_common_t* (*get_plugin)(); void * (*create)(bg_plugin_registry_t * plugin_reg); } meta_plugins[] = { { bg_singlepic_stills_input_name, bg_singlepic_stills_input_info, bg_singlepic_stills_input_get, bg_singlepic_stills_input_create, }, { bg_singlepic_input_name, bg_singlepic_input_info, bg_singlepic_input_get, bg_singlepic_input_create, }, { bg_singlepic_encoder_name, bg_singlepic_encoder_info, bg_singlepic_encoder_get, bg_singlepic_encoder_create, }, { bg_audiofiledevice_name, bg_audiofiledevice_info, bg_audiofiledevice_get, bg_audiofiledevice_create, }, { bg_ovl2text_name, bg_ovl2text_info, bg_ovl2text_get, bg_ovl2text_create, }, { /* End */ } }; struct bg_plugin_registry_s { bg_plugin_info_t * entries; bg_cfg_section_t * config_section; #if 0 /* Plugins generated by the core (from other plugins) */ bg_plugin_info_t * singlepic_input; bg_plugin_info_t * singlepic_stills_input; bg_plugin_info_t * singlepic_encoder; bg_plugin_info_t * audiofile_recorder; #endif }; void bg_plugin_info_destroy(bg_plugin_info_t * info) { if(info->gettext_domain) free(info->gettext_domain); if(info->gettext_directory) free(info->gettext_directory); if(info->name) free(info->name); if(info->long_name) free(info->long_name); if(info->description) free(info->description); if(info->mimetypes) free(info->mimetypes); if(info->extensions) free(info->extensions); if(info->protocols) free(info->protocols); if(info->module_filename) free(info->module_filename); if(info->devices) bg_device_info_destroy(info->devices); if(info->cmp_name) free(info->cmp_name); if(info->parameters) bg_parameter_info_destroy_array(info->parameters); if(info->audio_parameters) bg_parameter_info_destroy_array(info->audio_parameters); if(info->video_parameters) bg_parameter_info_destroy_array(info->video_parameters); if(info->subtitle_text_parameters) bg_parameter_info_destroy_array(info->subtitle_text_parameters); if(info->subtitle_overlay_parameters) bg_parameter_info_destroy_array(info->subtitle_overlay_parameters); free(info); } static void free_info_list(bg_plugin_info_t * entries) { bg_plugin_info_t * info; info = entries; while(info) { entries = info->next; bg_plugin_info_destroy(info); info = entries; } } static void make_cmp_name(bg_plugin_info_t * i) { char * tmp_string; int len; bg_bindtextdomain(i->gettext_domain, i->gettext_directory); tmp_string = bg_utf8_to_system(TRD(i->long_name, i->gettext_domain), -1); len = strxfrm(NULL, tmp_string, 0); i->cmp_name = malloc(len+1); strxfrm(i->cmp_name, tmp_string, len+1); free(tmp_string); } static int compare_swap(bg_plugin_info_t * i1, bg_plugin_info_t * i2) { if((i1->flags & BG_PLUGIN_FILTER_1) && (i2->flags & BG_PLUGIN_FILTER_1)) { if(!i1->cmp_name) { make_cmp_name(i1); } if(!i2->cmp_name) { make_cmp_name(i2); } return strcmp(i1->cmp_name, i2->cmp_name) > 0; } else if((!(i1->flags & BG_PLUGIN_FILTER_1)) && (!(i2->flags & BG_PLUGIN_FILTER_1))) { return i1->priority < i2->priority; } else if((!(i1->flags & BG_PLUGIN_FILTER_1)) && (i2->flags & BG_PLUGIN_FILTER_1)) return 1; return 0; } static bg_plugin_info_t * sort_by_priority(bg_plugin_info_t * list) { int i, j; bg_plugin_info_t * info; bg_plugin_info_t ** arr; int num_plugins = 0; int keep_going; /* Count plugins */ info = list; while(info) { num_plugins++; info = info->next; } /* Allocate array */ arr = malloc(num_plugins * sizeof(*arr)); info = list; for(i = 0; i < num_plugins; i++) { arr[i] = info; info = info->next; } /* Bubblesort */ for(i = 0; i < num_plugins - 1; i++) { keep_going = 0; for(j = num_plugins-1; j > i; j--) { if(compare_swap(arr[j-1], arr[j])) { info = arr[j]; arr[j] = arr[j-1]; arr[j-1] = info; keep_going = 1; } } if(!keep_going) break; } /* Rechain */ for(i = 0; i < num_plugins-1; i++) arr[i]->next = arr[i+1]; if(num_plugins>0) arr[num_plugins-1]->next = NULL; list = arr[0]; /* Free array */ free(arr); return list; } static bg_plugin_info_t * find_by_dll(bg_plugin_info_t * info, const char * filename) { while(info) { if(info->module_filename && !strcmp(info->module_filename, filename)) return info; info = info->next; } return NULL; } static bg_plugin_info_t * find_by_name(bg_plugin_info_t * info, const char * name) { while(info) { if(!strcmp(info->name, name)) return info; info = info->next; } return NULL; } const bg_plugin_info_t * bg_plugin_find_by_name(bg_plugin_registry_t * reg, const char * name) { return find_by_name(reg->entries, name); } const bg_plugin_info_t * bg_plugin_find_by_protocol(bg_plugin_registry_t * reg, const char * protocol) { const bg_plugin_info_t * info = reg->entries; while(info) { if(bg_string_match(protocol, info->protocols)) return info; info = info->next; } return NULL; } const bg_plugin_info_t * bg_plugin_find_by_filename(bg_plugin_registry_t * reg, const char * filename, int typemask) { char * extension; bg_plugin_info_t * info, *ret = NULL; int max_priority = BG_PLUGIN_PRIORITY_MIN - 1; if(!filename) return NULL; info = reg->entries; extension = strrchr(filename, '.'); if(!extension) { return NULL; } extension++; while(info) { if(!(info->type & typemask) || !(info->flags & BG_PLUGIN_FILE) || !info->extensions) { info = info->next; continue; } if(bg_string_match(extension, info->extensions)) { if(max_priority < info->priority) { max_priority = info->priority; ret = info; } // return info; } info = info->next; } return ret; } static bg_plugin_info_t * remove_from_list(bg_plugin_info_t * list, bg_plugin_info_t * info) { bg_plugin_info_t * before; if(info == list) { list = list->next; info->next = NULL; return list; } before = list; while(before->next != info) before = before->next; before->next = info->next; info->next = NULL; return list; } static bg_plugin_info_t * remove_duplicate(bg_plugin_info_t * list) { bg_plugin_info_t * info_1, * info_2, * next; int del = 0; info_1 = list; while(info_1) { /* Check if info_1 is already in the list */ info_2 = list; del = 0; while(info_2 != info_1) { if(info_1->name && info_2->name && !strcmp(info_1->name, info_2->name)) { next = info_1->next; list = remove_from_list(list, info_1); info_1 = next; del = 1; break; } else info_2 = info_2->next; } if(!del) info_1 = info_1->next; } return list; } static bg_plugin_info_t * append_to_list(bg_plugin_info_t * list, bg_plugin_info_t * info) { bg_plugin_info_t * end; if(!list) return info; end = list; while(end->next) end = end->next; end->next = info; return list; } static int check_plugin_version(void * handle) { int (*get_plugin_api_version)(); get_plugin_api_version = dlsym(handle, "get_plugin_api_version"); if(!get_plugin_api_version) return 0; if(get_plugin_api_version() != BG_PLUGIN_API_VERSION) return 0; return 1; } static void set_preset_path(bg_parameter_info_t * info, const char * prefix) { // int i; if(info->type == BG_PARAMETER_SECTION) info->flags |= BG_PARAMETER_GLOBAL_PRESET; info->preset_path = bg_strdup(info->preset_path, prefix); } bg_plugin_info_t * bg_plugin_info_create(const bg_plugin_common_t * plugin) { bg_plugin_info_t * new_info; new_info = calloc(1, sizeof(*new_info)); new_info->name = bg_strdup(new_info->name, plugin->name); new_info->long_name = bg_strdup(new_info->long_name, plugin->long_name); new_info->description = bg_strdup(new_info->description, plugin->description); new_info->gettext_domain = bg_strdup(new_info->gettext_domain, plugin->gettext_domain); new_info->gettext_directory = bg_strdup(new_info->gettext_directory, plugin->gettext_directory); new_info->type = plugin->type; new_info->flags = plugin->flags; new_info->priority = plugin->priority; if(plugin->type & (BG_PLUGIN_ENCODER_AUDIO| BG_PLUGIN_ENCODER_VIDEO| BG_PLUGIN_ENCODER_SUBTITLE_TEXT | BG_PLUGIN_ENCODER_SUBTITLE_OVERLAY | BG_PLUGIN_ENCODER )) { bg_encoder_plugin_t * encoder; encoder = (bg_encoder_plugin_t*)plugin; new_info->max_audio_streams = encoder->max_audio_streams; new_info->max_video_streams = encoder->max_video_streams; new_info->max_subtitle_text_streams = encoder->max_subtitle_text_streams; new_info->max_subtitle_overlay_streams = encoder->max_subtitle_overlay_streams; } return new_info; } static bg_plugin_info_t * plugin_info_create(const bg_plugin_common_t * plugin, void * plugin_priv, const char * module_filename) { char * prefix; bg_plugin_info_t * new_info; const bg_parameter_info_t * parameter_info; new_info = bg_plugin_info_create(plugin); new_info->module_filename = bg_strdup(new_info->module_filename, module_filename); if(plugin->get_parameters) { parameter_info = plugin->get_parameters(plugin_priv); new_info->parameters = bg_parameter_info_copy_array(parameter_info); if(new_info->parameters) { prefix = bg_sprintf("plugins/%s", new_info->name); set_preset_path(new_info->parameters, prefix); free(prefix); } } if(plugin->type & (BG_PLUGIN_ENCODER_AUDIO| BG_PLUGIN_ENCODER_VIDEO| BG_PLUGIN_ENCODER_SUBTITLE_TEXT | BG_PLUGIN_ENCODER_SUBTITLE_OVERLAY | BG_PLUGIN_ENCODER )) { bg_encoder_plugin_t * encoder; encoder = (bg_encoder_plugin_t*)plugin; if(encoder->get_audio_parameters) { parameter_info = encoder->get_audio_parameters(plugin_priv); new_info->audio_parameters = bg_parameter_info_copy_array(parameter_info); if(new_info->audio_parameters) { prefix = bg_sprintf("plugins/%s/audio", new_info->name); set_preset_path(new_info->audio_parameters, prefix); free(prefix); } } if(encoder->get_video_parameters) { parameter_info = encoder->get_video_parameters(plugin_priv); new_info->video_parameters = bg_parameter_info_copy_array(parameter_info); if(new_info->video_parameters) { prefix = bg_sprintf("plugins/%s/video", new_info->name); set_preset_path(new_info->video_parameters, prefix); free(prefix); } } if(encoder->get_subtitle_text_parameters) { parameter_info = encoder->get_subtitle_text_parameters(plugin_priv); new_info->subtitle_text_parameters = bg_parameter_info_copy_array(parameter_info); if(new_info->subtitle_text_parameters) { prefix = bg_sprintf("plugins/%s/subtitle_text", new_info->name); set_preset_path(new_info->subtitle_text_parameters, prefix); free(prefix); } } if(encoder->get_subtitle_overlay_parameters) { parameter_info = encoder->get_subtitle_overlay_parameters(plugin_priv); new_info->subtitle_overlay_parameters = bg_parameter_info_copy_array(parameter_info); if(new_info->subtitle_overlay_parameters) { prefix = bg_sprintf("plugins/%s/subtitle_overlay", new_info->name); set_preset_path(new_info->subtitle_overlay_parameters, prefix); free(prefix); } } } if(plugin->type & BG_PLUGIN_INPUT) { bg_input_plugin_t * input; input = (bg_input_plugin_t*)plugin; if(input->get_mimetypes) new_info->mimetypes = bg_strdup(new_info->mimetypes, input->get_mimetypes(plugin_priv)); if(input->get_extensions) new_info->extensions = bg_strdup(new_info->extensions, input->get_extensions(plugin_priv)); if(input->get_protocols) new_info->protocols = bg_strdup(new_info->protocols, input->get_protocols(plugin_priv)); } if(plugin->type & BG_PLUGIN_IMAGE_READER) { bg_image_reader_plugin_t * ir; ir = (bg_image_reader_plugin_t*)plugin; new_info->extensions = bg_strdup(new_info->extensions, ir->extensions); } if(plugin->type & BG_PLUGIN_IMAGE_WRITER) { bg_image_writer_plugin_t * iw; iw = (bg_image_writer_plugin_t*)plugin; new_info->extensions = bg_strdup(new_info->extensions, iw->extensions); } if(plugin->find_devices) new_info->devices = plugin->find_devices(); return new_info; } static bg_plugin_info_t * get_info(void * test_module, const char * filename, const bg_plugin_registry_options_t * opt) { bg_plugin_info_t * new_info; bg_plugin_common_t * plugin; void * plugin_priv; if(!check_plugin_version(test_module)) { bg_log(BG_LOG_ERROR, LOG_DOMAIN, "Plugin %s has no or wrong version", filename); return NULL; } plugin = (bg_plugin_common_t*)(dlsym(test_module, "the_plugin")); if(!plugin) { bg_log(BG_LOG_ERROR, LOG_DOMAIN, "No symbol the_plugin in %s", filename); return NULL; } if(!plugin->priority) bg_log(BG_LOG_WARNING, LOG_DOMAIN, "Plugin %s has zero priority", plugin->name); if(opt->blacklist) { int i = 0; while(opt->blacklist[i]) { if(!strcmp(plugin->name, opt->blacklist[i])) { bg_log(BG_LOG_INFO, LOG_DOMAIN, "Not loading %s (blacklisted)", plugin->name); return NULL; } i++; } } /* Get parameters */ plugin_priv = plugin->create(); new_info = plugin_info_create(plugin, plugin_priv, filename); plugin->destroy(plugin_priv); return new_info; } static bg_plugin_info_t * scan_directory_internal(const char * directory, bg_plugin_info_t ** _file_info, int * changed, bg_cfg_section_t * cfg_section, bg_plugin_api_t api, const bg_plugin_registry_options_t * opt) { bg_plugin_info_t * ret; DIR * dir; struct dirent * entry; char filename[FILENAME_MAX]; struct stat st; char * pos; void * test_module; bg_plugin_info_t * file_info; bg_plugin_info_t * new_info; bg_plugin_info_t * tmp_info; bg_cfg_section_t * plugin_section; bg_cfg_section_t * stream_section; if(_file_info) file_info = *_file_info; else file_info = NULL; ret = NULL; dir = opendir(directory); if(!dir) return NULL; while((entry = readdir(dir))) { /* Check for the filename */ pos = strrchr(entry->d_name, '.'); if(!pos) continue; if(strcmp(pos, ".so")) continue; sprintf(filename, "%s/%s", directory, entry->d_name); if(stat(filename, &st)) continue; /* Check if the plugin is already in the registry */ new_info = find_by_dll(file_info, filename); if(new_info) { if((st.st_mtime == new_info->module_time) && (bg_cfg_section_has_subsection(cfg_section, new_info->name))) { file_info = remove_from_list(file_info, new_info); ret = append_to_list(ret, new_info); /* Remove other plugins as well */ while((new_info = find_by_dll(file_info, filename))) { file_info = remove_from_list(file_info, new_info); ret = append_to_list(ret, new_info); } continue; } } if(!(*changed)) { *changed = 1; closedir(dir); if(_file_info) *_file_info = file_info; return ret; } /* Open the DLL and see what's inside */ test_module = dlopen(filename, RTLD_NOW); if(!test_module) { bg_log(BG_LOG_ERROR, LOG_DOMAIN, "dlopen failed for %s: %s", filename, dlerror()); continue; } switch(api) { case BG_PLUGIN_API_GMERLIN: new_info = get_info(test_module, filename, opt); break; case BG_PLUGIN_API_LADSPA: new_info = bg_ladspa_get_info(test_module, filename); break; case BG_PLUGIN_API_FREI0R: new_info = bg_frei0r_get_info(test_module, filename); break; #ifdef HAVE_LV case BG_PLUGIN_API_LV: new_info = bg_lv_get_info(filename); break; #endif } tmp_info = new_info; while(tmp_info) { tmp_info->module_time = st.st_mtime; /* Create parameter entries in the registry */ plugin_section = bg_cfg_section_find_subsection(cfg_section, tmp_info->name); if(tmp_info->parameters) { bg_cfg_section_create_items(plugin_section, tmp_info->parameters); } if(tmp_info->audio_parameters) { stream_section = bg_cfg_section_find_subsection(plugin_section, "$audio"); bg_cfg_section_create_items(stream_section, tmp_info->audio_parameters); } if(tmp_info->video_parameters) { stream_section = bg_cfg_section_find_subsection(plugin_section, "$video"); bg_cfg_section_create_items(stream_section, tmp_info->video_parameters); } if(tmp_info->subtitle_text_parameters) { stream_section = bg_cfg_section_find_subsection(plugin_section, "$subtitle_text"); bg_cfg_section_create_items(stream_section, tmp_info->subtitle_text_parameters); } if(tmp_info->subtitle_overlay_parameters) { stream_section = bg_cfg_section_find_subsection(plugin_section, "$subtitle_overlay"); bg_cfg_section_create_items(stream_section, tmp_info->subtitle_overlay_parameters); } tmp_info = tmp_info->next; } dlclose(test_module); ret = append_to_list(ret, new_info); } closedir(dir); if(_file_info) *_file_info = file_info; return ret; } static bg_plugin_info_t * scan_directory(const char * directory, bg_plugin_info_t ** _file_info, bg_cfg_section_t * cfg_section, bg_plugin_api_t api, const bg_plugin_registry_options_t * opt) { int changed = 0; bg_plugin_info_t * file_info; bg_plugin_info_t * file_info_next; char * tmp_string, *pos; bg_plugin_info_t * ret; ret = scan_directory_internal(directory, _file_info, &changed, cfg_section, api, opt); /* Check if there are entries from the file info left */ file_info = *_file_info; while(file_info) { tmp_string = bg_strdup(NULL, file_info->module_filename); pos = strrchr(tmp_string, '/'); if(pos) *pos = '\0'; if(!strcmp(tmp_string, directory)) { file_info_next = file_info->next; *_file_info = remove_from_list(*_file_info, file_info); bg_plugin_info_destroy(file_info); file_info = file_info_next; changed = 1; } else file_info = file_info->next; free(tmp_string); } if(!changed) return ret; free_info_list(ret); ret = scan_directory_internal(directory, _file_info, &changed, cfg_section, api, opt); return ret; } static bg_plugin_info_t * scan_multi(const char * path, bg_plugin_info_t ** _file_info, bg_cfg_section_t * section, bg_plugin_api_t api, const bg_plugin_registry_options_t * opt) { char ** paths; char ** real_paths; int num; bg_plugin_info_t * ret = NULL; bg_plugin_info_t * tmp_info; int do_scan; int i, j; paths = bg_strbreak(path, ':'); if(!paths) return ret; num = 0; i = 0; while(paths[i++]) num++; real_paths = calloc(num, sizeof(*real_paths)); for(i = 0; i < num; i++) real_paths[i] = bg_canonical_filename(paths[i]); for(i = 0; i < num; i++) { if(!real_paths[i]) continue; do_scan = 1; for(j = 0; j < i; j++) { if(real_paths[j] && !strcmp(real_paths[j], real_paths[i])) { do_scan = 0; /* Path already scanned */ break; } } if(do_scan) { tmp_info = scan_directory(real_paths[i], _file_info, section, api, opt); if(tmp_info) ret = append_to_list(ret, tmp_info); } } bg_strbreak_free(paths); for(i = 0; i < num; i++) { if(real_paths[i]) free(real_paths[i]); } free(real_paths); return ret; } bg_plugin_registry_t * bg_plugin_registry_create(bg_cfg_section_t * section) { bg_plugin_registry_options_t opt; memset(&opt, 0, sizeof(opt)); return bg_plugin_registry_create_with_options(section, &opt); } bg_plugin_registry_t * bg_plugin_registry_create_with_options(bg_cfg_section_t * section, const bg_plugin_registry_options_t * opt) { int i; bg_plugin_registry_t * ret; bg_plugin_info_t * file_info; bg_plugin_info_t * tmp_info; bg_plugin_info_t * tmp_info_next; char * filename; char * env; char * path; ret = calloc(1, sizeof(*ret)); ret->config_section = section; /* Load registry file */ file_info = NULL; filename = bg_search_file_read("", "plugins.xml"); if(filename) { file_info = bg_plugin_registry_load(filename); free(filename); } /* Native plugins */ env = getenv("GMERLIN_PLUGIN_PATH"); if(env) path = bg_sprintf("%s:%s", env, PLUGIN_DIR); else path = bg_sprintf("%s", PLUGIN_DIR); tmp_info = scan_multi(path, &file_info, section, BG_PLUGIN_API_GMERLIN, opt); if(tmp_info) ret->entries = append_to_list(ret->entries, tmp_info); free(path); /* Ladspa plugins */ env = getenv("LADSPA_PATH"); if(env) path = bg_sprintf("%s:/usr/lib64/ladspa:/usr/local/lib64/ladspa:/usr/lib/ladspa:/usr/local/lib/ladspa", env); else path = bg_sprintf("/usr/lib64/ladspa:/usr/local/lib64/ladspa:/usr/lib/ladspa:/usr/local/lib/ladspa"); tmp_info = scan_multi(path, &file_info, section, BG_PLUGIN_API_LADSPA, opt); if(tmp_info) ret->entries = append_to_list(ret->entries, tmp_info); free(path); /* Frei0r */ tmp_info = scan_multi("/usr/lib64/frei0r-1:/usr/local/lib64/frei0r-1:/usr/lib/frei0r-1:/usr/local/lib/frei0r-1", &file_info, section, BG_PLUGIN_API_FREI0R, opt); if(tmp_info) ret->entries = append_to_list(ret->entries, tmp_info); #ifdef HAVE_LV tmp_info = scan_directory(LV_PLUGIN_DIR, &file_info, section, BG_PLUGIN_API_LV, opt); if(tmp_info) ret->entries = append_to_list(ret->entries, tmp_info); #endif /* Now we have all external plugins, time to create the meta plugins */ i = 0; while(meta_plugins[i].name) { tmp_info = meta_plugins[i].get_info(ret); if(tmp_info) ret->entries = append_to_list(ret->entries, tmp_info); i++; } tmp_info = bg_edldec_get_info(); if(tmp_info) ret->entries = append_to_list(ret->entries, tmp_info); /* Sort */ ret->entries = sort_by_priority(ret->entries); if(!opt->dont_save) bg_plugin_registry_save(ret->entries); /* Remove duplicate external plugins */ ret->entries = remove_duplicate(ret->entries); /* Kick out unsupported plugins */ tmp_info = ret->entries; while(tmp_info) { if(tmp_info->flags & BG_PLUGIN_UNSUPPORTED) { tmp_info_next = tmp_info->next; ret->entries = remove_from_list(ret->entries, tmp_info); bg_plugin_info_destroy(tmp_info); tmp_info = tmp_info_next; } else tmp_info = tmp_info->next; } #if 0 /* Shouldn't be neccesary if the above code is bugfree */ /* Kick out eventually remaining infos from the file */ tmp_info = file_info; while(tmp_info) { tmp_info_next = tmp_info->next; bg_plugin_info_destroy(tmp_info); tmp_info = tmp_info_next; } #endif return ret; } void bg_plugin_registry_destroy(bg_plugin_registry_t * reg) { bg_plugin_info_t * info; info = reg->entries; while(info) { reg->entries = info->next; bg_plugin_info_destroy(info); info = reg->entries; } free(reg); } static bg_plugin_info_t * find_by_index(bg_plugin_info_t * info, int index, uint32_t type_mask, uint32_t flag_mask) { int i; bg_plugin_info_t * test_info; i = 0; test_info = info; while(test_info) { if((test_info->type & type_mask) && ((flag_mask == BG_PLUGIN_ALL) || (!test_info->flags && !flag_mask) || (test_info->flags & flag_mask))) { if(i == index) return test_info; i++; } test_info = test_info->next; } return NULL; } static bg_plugin_info_t * find_by_priority(bg_plugin_info_t * info, uint32_t type_mask, uint32_t flag_mask) { bg_plugin_info_t * test_info, *ret = NULL; int priority_max = BG_PLUGIN_PRIORITY_MIN - 1; test_info = info; while(test_info) { if((test_info->type & type_mask) && ((flag_mask == BG_PLUGIN_ALL) || (test_info->flags & flag_mask) || (!test_info->flags && !flag_mask))) { if(priority_max < test_info->priority) { priority_max = test_info->priority; ret = test_info; } } test_info = test_info->next; } return ret; } const bg_plugin_info_t * bg_plugin_find_by_index(bg_plugin_registry_t * reg, int index, uint32_t type_mask, uint32_t flag_mask) { return find_by_index(reg->entries, index, type_mask, flag_mask); } int bg_plugin_registry_get_num_plugins(bg_plugin_registry_t * reg, uint32_t type_mask, uint32_t flag_mask) { bg_plugin_info_t * info; int ret = 0; info = reg->entries; while(info) { if((info->type & type_mask) && ((!info->flags && !flag_mask) || (info->flags & flag_mask))) ret++; info = info->next; } return ret; } void bg_plugin_registry_scan_devices(bg_plugin_registry_t * plugin_reg, uint32_t type_mask, uint32_t flag_mask) { int i; bg_plugin_info_t * info; bg_plugin_common_t * plugin; void * priv; void * module; const bg_parameter_info_t * parameters; int num = bg_plugin_registry_get_num_plugins(plugin_reg, type_mask, flag_mask); for(i = 0; i < num; i++) { info = find_by_index(plugin_reg->entries, i, type_mask, flag_mask); if(!(info->flags & BG_PLUGIN_DEVPARAM)) continue; module = dlopen(info->module_filename, RTLD_NOW); plugin = (bg_plugin_common_t*)(dlsym(module, "the_plugin")); if(!plugin) { dlclose(module); continue; } priv = plugin->create(); parameters = plugin->get_parameters(priv); if(info->parameters) bg_parameter_info_destroy_array(info->parameters); info->parameters = bg_parameter_info_copy_array(parameters); dlclose(module); } } void bg_plugin_registry_set_extensions(bg_plugin_registry_t * reg, const char * plugin_name, const char * extensions) { bg_plugin_info_t * info; info = find_by_name(reg->entries, plugin_name); if(!info) return; if(!(info->flags & BG_PLUGIN_FILE)) return; info->extensions = bg_strdup(info->extensions, extensions); bg_plugin_registry_save(reg->entries); } void bg_plugin_registry_set_protocols(bg_plugin_registry_t * reg, const char * plugin_name, const char * protocols) { bg_plugin_info_t * info; info = find_by_name(reg->entries, plugin_name); if(!info) return; if(!(info->flags & BG_PLUGIN_URL)) return; info->protocols = bg_strdup(info->protocols, protocols); bg_plugin_registry_save(reg->entries); } void bg_plugin_registry_set_priority(bg_plugin_registry_t * reg, const char * plugin_name, int priority) { bg_plugin_info_t * info; info = find_by_name(reg->entries, plugin_name); if(!info) return; info->priority = priority; reg->entries = sort_by_priority(reg->entries); bg_plugin_registry_save(reg->entries); } bg_cfg_section_t * bg_plugin_registry_get_section(bg_plugin_registry_t * reg, const char * plugin_name) { return bg_cfg_section_find_subsection(reg->config_section, plugin_name); } static const struct { bg_plugin_type_t type; uint32_t flag_mask; char * key; } default_keys[] = { { BG_PLUGIN_OUTPUT_AUDIO, BG_PLUGIN_PLAYBACK, "audio_output" }, { BG_PLUGIN_OUTPUT_VIDEO, BG_PLUGIN_PLAYBACK, "video_output" }, { BG_PLUGIN_RECORDER_AUDIO, BG_PLUGIN_RECORDER, "audio_recorder" }, { BG_PLUGIN_RECORDER_VIDEO, BG_PLUGIN_RECORDER, "video_recorder" }, { BG_PLUGIN_ENCODER_AUDIO, BG_PLUGIN_FILE, "audio_encoder" }, { BG_PLUGIN_ENCODER_VIDEO|BG_PLUGIN_ENCODER, BG_PLUGIN_FILE, "video_encoder" }, { BG_PLUGIN_ENCODER_SUBTITLE_TEXT, BG_PLUGIN_FILE, "subtitle_text_encoder" }, { BG_PLUGIN_ENCODER_SUBTITLE_OVERLAY, BG_PLUGIN_FILE, "subtitle_overlay_encoder" }, { BG_PLUGIN_IMAGE_WRITER, BG_PLUGIN_FILE, "image_writer" }, { BG_PLUGIN_ENCODER_PP, BG_PLUGIN_PP, "encoder_pp" }, { BG_PLUGIN_VISUALIZATION, BG_PLUGIN_VISUALIZE_FRAME, "visualization_frame" }, { BG_PLUGIN_VISUALIZATION, BG_PLUGIN_VISUALIZE_GL, "visualization_gl" }, { BG_PLUGIN_VISUALIZATION, BG_PLUGIN_VISUALIZE_FRAME | BG_PLUGIN_VISUALIZE_GL, "visualization" }, { BG_PLUGIN_NONE, 0, (char*)NULL }, }; static const char * get_default_key(bg_plugin_type_t type, uint32_t flag_mask) { int i = 0; /* Try exact match */ while(default_keys[i].key) { if((type & default_keys[i].type) && (flag_mask == default_keys[i].flag_mask)) return default_keys[i].key; i++; } /* Try approximate match */ i = 0; while(default_keys[i].key) { if((type & default_keys[i].type) && (flag_mask & default_keys[i].flag_mask)) return default_keys[i].key; i++; } return NULL; } void bg_plugin_registry_set_default(bg_plugin_registry_t * r, bg_plugin_type_t type, uint32_t flag_mask, const char * name) { const char * key; key = get_default_key(type, flag_mask); if(key) bg_cfg_section_set_parameter_string(r->config_section, key, name); } const bg_plugin_info_t * bg_plugin_registry_get_default(bg_plugin_registry_t * r, bg_plugin_type_t type, uint32_t flag_mask) { const char * key; const char * name = NULL; const bg_plugin_info_t * ret; key = get_default_key(type, flag_mask); if(key) bg_cfg_section_get_parameter_string(r->config_section, key, &name); if(!name) { return find_by_priority(r->entries, type, flag_mask); } else { ret = bg_plugin_find_by_name(r, name); if(!ret) ret = find_by_priority(r->entries, type, flag_mask); return ret; } } void bg_plugin_ref(bg_plugin_handle_t * h) { bg_plugin_lock(h); h->refcount++; bg_log(BG_LOG_DEBUG, LOG_DOMAIN, "bg_plugin_ref %s: %d", h->info->name, h->refcount); bg_plugin_unlock(h); } static void unload_plugin(bg_plugin_handle_t * h) { bg_cfg_section_t * section; if(h->plugin->get_parameter && h->plugin_reg) { section = bg_plugin_registry_get_section(h->plugin_reg, h->info->name); bg_cfg_section_get(section, h->plugin->get_parameters(h->priv), h->plugin->get_parameter, h->priv); } if(h->info) { switch(h->info->api) { case BG_PLUGIN_API_GMERLIN: if(h->priv && h->plugin->destroy) h->plugin->destroy(h->priv); break; case BG_PLUGIN_API_LADSPA: bg_ladspa_unload(h); break; case BG_PLUGIN_API_FREI0R: bg_frei0r_unload(h); break; #ifdef HAVE_LV case BG_PLUGIN_API_LV: bg_lv_unload(h); break; #endif } } else if(h->priv && h->plugin->destroy) h->plugin->destroy(h->priv); if(h->location) free(h->location); #if 1 // Some few libs (e.g. the OpenGL lib shipped with NVidia) // seem to install pthread cleanup handlers, which point to library // functions. dlclosing libraries causes programs to crash // mysteriously when the thread lives longer than the plugin. // // So we leave them open and // rely on dlopen() never loading the same lib twice if(h->dll_handle) dlclose(h->dll_handle); #endif if(h->edl) bg_edl_destroy(h->edl); pthread_mutex_destroy(&h->mutex); free(h); } void bg_plugin_unref_nolock(bg_plugin_handle_t * h) { h->refcount--; bg_log(BG_LOG_DEBUG, LOG_DOMAIN, "bg_plugin_unref_nolock %s: %d", h->plugin->name, h->refcount); if(!h->refcount) unload_plugin(h); } void bg_plugin_unref(bg_plugin_handle_t * h) { int refcount; bg_plugin_lock(h); h->refcount--; bg_log(BG_LOG_DEBUG, LOG_DOMAIN, "bg_plugin_unref %s: %d", h->plugin->name, h->refcount); refcount = h->refcount; bg_plugin_unlock(h); if(!refcount) unload_plugin(h); } gavl_video_frame_t * bg_plugin_registry_load_image(bg_plugin_registry_t * r, const char * filename, gavl_video_format_t * format, gavl_metadata_t * m) { const bg_plugin_info_t * info; bg_image_reader_plugin_t * ir; bg_plugin_handle_t * handle = NULL; gavl_video_frame_t * ret = NULL; info = bg_plugin_find_by_filename(r, filename, BG_PLUGIN_IMAGE_READER); if(!info) { bg_log(BG_LOG_ERROR, LOG_DOMAIN, "No plugin found for image %s", filename); goto fail; } handle = bg_plugin_load(r, info); if(!handle) goto fail; ir = (bg_image_reader_plugin_t*)(handle->plugin); if(!ir->read_header(handle->priv, filename, format)) goto fail; if(ir->get_metadata && m) { const gavl_metadata_t * m_ret; m_ret = ir->get_metadata(handle->priv); if(m_ret) gavl_metadata_copy(m, m_ret); } ret = gavl_video_frame_create(format); if(!ir->read_image(handle->priv, ret)) goto fail; bg_plugin_unref(handle); return ret; fail: if(ret) gavl_video_frame_destroy(ret); return NULL; } void bg_plugin_registry_save_image(bg_plugin_registry_t * r, const char * filename, gavl_video_frame_t * frame, const gavl_video_format_t * format, const gavl_metadata_t * m) { const bg_plugin_info_t * info; gavl_video_format_t tmp_format; gavl_video_converter_t * cnv; bg_image_writer_plugin_t * iw; bg_plugin_handle_t * handle = NULL; gavl_video_frame_t * tmp_frame = NULL; info = bg_plugin_find_by_filename(r, filename, BG_PLUGIN_IMAGE_WRITER); cnv = gavl_video_converter_create(); if(!info) { bg_log(BG_LOG_ERROR, LOG_DOMAIN, "No plugin found for image %s", filename); goto fail; } handle = bg_plugin_load(r, info); if(!handle) goto fail; iw = (bg_image_writer_plugin_t*)(handle->plugin); gavl_video_format_copy(&tmp_format, format); if(!iw->write_header(handle->priv, filename, &tmp_format, m)) goto fail; if(gavl_video_converter_init(cnv, format, &tmp_format)) { tmp_frame = gavl_video_frame_create(&tmp_format); gavl_video_convert(cnv, frame, tmp_frame); if(!iw->write_image(handle->priv, tmp_frame)) goto fail; } else { if(!iw->write_image(handle->priv, frame)) goto fail; } bg_plugin_unref(handle); fail: if(tmp_frame) gavl_video_frame_destroy(tmp_frame); gavl_video_converter_destroy(cnv); } bg_plugin_handle_t * bg_plugin_handle_create() { bg_plugin_handle_t * ret; ret = calloc(1, sizeof(*ret)); pthread_mutex_init(&ret->mutex, NULL); return ret; } static bg_plugin_handle_t * load_plugin(bg_plugin_registry_t * reg, const bg_plugin_info_t * info) { bg_plugin_handle_t * ret; if(!info) return NULL; ret = bg_plugin_handle_create(); ret->plugin_reg = reg; pthread_mutex_init(&ret->mutex, NULL); if(info->module_filename) { if(info->api != BG_PLUGIN_API_LV) { /* We need all symbols global because some plugins might reference them */ ret->dll_handle = dlopen(info->module_filename, RTLD_NOW | RTLD_GLOBAL); if(!ret->dll_handle) { bg_log(BG_LOG_ERROR, LOG_DOMAIN, "dlopen failed for %s: %s", info->module_filename, dlerror()); goto fail; } } switch(info->api) { case BG_PLUGIN_API_GMERLIN: if(!check_plugin_version(ret->dll_handle)) { bg_log(BG_LOG_ERROR, LOG_DOMAIN, "Plugin %s has no or wrong version", info->module_filename); goto fail; } ret->plugin = dlsym(ret->dll_handle, "the_plugin"); if(!ret->plugin) { bg_log(BG_LOG_ERROR, LOG_DOMAIN, "dlsym failed for %s: %s", info->module_filename, dlerror()); goto fail; } ret->priv = ret->plugin->create(); break; case BG_PLUGIN_API_LADSPA: if(!bg_ladspa_load(ret, info)) goto fail; break; case BG_PLUGIN_API_FREI0R: if(!bg_frei0r_load(ret, info)) goto fail; break; #ifdef HAVE_LV case BG_PLUGIN_API_LV: if(!bg_lv_load(ret, info->name, info->flags, NULL)) goto fail; break; #endif } } else { int i = 0; while(meta_plugins[i].name) { if(!strcmp(meta_plugins[i].name, info->name)) { ret->plugin = meta_plugins[i].get_plugin(); ret->priv = meta_plugins[i].create(reg); break; } i++; } } ret->info = info; bg_plugin_ref(ret); return ret; fail: pthread_mutex_destroy(&ret->mutex); if(ret->dll_handle) dlclose(ret->dll_handle); free(ret); return NULL; } static void apply_parameters(bg_plugin_registry_t * reg, bg_plugin_handle_t * ret) { const bg_parameter_info_t * parameters; bg_cfg_section_t * section; /* Apply saved parameters */ if(ret->plugin->get_parameters) { parameters = ret->plugin->get_parameters(ret->priv); section = bg_plugin_registry_get_section(reg, ret->info->name); bg_cfg_section_apply(section, parameters, ret->plugin->set_parameter, ret->priv); } } bg_plugin_handle_t * bg_plugin_load(bg_plugin_registry_t * reg, const bg_plugin_info_t * info) { bg_plugin_handle_t * ret; ret = load_plugin(reg, info); if(ret) apply_parameters(reg, ret); return ret; } bg_plugin_handle_t * bg_ov_plugin_load(bg_plugin_registry_t * reg, const bg_plugin_info_t * info, const char * window_id) { bg_plugin_handle_t * ret; bg_ov_plugin_t * plugin; if(info->type != BG_PLUGIN_OUTPUT_VIDEO) { bg_log(BG_LOG_ERROR, LOG_DOMAIN, "Invalid plugin type for video output"); return NULL; } #if 0 if(!(info->flags & BG_PLUGIN_EMBED_WINDOW) && window_id) { bg_log(BG_LOG_ERROR, LOG_DOMAIN, "Plugin %s doesn't support embedded windows", info->name); return NULL; } #endif ret = load_plugin(reg, info); if(window_id) { plugin = (bg_ov_plugin_t*)(ret->plugin); if(plugin->set_window) plugin->set_window(ret->priv, window_id); } if(ret) apply_parameters(reg, ret); return ret; } void bg_plugin_lock(bg_plugin_handle_t * h) { pthread_mutex_lock(&h->mutex); } void bg_plugin_unlock(bg_plugin_handle_t * h) { pthread_mutex_unlock(&h->mutex); } void bg_plugin_registry_add_device(bg_plugin_registry_t * reg, const char * plugin_name, const char * device, const char * name) { bg_plugin_info_t * info; info = find_by_name(reg->entries, plugin_name); if(!info) return; info->devices = bg_device_info_append(info->devices, device, name); bg_plugin_registry_save(reg->entries); } void bg_plugin_registry_set_device_name(bg_plugin_registry_t * reg, const char * plugin_name, const char * device, const char * name) { int i; bg_plugin_info_t * info; info = find_by_name(reg->entries, plugin_name); if(!info || !info->devices) return; i = 0; while(info->devices[i].device) { if(!strcmp(info->devices[i].device, device)) { info->devices[i].name = bg_strdup(info->devices[i].name, name); bg_plugin_registry_save(reg->entries); return; } i++; } } static int my_strcmp(const char * str1, const char * str2) { if(!str1 && !str2) return 0; else if(str1 && str2) return strcmp(str1, str2); return 1; } void bg_plugin_registry_remove_device(bg_plugin_registry_t * reg, const char * plugin_name, const char * device, const char * name) { bg_plugin_info_t * info; int index; int num_devices; info = find_by_name(reg->entries, plugin_name); if(!info) return; index = -1; num_devices = 0; while(info->devices[num_devices].device) { if(!my_strcmp(info->devices[num_devices].name, name) && !strcmp(info->devices[num_devices].device, device)) { index = num_devices; } num_devices++; } if(index != -1) memmove(&info->devices[index], &info->devices[index+1], sizeof(*(info->devices)) * (num_devices - index)); bg_plugin_registry_save(reg->entries); } void bg_plugin_registry_find_devices(bg_plugin_registry_t * reg, const char * plugin_name) { bg_plugin_info_t * info; bg_plugin_handle_t * handle; info = find_by_name(reg->entries, plugin_name); if(!info) return; handle = bg_plugin_load(reg, info); bg_device_info_destroy(info->devices); info->devices = NULL; if(!handle || !handle->plugin->find_devices) return; info->devices = handle->plugin->find_devices(); bg_plugin_registry_save(reg->entries); bg_plugin_unref(handle); } char ** bg_plugin_registry_get_plugins(bg_plugin_registry_t*reg, uint32_t type_mask, uint32_t flag_mask) { int num_plugins, i; char ** ret; const bg_plugin_info_t * info; num_plugins = bg_plugin_registry_get_num_plugins(reg, type_mask, flag_mask); ret = calloc(num_plugins + 1, sizeof(char*)); for(i = 0; i < num_plugins; i++) { info = bg_plugin_find_by_index(reg, i, type_mask, flag_mask); ret[i] = bg_strdup(NULL, info->name); } return ret; } void bg_plugin_registry_free_plugins(char ** plugins) { int index = 0; if(!plugins) return; while(plugins[index]) { free(plugins[index]); index++; } free(plugins); } static void load_input_plugin(bg_plugin_registry_t * reg, const bg_plugin_info_t * info, bg_plugin_handle_t ** ret) { if(!(*ret) || !(*ret)->info || strcmp((*ret)->info->name, info->name)) { if(*ret) { bg_plugin_unref(*ret); *ret = NULL; } *ret = bg_plugin_load(reg, info); } } static int input_plugin_load(bg_plugin_registry_t * reg, const char * location, const bg_plugin_info_t * info, bg_plugin_handle_t ** ret, bg_input_callbacks_t * callbacks) { const char * real_location; char * protocol = NULL, * path = NULL; int num_plugins, i; uint32_t flags; bg_input_plugin_t * plugin; int try_and_error = 1; const bg_plugin_info_t * first_plugin = NULL; if(!location) return 0; if(!strncmp(location, "file://", 7)) location += 7; real_location = location; if(!info) /* No plugin given, seek one */ { if(bg_string_is_url(location)) { if(bg_url_split(location, &protocol, NULL, // user, NULL, // password, NULL, // hostname, NULL, // port, &path)) { info = bg_plugin_find_by_protocol(reg, protocol); if(info) { if(info->flags & BG_PLUGIN_REMOVABLE) real_location = path; } } } else if(!strcmp(location, "-")) { info = bg_plugin_find_by_protocol(reg, "stdin"); } else { info = bg_plugin_find_by_filename(reg, real_location, (BG_PLUGIN_INPUT)); } first_plugin = info; } else try_and_error = 0; /* We never try other plugins than the given one */ if(info) { /* Try to load this */ load_input_plugin(reg, info, ret); if(!(*ret)) { bg_log(BG_LOG_ERROR, LOG_DOMAIN, TRS("Loading plugin \"%s\" failed"), info->long_name); return 0; } plugin = (bg_input_plugin_t*)((*ret)->plugin); if(plugin->set_callbacks) plugin->set_callbacks((*ret)->priv, callbacks); if(!plugin->open((*ret)->priv, real_location)) { bg_log(BG_LOG_ERROR, LOG_DOMAIN, TRS("Opening %s with \"%s\" failed"), real_location, info->long_name); } else { if(protocol) free(protocol); if(path) free(path); (*ret)->location = bg_strdup((*ret)->location, real_location); return 1; } } if(protocol) free(protocol); if(path) free(path); if(!try_and_error) return 0; flags = bg_string_is_url(real_location) ? BG_PLUGIN_URL : BG_PLUGIN_FILE; num_plugins = bg_plugin_registry_get_num_plugins(reg, BG_PLUGIN_INPUT, flags); for(i = 0; i < num_plugins; i++) { info = bg_plugin_find_by_index(reg, i, BG_PLUGIN_INPUT, flags); if(info == first_plugin) continue; load_input_plugin(reg, info, ret); if(!*ret) continue; plugin = (bg_input_plugin_t*)((*ret)->plugin); if(!plugin->open((*ret)->priv, real_location)) { bg_log(BG_LOG_ERROR, LOG_DOMAIN, TRS("Opening %s with \"%s\" failed"), location, info->long_name); } else { (*ret)->location = bg_strdup((*ret)->location, real_location); return 1; } } return 0; } int bg_input_plugin_load(bg_plugin_registry_t * reg, const char * location, const bg_plugin_info_t * info, bg_plugin_handle_t ** ret, bg_input_callbacks_t * callbacks, int prefer_edl) { bg_input_plugin_t * plugin; const bg_edl_t * edl_c; bg_edl_t * edl; int num_tracks = 1; if(!input_plugin_load(reg, location, info, ret, callbacks)) return 0; plugin = (bg_input_plugin_t*)((*ret)->plugin); if(plugin->get_num_tracks) num_tracks = plugin->get_num_tracks((*ret)->priv); if(num_tracks && (!plugin->get_edl || !prefer_edl)) return 1; edl_c = plugin->get_edl((*ret)->priv); if(!edl_c) return 1; /* Debug */ // bg_edl_save(edl_c, "test.edl"); /* Load EDL instead */ edl = bg_edl_copy(edl_c); info = bg_plugin_find_by_name(reg, "i_edldec"); if(!bg_input_plugin_load_edl(reg, edl, info, ret, callbacks)) { bg_edl_destroy(edl); return 0; } (*ret)->edl = edl; return 1; } void bg_plugin_registry_set_encode_audio_to_video(bg_plugin_registry_t * reg, int audio_to_video) { bg_cfg_section_set_parameter_int(reg->config_section, "encode_audio_to_video", audio_to_video); } int bg_plugin_registry_get_encode_audio_to_video(bg_plugin_registry_t * reg) { int ret; bg_cfg_section_get_parameter_int(reg->config_section, "encode_audio_to_video", &ret); return ret; } void bg_plugin_registry_set_visualize(bg_plugin_registry_t * reg, int visualize) { bg_cfg_section_set_parameter_int(reg->config_section, "visualize", visualize); } int bg_plugin_registry_get_visualize(bg_plugin_registry_t * reg) { int ret; bg_cfg_section_get_parameter_int(reg->config_section, "visualize", &ret); return ret; } void bg_plugin_registry_set_encode_subtitle_text_to_video(bg_plugin_registry_t * reg, int subtitle_text_to_video) { bg_cfg_section_set_parameter_int(reg->config_section, "encode_subtitle_text_to_video", subtitle_text_to_video); } int bg_plugin_registry_get_encode_subtitle_text_to_video(bg_plugin_registry_t * reg) { int ret; bg_cfg_section_get_parameter_int(reg->config_section, "encode_subtitle_text_to_video", &ret); return ret; } void bg_plugin_registry_set_encode_subtitle_overlay_to_video(bg_plugin_registry_t * reg, int subtitle_overlay_to_video) { bg_cfg_section_set_parameter_int(reg->config_section, "encode_subtitle_overlay_to_video", subtitle_overlay_to_video); } int bg_plugin_registry_get_encode_subtitle_overlay_to_video(bg_plugin_registry_t * reg) { int ret; bg_cfg_section_get_parameter_int(reg->config_section, "encode_subtitle_overlay_to_video", &ret); return ret; } void bg_plugin_registry_set_encode_pp(bg_plugin_registry_t * reg, int use_pp) { bg_cfg_section_set_parameter_int(reg->config_section, "encode_pp", use_pp); } int bg_plugin_registry_get_encode_pp(bg_plugin_registry_t * reg) { int ret; bg_cfg_section_get_parameter_int(reg->config_section, "encode_pp", &ret); return ret; } static const bg_parameter_info_t encoder_section_general[] = { { .name = "$general", .long_name = TRS("General"), .type = BG_PARAMETER_SECTION, // .flags = BG_PARAMETER_OWN_SECTION, }, { } // End }; static const bg_parameter_info_t encoder_section_audio[] = { { .name = "$audio", .long_name = TRS("Audio"), .type = BG_PARAMETER_SECTION, .flags = BG_PARAMETER_OWN_SECTION, }, { } // End }; static const bg_parameter_info_t encoder_section_video[] = { { .name = "$video", .long_name = TRS("Video"), .type = BG_PARAMETER_SECTION, .flags = BG_PARAMETER_OWN_SECTION, }, { } // End }; static const bg_parameter_info_t encoder_section_subtitle_overlay[] = { { .name = "$subtitle_overlay", .long_name = TRS("Overlay subtitles"), .type = BG_PARAMETER_SECTION, .flags = BG_PARAMETER_OWN_SECTION, }, { } // End }; static const bg_parameter_info_t encoder_section_subtitle_text[] = { { .name = "$subtitle_text", .long_name = TRS("Text subtitles"), .type = BG_PARAMETER_SECTION, .flags = BG_PARAMETER_OWN_SECTION, }, { } // End }; static bg_parameter_info_t * create_encoder_parameters(const bg_plugin_info_t * info) { int i = 0; bg_parameter_info_t * ret; char * tmp_string; const bg_parameter_info_t * src[11]; // if(!strcmp(info->name, "e_mpeg")) // fprintf(stderr, "e_mpeg\n"); if(info->audio_parameters || info->video_parameters || info->subtitle_text_parameters || info->subtitle_overlay_parameters) { if(info->parameters) { if(info->parameters[0].type != BG_PARAMETER_SECTION) { src[i] = encoder_section_general; i++; } src[i] = info->parameters; i++; } if(info->audio_parameters) { src[i] = encoder_section_audio; i++; src[i] = info->audio_parameters; i++; } if(info->subtitle_text_parameters) { src[i] = encoder_section_subtitle_text; i++; src[i] = info->subtitle_text_parameters; i++; } if(info->subtitle_overlay_parameters) { src[i] = encoder_section_subtitle_overlay; i++; src[i] = info->subtitle_overlay_parameters; i++; } if(info->video_parameters) { src[i] = encoder_section_video; i++; src[i] = info->video_parameters; i++; } src[i] = NULL; ret = bg_parameter_info_concat_arrays(src); } else ret = bg_parameter_info_copy_array(info->parameters); if(ret) { ret->flags |= BG_PARAMETER_GLOBAL_PRESET; tmp_string = bg_sprintf("plugins/%s", info->name); ret->preset_path = bg_strdup(ret->preset_path, tmp_string); free(tmp_string); } // if(!strcmp(info->name, "e_mpeg")) // bg_parameters_dump(ret, "encoder_parameters"); return ret; } void bg_plugin_registry_set_parameter_info(bg_plugin_registry_t * reg, uint32_t type_mask, uint32_t flag_mask, bg_parameter_info_t * ret) { int num_plugins, i; const bg_plugin_info_t * info; num_plugins = bg_plugin_registry_get_num_plugins(reg, type_mask, flag_mask); ret->multi_names_nc = calloc(num_plugins + 1, sizeof(*ret->multi_names)); ret->multi_labels_nc = calloc(num_plugins + 1, sizeof(*ret->multi_labels)); ret->multi_parameters_nc = calloc(num_plugins + 1, sizeof(*ret->multi_parameters)); ret->multi_descriptions_nc = calloc(num_plugins + 1, sizeof(*ret->multi_descriptions)); bg_parameter_info_set_const_ptrs(ret); for(i = 0; i < num_plugins; i++) { info = bg_plugin_find_by_index(reg, i, type_mask, flag_mask); ret->multi_names_nc[i] = bg_strdup(NULL, info->name); /* First plugin is the default one */ if(!i && (ret->type != BG_PARAMETER_MULTI_CHAIN)) { ret->val_default.val_str = bg_strdup(NULL, info->name); } bg_bindtextdomain(info->gettext_domain, info->gettext_directory); ret->multi_descriptions_nc[i] = bg_strdup(NULL, TRD(info->description, info->gettext_domain)); ret->multi_labels_nc[i] = bg_strdup(NULL, TRD(info->long_name, info->gettext_domain)); if(info->type & (BG_PLUGIN_ENCODER_AUDIO | BG_PLUGIN_ENCODER_VIDEO | BG_PLUGIN_ENCODER_SUBTITLE_TEXT | BG_PLUGIN_ENCODER_SUBTITLE_OVERLAY | BG_PLUGIN_ENCODER)) ret->multi_parameters_nc[i] = create_encoder_parameters(info); else if(info->parameters) { ret->multi_parameters_nc[i] = bg_parameter_info_copy_array(info->parameters); } } } static const bg_parameter_info_t registry_settings_parameter = { .name = "$registry", .long_name = TRS("Registry settings"), .type = BG_PARAMETER_SECTION, }; static const bg_parameter_info_t plugin_settings_parameter = { .name = "$plugin", .long_name = TRS("Plugin settings"), .type = BG_PARAMETER_SECTION, }; static const bg_parameter_info_t extensions_parameter = { .name = "$extensions", .long_name = TRS("Extensions"), .type = BG_PARAMETER_STRING, }; static const bg_parameter_info_t protocols_parameter = { .name = "$protocols", .long_name = TRS("Protocols"), .type = BG_PARAMETER_STRING, }; static const bg_parameter_info_t priority_parameter = { .name = "$priority", .long_name = TRS("Priority"), .type = BG_PARAMETER_INT, .val_min = { .val_i = 1 }, .val_max = { .val_i = 10 }, }; void bg_plugin_registry_set_parameter_info_input(bg_plugin_registry_t * reg, uint32_t type_mask, uint32_t flag_mask, bg_parameter_info_t * ret) { int num_plugins, i; const bg_plugin_info_t * info; int index, index1, num_parameters; char * prefix; num_plugins = bg_plugin_registry_get_num_plugins(reg, type_mask, flag_mask); ret->type = BG_PARAMETER_MULTI_LIST; ret->flags |= BG_PARAMETER_NO_SORT; ret->multi_names_nc = calloc(num_plugins + 1, sizeof(*ret->multi_names)); ret->multi_labels_nc = calloc(num_plugins + 1, sizeof(*ret->multi_labels)); ret->multi_parameters_nc = calloc(num_plugins + 1, sizeof(*ret->multi_parameters)); ret->multi_descriptions_nc = calloc(num_plugins + 1, sizeof(*ret->multi_descriptions)); bg_parameter_info_set_const_ptrs(ret); for(i = 0; i < num_plugins; i++) { info = bg_plugin_find_by_index(reg, i, type_mask, flag_mask); ret->multi_names_nc[i] = bg_strdup(NULL, info->name); /* First plugin is the default one */ if(!i && (ret->type != BG_PARAMETER_MULTI_CHAIN)) { ret->val_default.val_str = bg_strdup(NULL, info->name); } bg_bindtextdomain(info->gettext_domain, info->gettext_directory); ret->multi_descriptions_nc[i] = bg_strdup(NULL, TRD(info->description, info->gettext_domain)); ret->multi_labels_nc[i] = bg_strdup(NULL, TRD(info->long_name, info->gettext_domain)); /* Create parameters: Extensions and protocols are added to the array if necessary */ num_parameters = 1; /* Priority */ if(info->flags & BG_PLUGIN_FILE) num_parameters++; if(info->flags & BG_PLUGIN_URL) num_parameters++; if(info->parameters && (info->parameters[0].type != BG_PARAMETER_SECTION)) num_parameters++; /* Plugin section */ if(info->parameters) num_parameters++; /* Registry */ // prefix = bg_sprintf("%s.", info->name); prefix = NULL; if(info->parameters) { index = 0; while(info->parameters[index].name) { index++; num_parameters++; } } ret->multi_parameters_nc[i] = calloc(num_parameters+1, sizeof(*ret->multi_parameters_nc[i])); index = 0; /* Now, build the parameter array */ if(info->parameters && (info->parameters[0].type != BG_PARAMETER_SECTION)) { bg_parameter_info_copy(&ret->multi_parameters_nc[i][index], &plugin_settings_parameter); index++; } if(info->parameters) { index1 = 0; while(info->parameters[index1].name) { bg_parameter_info_copy(&ret->multi_parameters_nc[i][index], &info->parameters[index1]); index++; index1++; } } if(info->parameters) { bg_parameter_info_copy(&ret->multi_parameters_nc[i][index], ®istry_settings_parameter); index++; } if(info->flags & BG_PLUGIN_FILE) { bg_parameter_info_copy(&ret->multi_parameters_nc[i][index], &extensions_parameter); ret->multi_parameters_nc[i][index].val_default.val_str = bg_strdup(NULL, info->extensions); index++; } if(info->flags & BG_PLUGIN_URL) { bg_parameter_info_copy(&ret->multi_parameters_nc[i][index], &protocols_parameter); ret->multi_parameters_nc[i][index].val_default.val_str = bg_strdup(NULL, info->protocols); index++; } bg_parameter_info_copy(&ret->multi_parameters_nc[i][index], &priority_parameter); ret->multi_parameters_nc[i][index].val_default.val_i = info->priority; index++; } } static int find_parameter_input(bg_plugin_registry_t * plugin_reg, const char * name, const bg_parameter_info_t ** parameter_info, bg_plugin_info_t ** plugin_info, bg_cfg_section_t ** section, const char ** parameter_name) { const char * pos1; const char * pos2; char * plugin_name; int ret = 0; pos1 = strchr(name, '.'); if(!pos1) return 0; pos1++; pos2 = strchr(pos1, '.'); if(!pos2) return 0; plugin_name = bg_strndup(NULL, pos1, pos2); pos2++; *parameter_name = pos2; *plugin_info = find_by_name(plugin_reg->entries, plugin_name); if(!(*plugin_info)) goto fail; if(*pos2 != '$') { *section = bg_cfg_section_find_subsection(plugin_reg->config_section, plugin_name); *parameter_info = bg_parameter_find((*plugin_info)->parameters, pos2); if(!(*parameter_info)) goto fail; } ret = 1; fail: free(plugin_name); return ret; } void bg_plugin_registry_set_parameter_input(void * data, const char * name, const bg_parameter_value_t * val) { bg_plugin_registry_t * plugin_reg = data; bg_cfg_section_t * cfg_section; const bg_parameter_info_t * parameter_info; bg_plugin_info_t * plugin_info; const char * parameter_name; if(!name) return; if(!find_parameter_input(plugin_reg, name, ¶meter_info, &plugin_info, &cfg_section, ¶meter_name)) return; // fprintf(stderr, // "bg_plugin_registry_set_parameter_input name: %s parameter_name: %s plugin_name: %s\n", // name, parameter_name, plugin_info->name); if(!strcmp(parameter_name, "$priority")) { bg_plugin_registry_set_priority(plugin_reg, plugin_info->name, val->val_i); } else if(!strcmp(parameter_name, "$extensions")) bg_plugin_registry_set_extensions(plugin_reg, plugin_info->name, val->val_str); else if(!strcmp(parameter_name, "$protocols")) bg_plugin_registry_set_protocols(plugin_reg, plugin_info->name, val->val_str); else bg_cfg_section_set_parameter(cfg_section, parameter_info, val); } int bg_plugin_registry_get_parameter_input(void * data, const char * name, bg_parameter_value_t * val) { bg_plugin_registry_t * plugin_reg = data; bg_cfg_section_t * cfg_section; const bg_parameter_info_t * parameter_info; bg_plugin_info_t * plugin_info; const char * parameter_name; if(!name) return 0; if(!find_parameter_input(plugin_reg, name, ¶meter_info, &plugin_info, &cfg_section, ¶meter_name)) return 0; // fprintf(stderr, // "bg_plugin_registry_get_parameter_input name: %s parameter_name: %s plugin_name: %s\n", // name, parameter_name, plugin_info->name); // fprintf(stderr, "plugin name: %s\n", plugin_info->name); if(!strcmp(parameter_name, "$priority")) { val->val_i = plugin_info->priority; // fprintf(stderr, "get priority: %d\n", val->val_i); } else if(!strcmp(parameter_name, "$extensions")) val->val_str = bg_strdup(val->val_str, plugin_info->extensions); else if(!strcmp(parameter_name, "$protocols")) val->val_str = bg_strdup(val->val_str, plugin_info->protocols); else bg_cfg_section_get_parameter(cfg_section, parameter_info, val); return 1; } static const bg_parameter_info_t audio_to_video_param = { .name = "encode_audio_to_video", .long_name = TRS("Write audio stream to video file if possible"), .type = BG_PARAMETER_CHECKBUTTON, }; static const bg_parameter_info_t subtitle_text_to_video_param = { .name = "encode_subtitle_text_to_video", .long_name = TRS("Write text subtitles to video file if possible"), .type = BG_PARAMETER_CHECKBUTTON, }; static const bg_parameter_info_t subtitle_overlay_to_video_param = { .name = "encode_subtitle_overlay_to_video", .long_name = TRS("Write overlay subtitles to video file if possible"), .type = BG_PARAMETER_CHECKBUTTON, }; static const bg_parameter_info_t audio_encoder_param = { .name = "audio_encoder", .long_name = TRS("Audio"), .type = BG_PARAMETER_MULTI_MENU, }; static const bg_parameter_info_t video_encoder_param = { .name = "video_encoder", .long_name = TRS("Video"), .type = BG_PARAMETER_MULTI_MENU, }; static const bg_parameter_info_t subtitle_text_encoder_param = { .name = "subtitle_text_encoder", .long_name = TRS("Text subtitles"), .type = BG_PARAMETER_MULTI_MENU, }; static const bg_parameter_info_t subtitle_overlay_encoder_param = { .name = "subtitle_overlay_encoder", .long_name = TRS("Overlay subtitles"), .type = BG_PARAMETER_MULTI_MENU, }; bg_parameter_info_t * bg_plugin_registry_create_encoder_parameters(bg_plugin_registry_t * reg, uint32_t type_mask, uint32_t flag_mask) { int do_audio = 0; int do_video = 0; int do_subtitle_text = 0; int do_subtitle_overlay = 0; int i; bg_parameter_info_t * ret; /* Determine what stream we want */ if(type_mask & BG_STREAM_AUDIO) do_audio = 1; if(type_mask & BG_STREAM_VIDEO) do_video = 1; if(type_mask & BG_STREAM_SUBTITLE_TEXT) do_subtitle_text = 1; if(type_mask & BG_STREAM_SUBTITLE_OVERLAY) do_subtitle_overlay = 1; /* Count parameters */ i = 0; if(do_audio) i += 1 + do_video; if(do_subtitle_text) i += 1 + do_video; if(do_subtitle_overlay) i += 1 + do_video; if(do_video) i++; ret = calloc(i+1, sizeof(*ret)); i = 0; if(do_audio) { if(do_video) { bg_parameter_info_copy(&ret[i], &audio_to_video_param); i++; } bg_parameter_info_copy(&ret[i], &audio_encoder_param); bg_plugin_registry_set_parameter_info(reg, BG_PLUGIN_ENCODER_AUDIO, flag_mask, &ret[i]); i++; } if(do_subtitle_text) { if(do_video) { bg_parameter_info_copy(&ret[i], &subtitle_text_to_video_param); i++; } bg_parameter_info_copy(&ret[i], &subtitle_text_encoder_param); bg_plugin_registry_set_parameter_info(reg, BG_PLUGIN_ENCODER_SUBTITLE_TEXT, flag_mask, &ret[i]); i++; } if(do_subtitle_overlay) { if(do_video) { bg_parameter_info_copy(&ret[i], &subtitle_overlay_to_video_param); i++; } bg_parameter_info_copy(&ret[i], &subtitle_overlay_encoder_param); bg_plugin_registry_set_parameter_info(reg, BG_PLUGIN_ENCODER_SUBTITLE_OVERLAY, flag_mask, &ret[i]); i++; } if(do_video) { bg_parameter_info_copy(&ret[i], &video_encoder_param); bg_plugin_registry_set_parameter_info(reg, BG_PLUGIN_ENCODER_VIDEO | BG_PLUGIN_ENCODER, flag_mask, &ret[i]); i++; } /* Set preset path */ ret[0].preset_path = bg_strdup(NULL, "encoders"); return ret; } static int encode_to_video(bg_plugin_registry_t * plugin_reg, bg_cfg_section_t * s, bg_stream_type_t type, int stream_mask) { int preference; const char * plugin_name = NULL; const bg_plugin_info_t * info; if(!(stream_mask & BG_STREAM_VIDEO)) return 0; bg_cfg_section_get_parameter_string(s, "video_encoder", &plugin_name); info = bg_plugin_find_by_name(plugin_reg, plugin_name); if(!info) return 0; switch(type) { case BG_STREAM_AUDIO: bg_cfg_section_get_parameter_int(s, "encode_audio_to_video", &preference); if(preference && info->max_audio_streams) return 1; break; case BG_STREAM_SUBTITLE_TEXT: bg_cfg_section_get_parameter_int(s, "encode_subtitle_text_to_video", &preference); if(preference && info->max_subtitle_text_streams) return 1; break; case BG_STREAM_SUBTITLE_OVERLAY: bg_cfg_section_get_parameter_int(s, "encode_subtitle_overlay_to_video", &preference); if(preference && info->max_subtitle_overlay_streams) return 1; break; default: break; } return 0; } const char * bg_encoder_section_get_plugin(bg_plugin_registry_t * plugin_reg, bg_cfg_section_t * s, bg_stream_type_t stream_type, int stream_mask) { const char * ret = NULL; switch(stream_type) { case BG_STREAM_AUDIO: if(!encode_to_video(plugin_reg, s, BG_STREAM_AUDIO, stream_mask)) bg_cfg_section_get_parameter_string(s, "audio_encoder", &ret); break; case BG_STREAM_SUBTITLE_TEXT: if(!encode_to_video(plugin_reg, s, BG_STREAM_SUBTITLE_TEXT, stream_mask)) bg_cfg_section_get_parameter_string(s, "subtitle_text_encoder", &ret); break; case BG_STREAM_SUBTITLE_OVERLAY: if(!encode_to_video(plugin_reg, s, BG_STREAM_SUBTITLE_OVERLAY, stream_mask)) bg_cfg_section_get_parameter_string(s, "subtitle_overlay_encoder", &ret); break; case BG_STREAM_VIDEO: bg_cfg_section_get_parameter_string(s, "video_encoder", &ret); break; } return ret; } void bg_encoder_section_get_plugin_config(bg_plugin_registry_t * plugin_reg, bg_cfg_section_t * s, bg_stream_type_t stream_type, int stream_mask, bg_cfg_section_t ** section_ret, const bg_parameter_info_t ** params_ret) { const char * plugin_name; const bg_plugin_info_t * info; plugin_name = bg_encoder_section_get_plugin(plugin_reg, s, stream_type, stream_mask); if(section_ret) *section_ret = NULL; if(params_ret) *params_ret = NULL; if(!plugin_name) return; info = bg_plugin_find_by_name(plugin_reg, plugin_name); if(!info->parameters) return; if(params_ret) { *params_ret = info->parameters; } switch(stream_type) { case BG_STREAM_AUDIO: if(section_ret) { *section_ret = bg_cfg_section_find_subsection(s, "audio_encoder"); *section_ret = bg_cfg_section_find_subsection(*section_ret, plugin_name); } break; case BG_STREAM_SUBTITLE_TEXT: if(section_ret) { *section_ret = bg_cfg_section_find_subsection(s, "subtitle_text_encoder"); *section_ret = bg_cfg_section_find_subsection(*section_ret, plugin_name); } break; case BG_STREAM_SUBTITLE_OVERLAY: if(section_ret) { *section_ret = bg_cfg_section_find_subsection(s, "subtitle_overlay_encoder"); *section_ret = bg_cfg_section_find_subsection(*section_ret, plugin_name); } break; case BG_STREAM_VIDEO: if(section_ret) { *section_ret = bg_cfg_section_find_subsection(s, "video_encoder"); *section_ret = bg_cfg_section_find_subsection(*section_ret, plugin_name); } break; } } void bg_encoder_section_get_stream_config(bg_plugin_registry_t * plugin_reg, bg_cfg_section_t * s, bg_stream_type_t stream_type, int stream_mask, bg_cfg_section_t ** section_ret, const bg_parameter_info_t ** params_ret) { const char * plugin_name; const bg_plugin_info_t * info; bg_cfg_section_t * subsection = NULL; int to_video = 0; plugin_name = bg_encoder_section_get_plugin(plugin_reg, s, stream_type, stream_mask); if(!plugin_name) { plugin_name = bg_encoder_section_get_plugin(plugin_reg, s, BG_STREAM_VIDEO, stream_mask); subsection = bg_cfg_section_find_subsection(s, "video_encoder"); to_video = 1; } info = bg_plugin_find_by_name(plugin_reg, plugin_name); if(section_ret) *section_ret = NULL; if(params_ret) *params_ret = NULL; switch(stream_type) { case BG_STREAM_AUDIO: if(params_ret) *params_ret = info->audio_parameters; if(section_ret && info->audio_parameters) { if(!subsection) subsection = bg_cfg_section_find_subsection(s, "audio_encoder"); subsection = bg_cfg_section_find_subsection(subsection, plugin_name); *section_ret = bg_cfg_section_find_subsection(subsection, "$audio"); } break; case BG_STREAM_SUBTITLE_TEXT: if(params_ret) *params_ret = info->subtitle_text_parameters; if(section_ret && info->subtitle_text_parameters) { if(!subsection) subsection = bg_cfg_section_find_subsection(s, "subtitle_text_encoder"); subsection = bg_cfg_section_find_subsection(subsection, plugin_name); *section_ret = bg_cfg_section_find_subsection(subsection, "$subtitle_text"); } break; case BG_STREAM_SUBTITLE_OVERLAY: if(params_ret) *params_ret = info->subtitle_overlay_parameters; if(section_ret && info->subtitle_overlay_parameters) { if(!subsection) subsection = bg_cfg_section_find_subsection(s, "subtitle_overlay_encoder"); subsection = bg_cfg_section_find_subsection(subsection, plugin_name); *section_ret = bg_cfg_section_find_subsection(subsection, "$subtitle_overlay"); } break; case BG_STREAM_VIDEO: if(params_ret) *params_ret = info->video_parameters; if(section_ret && info->video_parameters) { if(!subsection) subsection = bg_cfg_section_find_subsection(s, "video_encoder"); subsection = bg_cfg_section_find_subsection(subsection, plugin_name); *section_ret = bg_cfg_section_find_subsection(subsection, "$video"); } break; } } bg_cfg_section_t * bg_encoder_section_get_from_registry(bg_plugin_registry_t * plugin_reg, const bg_parameter_info_t * parameters, uint32_t type_mask, uint32_t flag_mask) { int i, j; const bg_plugin_info_t * info; bg_parameter_info_t * parameters_priv = NULL; bg_cfg_section_t * ret; bg_cfg_section_t * s_src; bg_cfg_section_t * s_dst; if(!parameters) { parameters_priv = bg_plugin_registry_create_encoder_parameters(plugin_reg, type_mask, flag_mask); parameters = parameters_priv; } /* Create section */ ret = bg_cfg_section_create_from_parameters("encoders", parameters); // bg_cfg_section_dump(ret, "encoder_section_1.xml"); /* Get the plugin defaults */ if(type_mask & BG_STREAM_AUDIO) { info = bg_plugin_registry_get_default(plugin_reg, BG_PLUGIN_ENCODER_AUDIO, flag_mask); bg_cfg_section_set_parameter_string(ret, "audio_encoder", info->name); bg_cfg_section_get_parameter_int(plugin_reg->config_section, "encode_audio_to_video", &i); bg_cfg_section_set_parameter_int(ret, "encode_audio_to_video", i); i = 0; while(strcmp(parameters[i].name, "audio_encoder")) i++; j = 0; while(parameters[i].multi_names[j]) { s_src = bg_cfg_section_find_subsection(plugin_reg->config_section, parameters[i].multi_names[j]); s_dst = bg_cfg_section_find_subsection(ret, "audio_encoder"); s_dst = bg_cfg_section_find_subsection(s_dst, parameters[i].multi_names[j]); bg_cfg_section_transfer(s_src, s_dst); j++; } } if(type_mask & BG_STREAM_SUBTITLE_TEXT) { info = bg_plugin_registry_get_default(plugin_reg, BG_PLUGIN_ENCODER_SUBTITLE_TEXT, flag_mask); bg_cfg_section_set_parameter_string(ret, "subtitle_text_encoder", info->name); bg_cfg_section_get_parameter_int(plugin_reg->config_section, "encode_subtitle_text_to_video", &i); bg_cfg_section_set_parameter_int(ret, "encode_subtitle_text_to_video", i); i = 0; while(strcmp(parameters[i].name, "subtitle_text_encoder")) i++; j = 0; while(parameters[i].multi_names[j]) { s_src = bg_cfg_section_find_subsection(plugin_reg->config_section, parameters[i].multi_names[j]); s_dst = bg_cfg_section_find_subsection(ret, "subtitle_text_encoder"); s_dst = bg_cfg_section_find_subsection(s_dst, parameters[i].multi_names[j]); bg_cfg_section_transfer(s_src, s_dst); j++; } } if(type_mask & BG_STREAM_SUBTITLE_OVERLAY) { info = bg_plugin_registry_get_default(plugin_reg, BG_PLUGIN_ENCODER_SUBTITLE_OVERLAY, flag_mask); bg_cfg_section_set_parameter_string(ret, "subtitle_overlay_encoder", info->name); bg_cfg_section_get_parameter_int(plugin_reg->config_section, "encode_subtitle_overlay_to_video", &i); bg_cfg_section_set_parameter_int(ret, "encode_subtitle_overlay_to_video", i); i = 0; while(strcmp(parameters[i].name, "subtitle_overlay_encoder")) i++; j = 0; while(parameters[i].multi_names[j]) { s_src = bg_cfg_section_find_subsection(plugin_reg->config_section, parameters[i].multi_names[j]); s_dst = bg_cfg_section_find_subsection(ret, "subtitle_overlay_encoder"); s_dst = bg_cfg_section_find_subsection(s_dst, parameters[i].multi_names[j]); bg_cfg_section_transfer(s_src, s_dst); j++; } } if(type_mask & BG_STREAM_VIDEO) { info = bg_plugin_registry_get_default(plugin_reg, BG_PLUGIN_ENCODER_VIDEO, flag_mask); bg_cfg_section_set_parameter_string(ret, "video_encoder", info->name); i = 0; while(strcmp(parameters[i].name, "video_encoder")) i++; j = 0; while(parameters[i].multi_names[j]) { s_src = bg_cfg_section_find_subsection(plugin_reg->config_section, parameters[i].multi_names[j]); s_dst = bg_cfg_section_find_subsection(ret, "video_encoder"); s_dst = bg_cfg_section_find_subsection(s_dst, parameters[i].multi_names[j]); bg_cfg_section_transfer(s_src, s_dst); j++; } } if(parameters_priv) bg_parameter_info_destroy_array(parameters_priv); // bg_cfg_section_dump(ret, "encoder_section_2.xml"); return ret; } void bg_encoder_section_store_in_registry(bg_plugin_registry_t * plugin_reg, bg_cfg_section_t * s, const bg_parameter_info_t * parameters, uint32_t type_mask, uint32_t flag_mask) { int i, j; const char * name; bg_parameter_info_t * parameters_priv = NULL; bg_cfg_section_t * s_src; bg_cfg_section_t * s_dst; if(!parameters) { parameters_priv = bg_plugin_registry_create_encoder_parameters(plugin_reg, type_mask, flag_mask); parameters = parameters_priv; } /* Get the plugin defaults */ if(type_mask & BG_STREAM_AUDIO) { bg_cfg_section_get_parameter_string(s, "audio_encoder", &name); bg_plugin_registry_set_default(plugin_reg, BG_PLUGIN_ENCODER_AUDIO, flag_mask, name); bg_cfg_section_get_parameter_int(s, "encode_audio_to_video", &i); bg_cfg_section_set_parameter_int(plugin_reg->config_section, "encode_audio_to_video", i); i = 0; while(strcmp(parameters[i].name, "audio_encoder")) i++; j = 0; while(parameters[i].multi_names[j]) { s_dst = bg_cfg_section_find_subsection(plugin_reg->config_section, parameters[i].multi_names[j]); s_src = bg_cfg_section_find_subsection(s, "audio_encoder"); s_src = bg_cfg_section_find_subsection(s_src, parameters[i].multi_names[j]); bg_cfg_section_transfer(s_src, s_dst); j++; } } if(type_mask & BG_STREAM_SUBTITLE_TEXT) { bg_cfg_section_get_parameter_string(s, "subtitle_text_encoder", &name); bg_plugin_registry_set_default(plugin_reg, BG_PLUGIN_ENCODER_SUBTITLE_TEXT, flag_mask, name); bg_cfg_section_get_parameter_int(s, "encode_subtitle_text_to_video", &i); bg_cfg_section_set_parameter_int(plugin_reg->config_section, "encode_subtitle_text_to_video", i); i = 0; while(strcmp(parameters[i].name, "subtitle_text_encoder")) i++; j = 0; while(parameters[i].multi_names[j]) { s_dst = bg_cfg_section_find_subsection(plugin_reg->config_section, parameters[i].multi_names[j]); s_src = bg_cfg_section_find_subsection(s, "subtitle_text_encoder"); s_src = bg_cfg_section_find_subsection(s_src, parameters[i].multi_names[j]); bg_cfg_section_transfer(s_src, s_dst); j++; } } if(type_mask & BG_STREAM_SUBTITLE_OVERLAY) { bg_cfg_section_get_parameter_string(s, "subtitle_overlay_encoder", &name); bg_plugin_registry_set_default(plugin_reg, BG_PLUGIN_ENCODER_SUBTITLE_OVERLAY, flag_mask, name); bg_cfg_section_get_parameter_int(s, "encode_subtitle_overlay_to_video", &i); bg_cfg_section_set_parameter_int(plugin_reg->config_section, "encode_subtitle_overlay_to_video", i); i = 0; while(strcmp(parameters[i].name, "subtitle_overlay_encoder")) i++; j = 0; while(parameters[i].multi_names[j]) { s_dst = bg_cfg_section_find_subsection(plugin_reg->config_section, parameters[i].multi_names[j]); s_src = bg_cfg_section_find_subsection(s, "subtitle_overlay_encoder"); s_src = bg_cfg_section_find_subsection(s_src, parameters[i].multi_names[j]); bg_cfg_section_transfer(s_src, s_dst); j++; } } if(type_mask & BG_STREAM_VIDEO) { bg_cfg_section_get_parameter_string(s, "video_encoder", &name); bg_plugin_registry_set_default(plugin_reg, BG_PLUGIN_ENCODER_VIDEO, flag_mask, name); i = 0; while(strcmp(parameters[i].name, "video_encoder")) i++; j = 0; while(parameters[i].multi_names[j]) { s_dst = bg_cfg_section_find_subsection(plugin_reg->config_section, parameters[i].multi_names[j]); s_src = bg_cfg_section_find_subsection(s, "video_encoder"); s_src = bg_cfg_section_find_subsection(s_src, parameters[i].multi_names[j]); bg_cfg_section_transfer(s_src, s_dst); j++; } } if(parameters_priv) bg_parameter_info_destroy_array(parameters_priv); } gmerlin-1.2.0~dfsg/lib/singlepic.c0000644000175000017500000007170011764363410016772 0ustar alessioalessio/***************************************************************** * gmerlin - a general purpose multimedia framework and applications * * Copyright (c) 2001 - 2011 Members of the Gmerlin project * gmerlin-general@lists.sourceforge.net * http://gmerlin.sourceforge.net * * 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 of the License, 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 this program. If not, see . * *****************************************************************/ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #define LOG_DOMAIN_ENC "singlepicture-encoder" #define LOG_DOMAIN_DEC "singlepicture-decoder" static char * get_extensions(bg_plugin_registry_t * reg, uint32_t type_mask, uint32_t flag_mask) { int num, i; char * ret = NULL; const bg_plugin_info_t * info; num = bg_plugin_registry_get_num_plugins(reg, type_mask, flag_mask); if(!num) return NULL; for(i = 0; i < num; i++) { info = bg_plugin_find_by_index(reg, i, type_mask, flag_mask); ret = bg_strcat(ret, info->extensions); if(i < num-1) ret = bg_strcat(ret, " "); } return ret; } /* Input stuff */ static const bg_parameter_info_t parameters_input[] = { { .name = "timescale", .long_name = TRS("Timescale"), .type = BG_PARAMETER_INT, .val_min = { .val_i = 1 }, .val_max = { .val_i = 100000 }, .val_default = { .val_i = 25 } }, { .name = "frame_duration", .long_name = TRS("Frame duration"), .type = BG_PARAMETER_INT, .val_min = { .val_i = 1 }, .val_max = { .val_i = 100000 }, .val_default = { .val_i = 1 } }, { /* End of parameters */ } }; static const bg_parameter_info_t parameters_input_still[] = { { .name = "display_time", .long_name = TRS("Display time"), .type = BG_PARAMETER_TIME, .val_min = { .val_time = 0 }, .val_max = { .val_time = 3600 * (gavl_time_t)GAVL_TIME_SCALE }, .val_default = { .val_time = 0 }, .help_string = TRS("Time to pass until the next track will be selected. 0 means infinite.") }, { /* End of parameters */ } }; typedef struct { bg_track_info_t track_info; bg_plugin_registry_t * plugin_reg; int timescale; int frame_duration; gavl_time_t display_time; char * template; int64_t frame_start; int64_t frame_end; int64_t current_frame; bg_plugin_handle_t * handle; bg_image_reader_plugin_t * image_reader; char * filename_buffer; int header_read; bg_stream_action_t action; int do_still; } input_t; static const bg_parameter_info_t * get_parameters_input(void * priv) { return parameters_input; } static const bg_parameter_info_t * get_parameters_input_still(void * priv) { return parameters_input_still; } static void set_parameter_input(void * priv, const char * name, const bg_parameter_value_t * val) { input_t * inp = priv; if(!name) return; else if(!strcmp(name, "timescale")) { inp->timescale = val->val_i; } else if(!strcmp(name, "frame_duration")) { inp->frame_duration = val->val_i; } else if(!strcmp(name, "display_time")) { inp->display_time = val->val_time; if(!inp->display_time) inp->display_time = GAVL_TIME_UNDEFINED; } } static int open_input(void * priv, const char * filename) { const bg_plugin_info_t * info; char * tmp_string; const char * pos; const char * pos_start; const char * pos_end; const gavl_metadata_t * m; input_t * inp = priv; /* Check if the first file exists */ if(access(filename, R_OK)) return 0; /* Load plugin */ info = bg_plugin_find_by_filename(inp->plugin_reg, filename, BG_PLUGIN_IMAGE_READER); if(!info) return 0; inp->handle = bg_plugin_load(inp->plugin_reg, info); inp->image_reader = (bg_image_reader_plugin_t*)inp->handle->plugin; /* Create template */ pos = filename + strlen(filename) - 1; while((*pos != '.') && (pos != filename)) pos--; if(pos == filename) return 0; /* pos points now to the last dot */ pos--; while(!isdigit(*pos) && (pos != filename)) pos--; if(pos == filename) return 0; /* pos points now to the last digit */ pos_end = pos+1; while(isdigit(*pos) && (pos != filename)) pos--; if(pos != filename) pos_start = pos+1; else pos_start = pos; /* Now, cut the pieces together */ if(pos_start != filename) inp->template = bg_strncat(inp->template, filename, pos_start); tmp_string = bg_sprintf("%%0%dd", (int)(pos_end - pos_start)); inp->template = bg_strcat(inp->template, tmp_string); free(tmp_string); inp->template = bg_strcat(inp->template, pos_end); inp->frame_start = strtoll(pos_start, NULL, 10); inp->frame_end = inp->frame_start+1; inp->filename_buffer = malloc(strlen(filename)+100); while(1) { sprintf(inp->filename_buffer, inp->template, inp->frame_end); if(access(inp->filename_buffer, R_OK)) break; inp->frame_end++; } /* Create stream */ inp->track_info.num_video_streams = 1; inp->track_info.video_streams = calloc(1, sizeof(*inp->track_info.video_streams)); inp->track_info.duration = gavl_frames_to_time(inp->timescale, inp->frame_duration, inp->frame_end - inp->frame_start); /* Get track name */ bg_set_track_name_default(&inp->track_info, filename); inp->track_info.flags |= (BG_TRACK_SEEKABLE|BG_TRACK_PAUSABLE); inp->current_frame = inp->frame_start; sprintf(inp->filename_buffer, inp->template, inp->current_frame); /* Load image header */ if(!inp->image_reader->read_header(inp->handle->priv, inp->filename_buffer, &inp->track_info.video_streams[0].format)) return 0; inp->track_info.video_streams[0].format.timescale = inp->timescale; inp->track_info.video_streams[0].format.frame_duration = inp->frame_duration; inp->track_info.video_streams[0].format.framerate_mode = GAVL_FRAMERATE_CONSTANT; inp->header_read = 1; /* Metadata */ if(inp->image_reader->get_metadata && (m = inp->image_reader->get_metadata(inp->handle->priv))) { gavl_metadata_copy(&inp->track_info.metadata, m); } gavl_metadata_set(&inp->track_info.video_streams[0].m, GAVL_META_FORMAT, "Single images"); return 1; } static int open_stills_input(void * priv, const char * filename) { const char * tag; const bg_plugin_info_t * info; const gavl_metadata_t * m; input_t * inp = priv; /* Check if the first file exists */ if(access(filename, R_OK)) return 0; /* First of all, check if there is a plugin for this format */ info = bg_plugin_find_by_filename(inp->plugin_reg, filename, BG_PLUGIN_IMAGE_READER); if(!info) return 0; inp->handle = bg_plugin_load(inp->plugin_reg, info); if(!inp->handle) { bg_log(BG_LOG_ERROR, LOG_DOMAIN_DEC, "Plugin %s could not be loaded", info->name); return 0; } inp->image_reader = (bg_image_reader_plugin_t*)inp->handle->plugin; /* Create stream */ inp->track_info.num_video_streams = 1; inp->track_info.video_streams = calloc(1, sizeof(*inp->track_info.video_streams)); inp->track_info.video_streams[0].format.framerate_mode = GAVL_FRAMERATE_STILL; inp->track_info.duration = inp->display_time; /* Get track name */ bg_set_track_name_default(&inp->track_info, filename); inp->filename_buffer = bg_strdup(inp->filename_buffer, filename); if(!inp->image_reader->read_header(inp->handle->priv, inp->filename_buffer, &inp->track_info.video_streams[0].format)) return 0; inp->track_info.video_streams[0].format.timescale = GAVL_TIME_SCALE; inp->track_info.video_streams[0].format.frame_duration = 0; inp->track_info.video_streams[0].format.framerate_mode = GAVL_FRAMERATE_STILL; /* Metadata */ if(inp->image_reader->get_metadata && (m = inp->image_reader->get_metadata(inp->handle->priv))) { gavl_metadata_copy(&inp->track_info.metadata, m); } tag = gavl_metadata_get(&inp->track_info.metadata, GAVL_META_FORMAT); if(tag) gavl_metadata_set(&inp->track_info.video_streams[0].m, GAVL_META_FORMAT, tag); else gavl_metadata_set(&inp->track_info.video_streams[0].m, GAVL_META_FORMAT, "Image"); gavl_metadata_set(&inp->track_info.metadata, GAVL_META_FORMAT, "Still image"); inp->header_read = 1; return 1; } static bg_track_info_t * get_track_info_input(void * priv, int track) { input_t * inp = priv; return &inp->track_info; } static int set_video_stream_input(void * priv, int stream, bg_stream_action_t action) { input_t * inp = priv; inp->action = action; /* Close image reader */ if(inp->action == BG_STREAM_ACTION_READRAW) { /* Unload the plugin */ if(inp->handle) bg_plugin_unref(inp->handle); inp->handle = NULL; inp->image_reader = NULL; } return 1; } static int get_compression_info_input(void * priv, int stream, gavl_compression_info_t * ci) { int ret; input_t * inp = priv; if(!inp->image_reader || !inp->image_reader->get_compression_info) return 0; ret = inp->image_reader->get_compression_info(inp->handle->priv, ci); if(ret) { if(gavl_compression_need_pixelformat(ci->id) && (inp->track_info.video_streams[0].format.pixelformat == GAVL_PIXELFORMAT_NONE)) return 0; } return ret; } static int start_input(void * priv) { return 1; } static int has_frame_input(void * priv, int stream) { return 1; } static int read_video_frame_input(void * priv, gavl_video_frame_t* f, int stream) { gavl_video_format_t format; input_t * inp = priv; if(inp->do_still) { if(inp->current_frame) return 0; } else if(inp->current_frame == inp->frame_end) return 0; if(!inp->header_read) { if(!inp->do_still) sprintf(inp->filename_buffer, inp->template, inp->current_frame); if(!inp->image_reader->read_header(inp->handle->priv, inp->filename_buffer, &format)) return 0; } if(!inp->image_reader->read_image(inp->handle->priv, f)) { return 0; } if(f) { f->timestamp = (inp->current_frame - inp->frame_start) * inp->frame_duration; if(!inp->do_still) f->duration = inp->frame_duration; } inp->header_read = 0; inp->current_frame++; return 1; } static int read_video_packet_input(void * priv, int stream, gavl_packet_t* p) { FILE * in; int64_t size; input_t * inp = priv; sprintf(inp->filename_buffer, inp->template, inp->current_frame); if(inp->do_still) { if(inp->current_frame) return 0; } else if(inp->current_frame == inp->frame_end) return 0; in = fopen(inp->filename_buffer, "rb"); if(!in) return 0; fseek(in, 0, SEEK_END); size = ftell(in); fseek(in, 0, SEEK_SET); gavl_packet_alloc(p, size); p->data_len = fread(p->data, 1, size, in); fclose(in); if(p->data_len < size) return 0; p->pts = (inp->current_frame - inp->frame_start) * inp->frame_duration; p->flags = GAVL_PACKET_KEYFRAME; if(!inp->do_still) p->duration = inp->frame_duration; inp->current_frame++; return 1; } static int set_track_input_stills(void * priv, int track) { input_t * inp = priv; /* Reset image reader */ inp->current_frame = 0; if(inp->header_read) { inp->image_reader->read_image(inp->handle->priv, NULL); inp->header_read = 0; } return 1; } static void seek_input(void * priv, int64_t * time, int scale) { input_t * inp = priv; int64_t time_scaled = gavl_time_rescale(scale, inp->timescale, *time); inp->current_frame = inp->frame_start + time_scaled / inp->frame_duration; time_scaled = (int64_t)inp->current_frame * inp->frame_duration; *time = gavl_time_rescale(inp->timescale, scale, time_scaled); } static void stop_input(void * priv) { input_t * inp = priv; if(inp->action != BG_STREAM_ACTION_DECODE) return; } static void close_input(void * priv) { input_t * inp = priv; if(inp->template) { free(inp->template); inp->template = NULL; } if(inp->filename_buffer) { free(inp->filename_buffer); inp->filename_buffer = NULL; } bg_track_info_free(&inp->track_info); /* Unload the plugin */ if(inp->handle) bg_plugin_unref(inp->handle); inp->handle = NULL; inp->image_reader = NULL; } static void destroy_input(void* priv) { close_input(priv); free(priv); } static const bg_input_plugin_t input_plugin = { .common = { BG_LOCALE, .name = bg_singlepic_input_name, .long_name = TRS("Image video input plugin"), .description = TRS("This plugin reads series of images as a video. It uses the installed image readers."), .type = BG_PLUGIN_INPUT, .flags = BG_PLUGIN_FILE, .priority = 5, .create = NULL, .destroy = destroy_input, .get_parameters = get_parameters_input, .set_parameter = set_parameter_input }, .open = open_input, // .get_num_tracks = bg_avdec_get_num_tracks, .get_track_info = get_track_info_input, .get_video_compression_info = get_compression_info_input, /* Set streams */ .set_video_stream = set_video_stream_input, /* * Start decoding. * Track info is the track, which should be played. * The plugin must take care of the "active" fields * in the stream infos to check out, which streams are to be decoded */ .start = start_input, /* Read one video frame (returns FALSE on EOF) */ .read_video = read_video_frame_input, .read_video_packet = read_video_packet_input, /* * Do percentage seeking (can be NULL) * Media streams are supposed to be seekable, if this * function is non-NULL AND the duration field of the track info * is > 0 */ .seek = seek_input, /* Stop playback, close all decoders */ .stop = stop_input, .close = close_input, }; static const bg_input_plugin_t input_plugin_stills = { .common = { BG_LOCALE, .name = bg_singlepic_stills_input_name, .long_name = "Still image input plugin", .description = TRS("This plugin reads images as stills. It uses the installed image readers."), .type = BG_PLUGIN_INPUT, .flags = BG_PLUGIN_FILE, .priority = BG_PLUGIN_PRIORITY_MAX, .create = NULL, .destroy = destroy_input, .get_parameters = get_parameters_input_still, .set_parameter = set_parameter_input }, .open = open_stills_input, .set_track = set_track_input_stills, // .get_num_tracks = bg_avdec_get_num_tracks, .get_track_info = get_track_info_input, /* Set streams */ .set_video_stream = set_video_stream_input, /* * Start decoding. * Track info is the track, which should be played. * The plugin must take care of the "active" fields * in the stream infos to check out, which streams are to be decoded */ .start = start_input, .has_still = has_frame_input, /* Read one video frame (returns FALSE on EOF) */ .read_video = read_video_frame_input, /* * Do percentage seeking (can be NULL) * Media streams are supposed to be seekable, if this * function is non-NULL AND the duration field of the track info * is > 0 */ // .seek = seek_input, /* Stop playback, close all decoders */ .stop = stop_input, .close = close_input, }; const bg_plugin_common_t * bg_singlepic_input_get() { return (const bg_plugin_common_t*)(&input_plugin); } const bg_plugin_common_t * bg_singlepic_stills_input_get() { return (const bg_plugin_common_t*)(&input_plugin_stills); } static bg_plugin_info_t * get_input_info(bg_plugin_registry_t * reg, const bg_input_plugin_t * plugin) { bg_plugin_info_t * ret; if(!bg_plugin_registry_get_num_plugins(reg, BG_PLUGIN_IMAGE_READER, BG_PLUGIN_FILE)) return NULL; ret = bg_plugin_info_create(&plugin->common); ret->extensions = get_extensions(reg, BG_PLUGIN_IMAGE_READER, BG_PLUGIN_FILE); return ret; } bg_plugin_info_t * bg_singlepic_input_info(bg_plugin_registry_t * reg) { bg_plugin_info_t * ret; ret = get_input_info(reg, &input_plugin); if(ret) ret->parameters = bg_parameter_info_copy_array(parameters_input); return ret; } bg_plugin_info_t * bg_singlepic_stills_input_info(bg_plugin_registry_t * reg) { bg_plugin_info_t * ret; ret = get_input_info(reg, &input_plugin_stills); if(ret) ret->parameters = bg_parameter_info_copy_array(parameters_input_still); return ret; } void * bg_singlepic_input_create(bg_plugin_registry_t * reg) { input_t * ret; ret = calloc(1, sizeof(*ret)); ret->plugin_reg = reg; return ret; } void * bg_singlepic_stills_input_create(bg_plugin_registry_t * reg) { input_t * ret; ret = calloc(1, sizeof(*ret)); ret->plugin_reg = reg; ret->do_still = 1; return ret; } /* Encoder stuff */ static const bg_parameter_info_t parameters_encoder[] = { { .name = "plugin", .long_name = TRS("Plugin"), .type = BG_PARAMETER_MULTI_MENU, }, { .name = "frame_digits", .long_name = TRS("Framenumber digits"), .type = BG_PARAMETER_INT, .val_min = { .val_i = 1 }, .val_max = { .val_i = 9 }, .val_default = { .val_i = 4 }, }, { .name = "frame_offset", .long_name = TRS("Framenumber offset"), .type = BG_PARAMETER_INT, .val_min = { .val_i = 0 }, .val_max = { .val_i = 1000000 }, .val_default = { .val_i = 0 }, } }; typedef struct { char * filename_base; bg_plugin_handle_t * plugin_handle; bg_image_writer_plugin_t * image_writer; gavl_metadata_t metadata; bg_parameter_info_t * parameters; bg_plugin_registry_t * plugin_reg; int frame_digits, frame_offset; int64_t frame_counter; char * mask; char * filename_buffer; gavl_video_format_t format; bg_encoder_callbacks_t * cb; int have_header; bg_iw_callbacks_t iw_callbacks; const gavl_compression_info_t * ci; } encoder_t; static int iw_callbacks_create_output_file(void * priv, const char * filename) { encoder_t * e = priv; return bg_encoder_cb_create_output_file(e->cb, filename); } static bg_parameter_info_t * create_encoder_parameters(bg_plugin_registry_t * plugin_reg) { bg_parameter_info_t * ret = bg_parameter_info_copy_array(parameters_encoder); bg_plugin_registry_set_parameter_info(plugin_reg, BG_PLUGIN_IMAGE_WRITER, BG_PLUGIN_FILE, &ret[0]); return ret; } static const bg_parameter_info_t * get_parameters_encoder(void * priv) { encoder_t * enc = (encoder_t *)priv; if(!enc->parameters) enc->parameters = create_encoder_parameters(enc->plugin_reg); return enc->parameters; } static void set_parameter_encoder(void * priv, const char * name, const bg_parameter_value_t * val) { const bg_plugin_info_t * info; encoder_t * e; e = (encoder_t *)priv; if(!name) { return; } else if(!strcmp(name, "plugin")) { /* Load plugin */ if(!e->plugin_handle || strcmp(e->plugin_handle->info->name, val->val_str)) { if(e->plugin_handle) { bg_plugin_unref(e->plugin_handle); e->plugin_handle = NULL; } info = bg_plugin_find_by_name(e->plugin_reg, val->val_str); e->plugin_handle = bg_plugin_load(e->plugin_reg, info); e->image_writer = (bg_image_writer_plugin_t*)(e->plugin_handle->plugin); if(e->image_writer->set_callbacks) e->image_writer->set_callbacks(e->plugin_handle->priv, &e->iw_callbacks); } } else if(!strcmp(name, "frame_digits")) { e->frame_digits = val->val_i; } else if(!strcmp(name, "frame_offset")) { e->frame_offset = val->val_i; } else { if(e->plugin_handle && e->plugin_handle->plugin->set_parameter) { e->plugin_handle->plugin->set_parameter(e->plugin_handle->priv, name, val); } } } static void set_callbacks_encoder(void * data, bg_encoder_callbacks_t * cb) { encoder_t * e = data; e->cb = cb; } static void create_mask(encoder_t * e, const char * ext) { char * tmp_string; int filename_len; e->mask = bg_strdup(e->mask, e->filename_base); tmp_string = bg_sprintf("-%%0%d"PRId64".%s", e->frame_digits, ext); e->mask = bg_strcat(e->mask, tmp_string); free(tmp_string); filename_len = strlen(e->filename_base) + e->frame_digits + strlen(ext) + 16; e->filename_buffer = malloc(filename_len); } static int open_encoder(void * data, const char * filename, const gavl_metadata_t * metadata, const bg_chapter_list_t * chapter_list) { encoder_t * e; e = (encoder_t *)data; e->frame_counter = e->frame_offset; e->filename_base = bg_strdup(e->filename_base, filename); if(metadata) gavl_metadata_copy(&e->metadata, metadata); return 1; } static int write_frame_header(encoder_t * e) { int ret; e->have_header = 1; /* Create filename */ sprintf(e->filename_buffer, e->mask, e->frame_counter); ret = e->image_writer->write_header(e->plugin_handle->priv, e->filename_buffer, &e->format, &e->metadata); if(!ret) { e->have_header = 0; } e->frame_counter++; return ret; } static int start_encoder(void * data) { encoder_t * e; e = (encoder_t *)data; return (e->have_header || e->ci) ? 1 : 0; } static int writes_compressed_video(void * priv, const gavl_video_format_t * format, const gavl_compression_info_t * info) { int separate = 0; if(gavl_compression_get_extension(info->id, &separate) && separate) return 1; return 0; } static int add_video_stream_encoder(void * data, const gavl_metadata_t * m, const gavl_video_format_t * format) { char ** extensions; encoder_t * e = data; gavl_video_format_copy(&e->format, format); extensions = bg_strbreak(e->image_writer->extensions, ' '); create_mask(e, extensions[0]); bg_strbreak_free(extensions); /* Write image header so we know the format */ write_frame_header(e); return 0; } static int add_video_stream_compressed_encoder(void * data, const gavl_metadata_t * m, const gavl_video_format_t * format, const gavl_compression_info_t * info) { encoder_t * e; e = (encoder_t *)data; e->ci = info; create_mask(e, gavl_compression_get_extension(e->ci->id, NULL)); return 0; } static void get_video_format_encoder(void * data, int stream, gavl_video_format_t * format) { encoder_t * e; e = (encoder_t *)data; gavl_video_format_copy(format, &e->format); } static int write_video_frame_encoder(void * data, gavl_video_frame_t * frame, int stream) { int ret = 1; encoder_t * e; e = (encoder_t *)data; if(!e->have_header) ret = write_frame_header(e); if(ret) ret = e->image_writer->write_image(e->plugin_handle->priv, frame); e->have_header = 0; return ret; } static int write_video_packet_encoder(void * data, gavl_packet_t * packet, int stream) { FILE * out; encoder_t * e = data; sprintf(e->filename_buffer, e->mask, e->frame_counter); if(!bg_encoder_cb_create_output_file(e->cb, e->filename_buffer)) return 0; out = fopen(e->filename_buffer, "wb"); if(!out) { bg_log(BG_LOG_ERROR, LOG_DOMAIN_ENC, "Cannot open file %s: %s", e->filename_buffer, strerror(errno)); return 0; } if(fwrite(packet->data, 1, packet->data_len, out) < packet->data_len) { bg_log(BG_LOG_ERROR, LOG_DOMAIN_ENC, "Couldn't write data to %s: %s", e->filename_buffer, strerror(errno)); return 0; } fclose(out); e->frame_counter++; return 1; } #define STR_FREE(s) if(s){free(s);s=NULL;} static int close_encoder(void * data, int do_delete) { int64_t i; encoder_t * e = data; if(do_delete) { for(i = e->frame_offset; i < e->frame_counter; i++) { sprintf(e->filename_buffer, e->mask, i); remove(e->filename_buffer); } } STR_FREE(e->mask); STR_FREE(e->filename_buffer); STR_FREE(e->filename_base); gavl_metadata_free(&e->metadata); if(e->plugin_handle) { bg_plugin_unref(e->plugin_handle); e->plugin_handle = NULL; } return 1; } static void destroy_encoder(void * data) { encoder_t * e; e = (encoder_t *)data; close_encoder(data, 0); if(e->parameters) { bg_parameter_info_destroy_array(e->parameters); } free(e); } const bg_encoder_plugin_t encoder_plugin = { .common = { BG_LOCALE, .name = bg_singlepic_encoder_name, .long_name = "Singlepicture encoder", .description = TRS("This plugin encodes a video as a series of images. It uses the installed image writers."), .type = BG_PLUGIN_ENCODER_VIDEO, .flags = BG_PLUGIN_FILE, .priority = BG_PLUGIN_PRIORITY_MAX, .create = NULL, .destroy = destroy_encoder, .get_parameters = get_parameters_encoder, .set_parameter = set_parameter_encoder }, /* Maximum number of audio/video streams. -1 means infinite */ .max_audio_streams = 0, .max_video_streams = 1, /* Open a file, filename base is without extension, which will be added by the plugin */ .set_callbacks = set_callbacks_encoder, .open = open_encoder, .writes_compressed_video = writes_compressed_video, .add_video_stream = add_video_stream_encoder, .add_video_stream_compressed = add_video_stream_compressed_encoder, .get_video_format = get_video_format_encoder, .start = start_encoder, .write_video_frame = write_video_frame_encoder, .write_video_packet = write_video_packet_encoder, /* Close it */ .close = close_encoder, }; const bg_plugin_common_t * bg_singlepic_encoder_get() { return (bg_plugin_common_t*)(&encoder_plugin); } bg_plugin_info_t * bg_singlepic_encoder_info(bg_plugin_registry_t * reg) { bg_plugin_info_t * ret; if(!bg_plugin_registry_get_num_plugins(reg, BG_PLUGIN_IMAGE_WRITER, BG_PLUGIN_FILE)) return NULL; ret = bg_plugin_info_create(&encoder_plugin.common); ret->parameters = create_encoder_parameters(reg); return ret; } void * bg_singlepic_encoder_create(bg_plugin_registry_t * reg) { encoder_t * ret; ret = calloc(1, sizeof(*ret)); ret->plugin_reg = reg; ret->iw_callbacks.data = ret; ret->iw_callbacks.create_output_file = iw_callbacks_create_output_file; return ret; } gmerlin-1.2.0~dfsg/lib/player_audio.c0000644000175000017500000002245511764363410017475 0ustar alessioalessio/***************************************************************** * gmerlin - a general purpose multimedia framework and applications * * Copyright (c) 2001 - 2011 Members of the Gmerlin project * gmerlin-general@lists.sourceforge.net * http://gmerlin.sourceforge.net * * 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 of the License, 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 this program. If not, see . * *****************************************************************/ #include #include #include #include #define LOG_DOMAIN "player.audio" #include #include void bg_player_audio_create(bg_player_t * p, bg_plugin_registry_t * plugin_reg) { bg_player_audio_stream_t * s = &p->audio_stream; bg_gavl_audio_options_init(&s->options); s->th = bg_player_thread_create(p->thread_common); s->fc = bg_audio_filter_chain_create(&s->options, plugin_reg); s->cnv_out = gavl_audio_converter_create(); s->volume = gavl_volume_control_create(); s->peak_detector = gavl_peak_detector_create(); pthread_mutex_init(&s->volume_mutex,NULL); pthread_mutex_init(&s->config_mutex,NULL); pthread_mutex_init(&s->time_mutex,NULL); pthread_mutex_init(&s->mute_mutex, NULL); pthread_mutex_init(&s->eof_mutex,NULL); s->timer = gavl_timer_create(); } void bg_player_audio_destroy(bg_player_t * p) { bg_player_audio_stream_t * s = &p->audio_stream; gavl_audio_converter_destroy(s->cnv_out); bg_gavl_audio_options_free(&s->options); bg_audio_filter_chain_destroy(s->fc); gavl_volume_control_destroy(s->volume); gavl_peak_detector_destroy(s->peak_detector); pthread_mutex_destroy(&s->volume_mutex); pthread_mutex_destroy(&s->eof_mutex); pthread_mutex_destroy(&s->time_mutex); gavl_timer_destroy(s->timer); if(s->plugin_handle) bg_plugin_unref(s->plugin_handle); bg_player_thread_destroy(s->th); } int bg_player_audio_init(bg_player_t * player, int audio_stream) { gavl_sample_format_t force_format; gavl_audio_options_t * opt; bg_player_audio_stream_t * s; // int do_filter; if(!DO_AUDIO(player->flags)) return 1; s = &player->audio_stream; s->send_silence = 0; s->options.options_changed = 0; s->in_func = bg_player_input_read_audio; s->in_data = player; s->in_stream = player->current_audio_stream; bg_player_input_get_audio_format(player); bg_audio_filter_chain_connect_input(s->fc, s->in_func, s->in_data, s->in_stream); s->in_func = bg_audio_filter_chain_read; s->in_data = s->fc; s->in_stream = 0; pthread_mutex_lock(&s->config_mutex); force_format = s->options.force_format; bg_audio_filter_chain_init(s->fc, &s->input_format, &s->fifo_format); pthread_mutex_unlock(&s->config_mutex); gavl_audio_format_copy(&s->output_format, &s->fifo_format); if(!bg_player_oa_init(s)) return 0; gavl_audio_format_copy(&s->fifo_format, &s->output_format); if(force_format != GAVL_SAMPLE_NONE) s->fifo_format.sample_format = force_format; bg_audio_filter_chain_set_out_format(s->fc, &s->fifo_format); /* Volume control */ gavl_volume_control_set_format(s->volume, &s->fifo_format); gavl_peak_detector_set_format(s->peak_detector, &s->fifo_format); /* Output conversion */ opt = gavl_audio_converter_get_options(s->cnv_out); gavl_audio_options_copy(opt, s->options.opt); s->fifo_frame = gavl_audio_frame_create(&s->output_format); if(!gavl_audio_converter_init(s->cnv_out, &s->fifo_format, &s->output_format)) { s->do_convert_out = 0; s->output_frame = s->fifo_frame; } else { s->do_convert_out = 1; s->output_frame = gavl_audio_frame_create(&s->output_format); } return 1; } void bg_player_audio_cleanup(bg_player_t * player) { bg_player_audio_stream_t * s; s = &player->audio_stream; if(s->fifo_frame) { gavl_audio_frame_destroy(s->fifo_frame); s->fifo_frame = NULL; } if(s->output_frame && s->do_convert_out) { gavl_audio_frame_destroy(s->output_frame); } s->output_frame = NULL; } /* Configuration stuff */ static const bg_parameter_info_t parameters[] = { #if 0 { .name = "audio", .long_name = TRS("Audio"), .type = BG_PARAMETER_SECTION, }, #endif BG_GAVL_PARAM_FORCE_SAMPLEFORMAT, BG_GAVL_PARAM_CONVERSION_QUALITY, BG_GAVL_PARAM_AUDIO_DITHER_MODE, BG_GAVL_PARAM_SAMPLERATE, BG_GAVL_PARAM_RESAMPLE_MODE, BG_GAVL_PARAM_CHANNEL_SETUP, { /* End of parameters */ } }; const bg_parameter_info_t * bg_player_get_audio_parameters(bg_player_t * p) { return parameters; } const bg_parameter_info_t * bg_player_get_audio_filter_parameters(bg_player_t * p) { return bg_audio_filter_chain_get_parameters(p->audio_stream.fc); } void bg_player_set_audio_parameter(void * data, const char * name, const bg_parameter_value_t * val) { bg_player_t * p = (bg_player_t*)data; int need_restart = 0; int is_interrupted; int do_init; int check_restart; do_init = (bg_player_get_state(p) == BG_PLAYER_STATE_INIT); pthread_mutex_lock(&p->audio_stream.config_mutex); is_interrupted = p->audio_stream.interrupted; bg_gavl_audio_set_parameter(&p->audio_stream.options, name, val); if(!do_init && !is_interrupted) check_restart = 1; else check_restart = 0; if(check_restart) need_restart = p->audio_stream.options.options_changed; pthread_mutex_unlock(&p->audio_stream.config_mutex); if(!need_restart && check_restart) { bg_audio_filter_chain_lock(p->audio_stream.fc); need_restart = bg_audio_filter_chain_need_restart(p->audio_stream.fc); bg_audio_filter_chain_unlock(p->audio_stream.fc); } if(need_restart) { bg_log(BG_LOG_INFO, LOG_DOMAIN, "Restarting playback due to changed audio options"); bg_player_interrupt(p); pthread_mutex_lock(&p->audio_stream.config_mutex); p->audio_stream.interrupted = 1; pthread_mutex_unlock(&p->audio_stream.config_mutex); } if(!name && is_interrupted) { bg_player_interrupt_resume(p); pthread_mutex_lock(&p->audio_stream.config_mutex); p->audio_stream.interrupted = 0; pthread_mutex_unlock(&p->audio_stream.config_mutex); } } void bg_player_set_audio_filter_parameter(void * data, const char * name, const bg_parameter_value_t * val) { int need_restart = 0; int is_interrupted; int do_init; bg_player_t * p = (bg_player_t*)data; do_init = (bg_player_get_state(p) == BG_PLAYER_STATE_INIT); pthread_mutex_lock(&p->audio_stream.config_mutex); is_interrupted = p->audio_stream.interrupted; pthread_mutex_unlock(&p->audio_stream.config_mutex); bg_audio_filter_chain_lock(p->audio_stream.fc); bg_audio_filter_chain_set_parameter(p->audio_stream.fc, name, val); need_restart = bg_audio_filter_chain_need_restart(p->audio_stream.fc); bg_audio_filter_chain_unlock(p->audio_stream.fc); if(!do_init && need_restart && !is_interrupted) { bg_log(BG_LOG_INFO, LOG_DOMAIN, "Restarting playback due to changed audio filters"); bg_player_interrupt(p); pthread_mutex_lock(&p->audio_stream.config_mutex); p->audio_stream.interrupted = 1; pthread_mutex_unlock(&p->audio_stream.config_mutex); } if(!name && is_interrupted) { bg_player_interrupt_resume(p); pthread_mutex_lock(&p->audio_stream.config_mutex); p->audio_stream.interrupted = 0; pthread_mutex_unlock(&p->audio_stream.config_mutex); } } int bg_player_read_audio(bg_player_t * p, gavl_audio_frame_t * frame) { bg_player_audio_stream_t * s = &p->audio_stream; return s->in_func(s->in_data, frame, s->in_stream, s->fifo_format.samples_per_frame); } int bg_player_audio_set_eof(bg_player_t * p) { bg_msg_t * msg; int ret = 1; bg_log(BG_LOG_INFO, LOG_DOMAIN, "Detected EOF"); pthread_mutex_lock(&p->video_stream.eof_mutex); pthread_mutex_lock(&p->audio_stream.eof_mutex); p->audio_stream.eof = 1; if(p->video_stream.eof) { msg = bg_msg_queue_lock_write(p->command_queue); bg_msg_set_id(msg, BG_PLAYER_CMD_SETSTATE); bg_msg_set_arg_int(msg, 0, BG_PLAYER_STATE_EOF); bg_msg_queue_unlock_write(p->command_queue); } else { ret = 0; p->audio_stream.send_silence = 1; } pthread_mutex_unlock(&p->audio_stream.eof_mutex); pthread_mutex_unlock(&p->video_stream.eof_mutex); return ret; } gmerlin-1.2.0~dfsg/lib/parameter.c0000644000175000017500000003216611764363410017000 0ustar alessioalessio/***************************************************************** * gmerlin - a general purpose multimedia framework and applications * * Copyright (c) 2001 - 2011 Members of the Gmerlin project * gmerlin-general@lists.sourceforge.net * http://gmerlin.sourceforge.net * * 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 of the License, 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 this program. If not, see . * *****************************************************************/ #include #include #include #include void bg_parameter_value_copy(bg_parameter_value_t * dst, const bg_parameter_value_t * src, const bg_parameter_info_t * info) { switch(info->type) { case BG_PARAMETER_CHECKBUTTON: dst->val_i = src->val_i; break; case BG_PARAMETER_INT: case BG_PARAMETER_SLIDER_INT: dst->val_i = src->val_i; break; case BG_PARAMETER_FLOAT: case BG_PARAMETER_SLIDER_FLOAT: dst->val_f = src->val_f; break; case BG_PARAMETER_STRING: case BG_PARAMETER_STRING_HIDDEN: case BG_PARAMETER_FONT: case BG_PARAMETER_DEVICE: case BG_PARAMETER_FILE: case BG_PARAMETER_DIRECTORY: case BG_PARAMETER_STRINGLIST: case BG_PARAMETER_MULTI_MENU: case BG_PARAMETER_MULTI_LIST: case BG_PARAMETER_MULTI_CHAIN: dst->val_str = bg_strdup(dst->val_str, src->val_str); break; case BG_PARAMETER_COLOR_RGB: memcpy(dst->val_color, src->val_color, 3 * sizeof(dst->val_color[0])); dst->val_color[3] = 1.0; break; case BG_PARAMETER_COLOR_RGBA: memcpy(dst->val_color, src->val_color, 4 * sizeof(dst->val_color[0])); break; case BG_PARAMETER_POSITION: memcpy(dst->val_pos, src->val_pos, 2 * sizeof(dst->val_pos[0])); break; case BG_PARAMETER_TIME: dst->val_time = src->val_time; break; case BG_PARAMETER_SECTION: case BG_PARAMETER_BUTTON: break; } } void bg_parameter_value_free(bg_parameter_value_t * val, bg_parameter_type_t type) { switch(type) { case BG_PARAMETER_CHECKBUTTON: case BG_PARAMETER_INT: case BG_PARAMETER_SLIDER_INT: case BG_PARAMETER_FLOAT: case BG_PARAMETER_SLIDER_FLOAT: case BG_PARAMETER_TIME: case BG_PARAMETER_SECTION: case BG_PARAMETER_COLOR_RGB: case BG_PARAMETER_COLOR_RGBA: case BG_PARAMETER_POSITION: case BG_PARAMETER_BUTTON: break; case BG_PARAMETER_STRING: case BG_PARAMETER_STRING_HIDDEN: case BG_PARAMETER_FONT: case BG_PARAMETER_DEVICE: case BG_PARAMETER_FILE: case BG_PARAMETER_DIRECTORY: case BG_PARAMETER_STRINGLIST: case BG_PARAMETER_MULTI_MENU: case BG_PARAMETER_MULTI_LIST: case BG_PARAMETER_MULTI_CHAIN: if(val->val_str) free(val->val_str); break; } } static char ** copy_string_array(char const * const * arr) { int i, num; char ** ret; if(!arr) return NULL; num = 0; while(arr[num]) num++; ret = calloc(num+1, sizeof(*ret)); for(i = 0; i < num; i++) ret[i] = bg_strdup(ret[i], arr[i]); return ret; } static void free_string_array(char ** arr) { int i = 0; if(!arr) return; while(arr[i]) { free(arr[i]); i++; } free(arr); } void bg_parameter_info_copy(bg_parameter_info_t * dst, const bg_parameter_info_t * src) { int num_options, i; dst->name = bg_strdup(dst->name, src->name); dst->long_name = bg_strdup(dst->long_name, src->long_name); dst->opt = bg_strdup(dst->opt, src->opt); dst->help_string = bg_strdup(dst->help_string, src->help_string); dst->type = src->type; dst->flags = src->flags; dst->gettext_domain = bg_strdup(dst->gettext_domain, src->gettext_domain); dst->gettext_directory = bg_strdup(dst->gettext_directory, src->gettext_directory); dst->preset_path = bg_strdup(dst->preset_path, src->preset_path); switch(dst->type) { case BG_PARAMETER_CHECKBUTTON: dst->val_default.val_i = src->val_default.val_i; break; case BG_PARAMETER_INT: case BG_PARAMETER_SLIDER_INT: dst->val_default.val_i = src->val_default.val_i; dst->val_min.val_i = src->val_min.val_i; dst->val_max.val_i = src->val_max.val_i; break; case BG_PARAMETER_FLOAT: case BG_PARAMETER_SLIDER_FLOAT: dst->val_default.val_f = src->val_default.val_f; dst->val_min.val_f = src->val_min.val_f; dst->val_max.val_f = src->val_max.val_f; dst->num_digits = src->num_digits; break; case BG_PARAMETER_STRING: case BG_PARAMETER_STRING_HIDDEN: case BG_PARAMETER_FONT: case BG_PARAMETER_DEVICE: case BG_PARAMETER_FILE: case BG_PARAMETER_DIRECTORY: dst->val_default.val_str = bg_strdup(dst->val_default.val_str, src->val_default.val_str); break; case BG_PARAMETER_MULTI_MENU: case BG_PARAMETER_MULTI_LIST: case BG_PARAMETER_MULTI_CHAIN: dst->val_default.val_str = bg_strdup(dst->val_default.val_str, src->val_default.val_str); dst->multi_names_nc = copy_string_array(src->multi_names); dst->multi_labels_nc = copy_string_array(src->multi_labels); dst->multi_descriptions_nc = copy_string_array(src->multi_descriptions); i = 0; if(src->multi_names) { num_options = 0; while(src->multi_names[num_options]) num_options++; if(src->multi_parameters) { dst->multi_parameters_nc = calloc(num_options, sizeof(*(src->multi_parameters_nc))); i = 0; while(src->multi_names[i]) { if(src->multi_parameters[i]) dst->multi_parameters_nc[i] = bg_parameter_info_copy_array(src->multi_parameters[i]); i++; } } } break; case BG_PARAMETER_STRINGLIST: dst->val_default.val_str = bg_strdup(dst->val_default.val_str, src->val_default.val_str); /* Copy stringlist options */ if(src->multi_names) dst->multi_names_nc = copy_string_array(src->multi_names); if(src->multi_labels) dst->multi_labels_nc = copy_string_array(src->multi_labels); dst->multi_names = (char const **)dst->multi_names_nc; dst->multi_labels = (char const **)dst->multi_labels_nc; break; case BG_PARAMETER_COLOR_RGB: if(src->val_default.val_color) { memcpy(dst->val_default.val_color, src->val_default.val_color, 3 * sizeof(dst->val_default.val_color[0])); dst->val_default.val_color[3] = 1.0; } break; case BG_PARAMETER_COLOR_RGBA: if(src->val_default.val_color) { memcpy(dst->val_default.val_color, src->val_default.val_color, 4 * sizeof(dst->val_default.val_color[0])); } break; case BG_PARAMETER_POSITION: if(src->val_default.val_color) { memcpy(dst->val_default.val_pos, src->val_default.val_pos, 2 * sizeof(dst->val_default.val_pos[0])); } dst->num_digits = src->num_digits; break; case BG_PARAMETER_TIME: dst->val_default.val_time = src->val_default.val_time; break; case BG_PARAMETER_SECTION: case BG_PARAMETER_BUTTON: break; } bg_parameter_info_set_const_ptrs(dst); } bg_parameter_info_t * bg_parameter_info_copy_array(const bg_parameter_info_t * src) { int num_parameters, i; bg_parameter_info_t * ret; num_parameters = 0; while(src[num_parameters].name) num_parameters++; ret = calloc(num_parameters + 1, sizeof(bg_parameter_info_t)); for(i = 0; i < num_parameters; i++) bg_parameter_info_copy(&ret[i], &src[i]); return ret; } void bg_parameter_info_destroy_array(bg_parameter_info_t * info) { int index = 0; int i; while(info[index].name) { free(info[index].name); if(info[index].long_name) free(info[index].long_name); if(info[index].opt) free(info[index].opt); if(info[index].help_string) free(info[index].help_string); if(info[index].gettext_domain) free(info[index].gettext_domain); if(info[index].gettext_directory) free(info[index].gettext_directory); if(info[index].preset_path) free(info[index].preset_path); switch(info[index].type) { case BG_PARAMETER_STRINGLIST: free_string_array(info[index].multi_names_nc); free_string_array(info[index].multi_labels_nc); if(info[index].val_default.val_str) free(info[index].val_default.val_str); break; case BG_PARAMETER_STRING: case BG_PARAMETER_STRING_HIDDEN: case BG_PARAMETER_FONT: case BG_PARAMETER_DEVICE: case BG_PARAMETER_FILE: case BG_PARAMETER_DIRECTORY: if(info[index].val_default.val_str) free(info[index].val_default.val_str); break; case BG_PARAMETER_SECTION: case BG_PARAMETER_BUTTON: case BG_PARAMETER_CHECKBUTTON: case BG_PARAMETER_INT: case BG_PARAMETER_FLOAT: case BG_PARAMETER_TIME: case BG_PARAMETER_SLIDER_INT: case BG_PARAMETER_SLIDER_FLOAT: case BG_PARAMETER_COLOR_RGB: case BG_PARAMETER_COLOR_RGBA: case BG_PARAMETER_POSITION: break; case BG_PARAMETER_MULTI_MENU: case BG_PARAMETER_MULTI_LIST: case BG_PARAMETER_MULTI_CHAIN: i = 0; if(info[index].multi_parameters) { while(info[index].multi_names[i]) { if(info[index].multi_parameters[i]) bg_parameter_info_destroy_array(info[index].multi_parameters_nc[i]); i++; } free(info[index].multi_parameters_nc); } free_string_array(info[index].multi_names_nc); free_string_array(info[index].multi_labels_nc); free_string_array(info[index].multi_descriptions_nc); if(info[index].val_default.val_str) free(info[index].val_default.val_str); } index++; } free(info); } bg_parameter_info_t * bg_parameter_info_concat_arrays(bg_parameter_info_t const ** srcs) { int i, j, dst, num_parameters; bg_parameter_info_t * ret; /* Count the parameters */ num_parameters = 0; i = 0; while(srcs[i]) { j = 0; while(srcs[i][j].name) { num_parameters++; j++; } i++; } /* Allocate destination */ ret = calloc(num_parameters+1, sizeof(*ret)); /* Copy stuff */ i = 0; dst = 0; while(srcs[i]) { j = 0; while(srcs[i][j].name) { bg_parameter_info_copy(&ret[dst], &srcs[i][j]); dst++; j++; } i++; } return ret; } int bg_parameter_get_selected(const bg_parameter_info_t * info, const char * val) { int ret = -1, i; if(val) { i = 0; while(info->multi_names[i]) { if(!strcmp(val, info->multi_names[i])) { ret = i; break; } i++; } } if((ret < 0) && info->val_default.val_str) { i = 0; /* Try default value */ while(info->multi_names[i]) { if(!strcmp(info->val_default.val_str, info->multi_names[i])) { ret = i; break; } i++; } } if(ret < 0) return 0; else return ret; } const bg_parameter_info_t * bg_parameter_find(const bg_parameter_info_t * info, const char * name) { int i, j; const bg_parameter_info_t * child_ret; i = 0; while(info[i].name) { if(!strcmp(name, info[i].name)) return &info[i]; if(info[i].multi_parameters && info[i].multi_names) { j = 0; while(info[i].multi_names[j]) { if(info[i].multi_parameters[j]) { child_ret = bg_parameter_find(info[i].multi_parameters[j], name); if(child_ret) return child_ret; } j++; } } i++; } return NULL; } void bg_parameter_info_set_const_ptrs(bg_parameter_info_t * ret) { ret->multi_names = (char const **)ret->multi_names_nc; ret->multi_labels = (char const **)ret->multi_labels_nc; ret->multi_descriptions = (char const **)ret->multi_descriptions_nc; ret->multi_parameters = (bg_parameter_info_t const * const *)ret->multi_parameters_nc; } gmerlin-1.2.0~dfsg/lib/player_subtitle.c0000644000175000017500000002010011764363410020210 0ustar alessioalessio/***************************************************************** * gmerlin - a general purpose multimedia framework and applications * * Copyright (c) 2001 - 2011 Members of the Gmerlin project * gmerlin-general@lists.sourceforge.net * http://gmerlin.sourceforge.net * * 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 of the License, 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 this program. If not, see . * *****************************************************************/ #include #include #include #include // #define DUMP_SUBTITLE void bg_player_subtitle_create(bg_player_t * p) { p->subtitle_stream.cnv = gavl_video_converter_create(); p->subtitle_stream.renderer = bg_text_renderer_create(); pthread_mutex_init(&p->subtitle_stream.config_mutex, NULL); } void bg_player_subtitle_destroy(bg_player_t * p) { gavl_video_converter_destroy(p->subtitle_stream.cnv); pthread_mutex_destroy(&p->subtitle_stream.config_mutex); bg_text_renderer_destroy(p->subtitle_stream.renderer); } int bg_player_subtitle_init(bg_player_t * player, int subtitle_stream) { bg_player_subtitle_stream_t * s; if(!DO_SUBTITLE(player->flags)) return 1; s = &player->subtitle_stream; bg_player_input_get_subtitle_format(player); if(DO_SUBTITLE_TEXT(player->flags)) { pthread_mutex_lock(&s->config_mutex); if(DO_SUBTITLE_ONLY(player->flags)) { bg_text_renderer_init(s->renderer, NULL, &player->subtitle_stream.input_format); bg_text_renderer_get_frame_format(player->subtitle_stream.renderer, &player->video_stream.input_format); gavl_video_format_copy(&player->video_stream.output_format, &player->video_stream.input_format); } else { bg_text_renderer_init(player->subtitle_stream.renderer, &player->video_stream.output_format, &player->subtitle_stream.input_format); } pthread_mutex_unlock(&player->subtitle_stream.config_mutex); } else { if(DO_SUBTITLE_ONLY(player->flags)) { gavl_video_format_copy(&player->video_stream.input_format, &player->subtitle_stream.input_format); gavl_video_format_copy(&player->video_stream.output_format, &player->video_stream.input_format); } } /* Initialize subtitle fifo */ if(!DO_SUBTITLE_ONLY(player->flags)) { /* Video output already initialized */ bg_player_ov_set_subtitle_format(&player->video_stream); bg_player_subtitle_init_converter(player); } return 1; } #define FREE_OVERLAY(ovl) if(ovl.frame) { gavl_video_frame_destroy(ovl.frame); ovl.frame = NULL; } void bg_player_subtitle_cleanup(bg_player_t * player) { FREE_OVERLAY(player->subtitle_stream.input_subtitle); } #undef FREE_OVERLAY /* Configuration stuff */ static bg_parameter_info_t general_parameters[] = { { .name = "general", .long_name = TRS("General"), .type = BG_PARAMETER_SECTION, }, { .name = "time_offset", .long_name = TRS("Time offset"), .flags = BG_PARAMETER_SYNC, .type = BG_PARAMETER_FLOAT, .val_min = { .val_f = -600.0 }, .val_max = { .val_f = 600.0 }, .num_digits = 3, }, { /* */ } }; const bg_parameter_info_t * bg_player_get_subtitle_parameters(bg_player_t * p) { if(!p->subtitle_stream.parameters) { const bg_parameter_info_t * info[3]; info[0] = general_parameters; info[1] = bg_text_renderer_get_parameters(); info[2] = NULL; p->subtitle_stream.parameters = bg_parameter_info_concat_arrays(info); } return p->subtitle_stream.parameters; } void bg_player_set_subtitle_parameter(void * data, const char * name, const bg_parameter_value_t * val) { bg_player_t * player = (bg_player_t*)data; if(!name) return; pthread_mutex_lock(&player->subtitle_stream.config_mutex); if(!strcmp(name, "time_offset")) { player->subtitle_stream.time_offset = (int64_t)(val->val_f * GAVL_TIME_SCALE + 0.5); } else bg_text_renderer_set_parameter(player->subtitle_stream.renderer, name, val); pthread_mutex_unlock(&player->subtitle_stream.config_mutex); } void bg_player_subtitle_init_converter(bg_player_t * player) { bg_player_subtitle_stream_t * s; s = &player->subtitle_stream; s->do_convert = gavl_video_converter_init(s->cnv, &s->input_format, &s->output_format); if(s->do_convert) s->input_subtitle.frame = gavl_video_frame_create(&s->input_format); } int bg_player_has_subtitle(bg_player_t * p) { int ret; bg_plugin_lock(p->input_handle); ret= p->input_plugin->has_subtitle(p->input_priv, p->current_subtitle_stream); bg_plugin_unlock(p->input_handle); return ret; } int bg_player_read_subtitle(bg_player_t * p, gavl_overlay_t * ovl) { gavl_time_t start, duration; bg_player_subtitle_stream_t * s = &p->subtitle_stream; if(DO_SUBTITLE_TEXT(p->flags)) { bg_plugin_lock(p->input_handle); if(!p->input_plugin->read_subtitle_text(p->input_priv, &s->buffer, &s->buffer_alloc, &start, &duration, p->current_subtitle_stream)) { bg_plugin_unlock(p->input_handle); return 0; } bg_plugin_unlock(p->input_handle); if(s->do_convert) { bg_text_renderer_render(s->renderer, s->buffer, &s->input_subtitle); gavl_video_convert(s->cnv, s->input_subtitle.frame, ovl->frame); gavl_rectangle_i_copy(&ovl->ovl_rect, &s->input_subtitle.ovl_rect); ovl->dst_x = s->input_subtitle.dst_x; ovl->dst_y = s->input_subtitle.dst_y; } else { bg_text_renderer_render(s->renderer, s->buffer, ovl); } ovl->frame->timestamp = start; ovl->frame->duration = duration; } else { if(s->do_convert) { bg_plugin_lock(p->input_handle); if(!p->input_plugin->read_subtitle_overlay(p->input_priv, &s->input_subtitle, p->current_subtitle_stream)) { bg_plugin_unlock(p->input_handle); return 0; } bg_plugin_unlock(p->input_handle); gavl_video_convert(s->cnv, s->input_subtitle.frame, ovl->frame); gavl_rectangle_i_copy(&ovl->ovl_rect, &s->input_subtitle.ovl_rect); ovl->dst_x = s->input_subtitle.dst_x; ovl->dst_y = s->input_subtitle.dst_y; } else { if(!p->input_plugin->read_subtitle_overlay(p->input_priv, ovl, p->current_subtitle_stream)) { return 0; } } } /* Unscale the overlay times */ ovl->frame->timestamp = gavl_time_unscale(s->input_format.timescale, ovl->frame->timestamp) + s->time_offset; ovl->frame->duration = gavl_time_unscale(s->input_format.timescale, ovl->frame->duration); #ifdef DUMP_SUBTITLE bg_dprintf("Got subtitle %f -> %f (%f)\n", gavl_time_to_seconds(ovl->frame->timestamp), gavl_time_to_seconds(ovl->frame->timestamp + ovl->frame->duration), gavl_time_to_seconds(ovl->frame->duration)); #endif return 1; } gmerlin-1.2.0~dfsg/lib/bglv.c0000644000175000017500000011274511764363410015754 0ustar alessioalessio/***************************************************************** * gmerlin - a general purpose multimedia framework and applications * * Copyright (c) 2001 - 2011 Members of the Gmerlin project * gmerlin-general@lists.sourceforge.net * http://gmerlin.sourceforge.net * * 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 of the License, 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 this program. If not, see . * *****************************************************************/ #include #include #include #include #include #include #include #include /* Fixme: for now, we assume, that X11 is always present... */ #include static int lv_initialized = 0; pthread_mutex_t lv_initialized_mutex = PTHREAD_MUTEX_INITIALIZER; static const int bg_attributes[VISUAL_GL_ATTRIBUTE_LAST] = { [VISUAL_GL_ATTRIBUTE_NONE] = -1, /**< No attribute. */ [VISUAL_GL_ATTRIBUTE_BUFFER_SIZE] = BG_GL_ATTRIBUTE_BUFFER_SIZE, [VISUAL_GL_ATTRIBUTE_LEVEL] = BG_GL_ATTRIBUTE_LEVEL, [VISUAL_GL_ATTRIBUTE_RGBA] = BG_GL_ATTRIBUTE_RGBA, [VISUAL_GL_ATTRIBUTE_DOUBLEBUFFER] = BG_GL_ATTRIBUTE_DOUBLEBUFFER, [VISUAL_GL_ATTRIBUTE_STEREO] = BG_GL_ATTRIBUTE_STEREO, [VISUAL_GL_ATTRIBUTE_AUX_BUFFERS] = BG_GL_ATTRIBUTE_AUX_BUFFERS, [VISUAL_GL_ATTRIBUTE_RED_SIZE] = BG_GL_ATTRIBUTE_RED_SIZE, [VISUAL_GL_ATTRIBUTE_GREEN_SIZE] = BG_GL_ATTRIBUTE_GREEN_SIZE, [VISUAL_GL_ATTRIBUTE_BLUE_SIZE] = BG_GL_ATTRIBUTE_BLUE_SIZE, [VISUAL_GL_ATTRIBUTE_ALPHA_SIZE] = BG_GL_ATTRIBUTE_ALPHA_SIZE, [VISUAL_GL_ATTRIBUTE_DEPTH_SIZE] = BG_GL_ATTRIBUTE_DEPTH_SIZE, [VISUAL_GL_ATTRIBUTE_STENCIL_SIZE] = BG_GL_ATTRIBUTE_STENCIL_SIZE, [VISUAL_GL_ATTRIBUTE_ACCUM_RED_SIZE] = BG_GL_ATTRIBUTE_ACCUM_RED_SIZE, [VISUAL_GL_ATTRIBUTE_ACCUM_GREEN_SIZE] = BG_GL_ATTRIBUTE_ACCUM_GREEN_SIZE, [VISUAL_GL_ATTRIBUTE_ACCUM_BLUE_SIZE] = BG_GL_ATTRIBUTE_ACCUM_BLUE_SIZE, [VISUAL_GL_ATTRIBUTE_ACCUM_ALPHA_SIZE] = BG_GL_ATTRIBUTE_ACCUM_ALPHA_SIZE, }; #define SAMPLES_PER_FRAME 512 static int key_callback(void * data, int key, int mask); static int key_release_callback(void * data, int key, int mask); static int motion_callback(void * data, int x, int y, int mask); static int button_callback(void * data, int x, int y, int button, int mask); static int button_release_callback(void * data, int x, int y, int button, int mask); static void log_error(const char *message, const char *funcname, void *priv) { char * domain; domain = bg_sprintf("lv.%s", funcname); bg_log_notranslate(BG_LOG_ERROR, domain, "%s", message); free(domain); } static void log_info(const char *message, const char *funcname, void *priv) { char * domain; domain = bg_sprintf("lv.%s", funcname); bg_log_notranslate(BG_LOG_INFO, domain, "%s", message); free(domain); } static void log_warning(const char *message, const char *funcname, void *priv) { char * domain; domain = bg_sprintf("lv.%s", funcname); bg_log_notranslate(BG_LOG_WARNING, domain, "%s", message); free(domain); } static void check_init() { char * argv = { "libgmerlin" }; char ** argvp = &argv; int argc = 1; pthread_mutex_lock(&lv_initialized_mutex); if(lv_initialized) { pthread_mutex_unlock(&lv_initialized_mutex); return; } /* Initialize the library */ visual_init(&argc, &argvp); /* Set the log callbacks */ visual_log_set_info_handler(log_info, NULL); visual_log_set_warning_handler(log_warning, NULL); visual_log_set_critical_handler(log_warning, NULL); visual_log_set_error_handler(log_error, NULL); lv_initialized = 1; pthread_mutex_unlock(&lv_initialized_mutex); } static VisUIWidget * check_widget(VisUIWidget * w, const char * name, bg_parameter_info_t * info) { VisUIWidget * ret = NULL; int i; int num_items; VisListEntry * list_entry; switch(w->type) { case VISUAL_WIDGET_TYPE_RANGE: /**< Range base widget: \a VisUIRange. */ case VISUAL_WIDGET_TYPE_ENTRY: /**< Entry box widget: \a VisUIEntry. */ case VISUAL_WIDGET_TYPE_MUTATOR: /**< Mutator base widget: \a VisUIMutator. */ case VISUAL_WIDGET_TYPE_NULL: /**< NULL widget */ case VISUAL_WIDGET_TYPE_WIDGET: /**< Base widget: \a VisUIWidget. */ case VISUAL_WIDGET_TYPE_LABEL: /**< Label widget: \a VisUILabel. */ case VISUAL_WIDGET_TYPE_IMAGE: /**< Image widget: \a VisUIImage. */ case VISUAL_WIDGET_TYPE_SEPARATOR: /**< Separator widget: \a VisUISeparator. */ case VISUAL_WIDGET_TYPE_COLORPALETTE:/**< Color palette widget: \a VisUIColorPalette. */ case VISUAL_WIDGET_TYPE_CHOICE: /**< Choice base widget: \a VisUIChoice. */ break; case VISUAL_WIDGET_TYPE_CONTAINER: /**< Container widget: \a VisUIContainer. */ case VISUAL_WIDGET_TYPE_FRAME: /**< Frame widget: \a VisUIFrame. */ /* Get child */ return check_widget(VISUAL_UI_CONTAINER(w)->child, name, info); break; case VISUAL_WIDGET_TYPE_BOX: /**< Box widget: \a VisUIBox. */ /* Get children */ list_entry = NULL; while(visual_list_next(&VISUAL_UI_BOX(w)->childs, &list_entry)) { if((ret = check_widget(list_entry->data, name, info))) return ret; } break; case VISUAL_WIDGET_TYPE_TABLE: /**< Table widget: \a VisUITable. */ /* Get children */ list_entry = NULL; while(visual_list_next(&VISUAL_UI_TABLE(w)->childs, &list_entry)) { if((ret = check_widget(((VisUITableEntry*)list_entry->data)->widget, name, info))) { return ret; } } break; case VISUAL_WIDGET_TYPE_NOTEBOOK: /**< Notebook widget: \a VisUINotebook. */ /* Get children */ /* Get children */ list_entry = NULL; while(visual_list_next(&VISUAL_UI_NOTEBOOK(w)->childs, &list_entry)) { if((ret = check_widget(list_entry->data, name, info))) return ret; } break; case VISUAL_WIDGET_TYPE_SLIDER: /**< Slider widget: \a VisUISlider. */ if(strcmp(name, VISUAL_UI_MUTATOR(w)->param->name)) return 0; if((VISUAL_UI_MUTATOR(w)->param->type == VISUAL_PARAM_ENTRY_TYPE_FLOAT) || (VISUAL_UI_MUTATOR(w)->param->type == VISUAL_PARAM_ENTRY_TYPE_DOUBLE)) { info->type = BG_PARAMETER_SLIDER_FLOAT; info->val_min.val_f = VISUAL_UI_RANGE(w)->min; info->val_max.val_f = VISUAL_UI_RANGE(w)->max; info->num_digits = VISUAL_UI_RANGE(w)->precision; if((VISUAL_UI_MUTATOR(w)->param->type == VISUAL_PARAM_ENTRY_TYPE_FLOAT)) info->val_default.val_f = VISUAL_UI_MUTATOR(w)->param->numeric.floating; else info->val_default.val_f = VISUAL_UI_MUTATOR(w)->param->numeric.doubleflt; } else { info->type = BG_PARAMETER_SLIDER_INT; info->val_min.val_i = (int)VISUAL_UI_RANGE(w)->min; info->val_max.val_i = (int)VISUAL_UI_RANGE(w)->max; info->val_default.val_i = VISUAL_UI_MUTATOR(w)->param->numeric.integer; } info->flags |= BG_PARAMETER_SYNC; ret = w; break; case VISUAL_WIDGET_TYPE_NUMERIC: /**< Numeric widget: \a VisUINumeric. */ if(strcmp(name, VISUAL_UI_MUTATOR(w)->param->name)) return 0; if((VISUAL_UI_MUTATOR(w)->param->type == VISUAL_PARAM_ENTRY_TYPE_FLOAT) || (VISUAL_UI_MUTATOR(w)->param->type == VISUAL_PARAM_ENTRY_TYPE_DOUBLE)) { info->type = BG_PARAMETER_FLOAT; info->val_min.val_f = VISUAL_UI_RANGE(w)->min; info->val_max.val_f = VISUAL_UI_RANGE(w)->max; info->num_digits = VISUAL_UI_RANGE(w)->precision; if((VISUAL_UI_MUTATOR(w)->param->type == VISUAL_PARAM_ENTRY_TYPE_FLOAT)) info->val_default.val_f = VISUAL_UI_MUTATOR(w)->param->numeric.floating; else info->val_default.val_f = VISUAL_UI_MUTATOR(w)->param->numeric.doubleflt; } else { info->type = BG_PARAMETER_INT; info->val_min.val_i = (int)VISUAL_UI_RANGE(w)->min; info->val_max.val_i = (int)VISUAL_UI_RANGE(w)->max; info->val_default.val_i = VISUAL_UI_MUTATOR(w)->param->numeric.integer; } info->flags |= BG_PARAMETER_SYNC; ret = w; break; case VISUAL_WIDGET_TYPE_COLOR: /**< Color widget: \a VisUIColor. */ case VISUAL_WIDGET_TYPE_COLORBUTTON: /**< Color button widget: \a VisUIColorButton. */ if(strcmp(name, VISUAL_UI_MUTATOR(w)->param->name)) return 0; info->type = BG_PARAMETER_COLOR_RGB; info->flags |= BG_PARAMETER_SYNC; info->val_default.val_color[0] = (float)VISUAL_UI_MUTATOR(w)->param->color.r / 255.0; info->val_default.val_color[1] = (float)VISUAL_UI_MUTATOR(w)->param->color.g / 255.0; info->val_default.val_color[2] = (float)VISUAL_UI_MUTATOR(w)->param->color.b / 255.0; ret = w; break; case VISUAL_WIDGET_TYPE_POPUP: /**< Popup widget: \a VisUIPopup. */ case VISUAL_WIDGET_TYPE_LIST: /**< List widget: \a VisUIList. */ case VISUAL_WIDGET_TYPE_RADIO: /**< Radio widget: \a VisUIRadio. */ if(strcmp(name, VISUAL_UI_MUTATOR(w)->param->name)) return 0; info->type = BG_PARAMETER_STRINGLIST; info->flags |= BG_PARAMETER_SYNC; num_items = 0; list_entry = NULL; while(visual_list_next(&VISUAL_UI_CHOICE(w)->choices.choices, &list_entry)) num_items++; info->multi_names_nc = calloc(num_items+1, sizeof(info->multi_names_nc)); list_entry = NULL; for(i = 0; i < num_items; i++) { visual_list_next(&VISUAL_UI_CHOICE(w)->choices.choices, &list_entry); info->multi_names_nc[i] = bg_strdup(NULL, ((VisUIChoiceEntry*)(list_entry->data))->name); /* Check if this is the current value */ // visual_param_entry_compare(((VisUIChoiceEntry*)(list_entry->data))->value, // VISUAL_UI_MUTATOR(w)->param) if(!i) { info->val_default.val_str = bg_strdup(NULL, info->multi_names_nc[i]); } } ret = w; break; case VISUAL_WIDGET_TYPE_CHECKBOX: /**< Checkbox widget: \a VisUICheckbox. */ if(strcmp(name, VISUAL_UI_MUTATOR(w)->param->name)) return 0; info->type = BG_PARAMETER_CHECKBUTTON; info->flags |= BG_PARAMETER_SYNC; ret = w; break; } if(ret) info->help_string = bg_strdup(info->help_string, w->tooltip); bg_parameter_info_set_const_ptrs(info); return ret; } static bg_parameter_info_t * create_parameters(VisActor * actor, VisUIWidget *** widgets, VisParamEntry *** params_ret) { int num_parameters, i, index, supported; bg_parameter_info_t * ret; VisParamContainer * params; // VisHashmapChainEntry *entry; VisParamEntry *param_entry; VisListEntry * list_entry; VisUIWidget * widget; VisUIWidget * param_widget; params = visual_plugin_get_params(visual_actor_get_plugin(actor)); /* Count parameters */ num_parameters = 0; list_entry = NULL; while(visual_list_next(¶ms->entries, &list_entry)) num_parameters++; if(!num_parameters) return NULL; /* Create parameters */ ret = calloc(num_parameters+1, sizeof(*ret)); if(widgets) *widgets = calloc(num_parameters, sizeof(**widgets)); if(params_ret) *params_ret = calloc(num_parameters, sizeof(**params_ret)); list_entry = NULL; index = 0; widget = visual_plugin_get_userinterface(visual_actor_get_plugin(actor)); for(i = 0; i < num_parameters; i++) { visual_list_next(¶ms->entries, &list_entry); param_entry = list_entry->data; // param_entry = VISUAL_PARAMENTRY(entry->data); if(params_ret) (*params_ret)[index] = param_entry; supported = 1; if(widget) param_widget = check_widget(widget, param_entry->name, &ret[index]); else param_widget = NULL; if(!param_widget) { switch(param_entry->type) { case VISUAL_PARAM_ENTRY_TYPE_NULL: /**< No parameter. */ supported = 0; break; case VISUAL_PARAM_ENTRY_TYPE_STRING: /**< String parameter. */ ret[index].type = BG_PARAMETER_STRING; ret[index].val_default.val_str = bg_strdup(ret[index].val_default.val_str, param_entry->string); break; case VISUAL_PARAM_ENTRY_TYPE_INTEGER: /**< Integer parameter. */ ret[index].type = BG_PARAMETER_INT; ret[index].flags |= BG_PARAMETER_SYNC; ret[index].val_default.val_i = param_entry->numeric.integer; break; case VISUAL_PARAM_ENTRY_TYPE_FLOAT: /**< Floating point parameter. */ ret[index].type = BG_PARAMETER_FLOAT; ret[index].flags |= BG_PARAMETER_SYNC; ret[index].val_default.val_f = param_entry->numeric.floating; break; case VISUAL_PARAM_ENTRY_TYPE_DOUBLE: /**< Double floating point parameter. */ ret[index].type = BG_PARAMETER_FLOAT; ret[index].flags |= BG_PARAMETER_SYNC; ret[index].val_default.val_f = param_entry->numeric.doubleflt; break; case VISUAL_PARAM_ENTRY_TYPE_COLOR: /**< VisColor parameter. */ ret[index].type = BG_PARAMETER_COLOR_RGB; ret[index].flags |= BG_PARAMETER_SYNC; ret[index].val_default.val_color[0] = (float)param_entry->color.r / 255.0; ret[index].val_default.val_color[1] = (float)param_entry->color.g / 255.0; ret[index].val_default.val_color[2] = (float)param_entry->color.b / 255.0; break; case VISUAL_PARAM_ENTRY_TYPE_PALETTE: /**< VisPalette parameter. */ case VISUAL_PARAM_ENTRY_TYPE_OBJECT: /**< VisObject parameter. */ case VISUAL_PARAM_ENTRY_TYPE_END: /**< List end, and used as terminator for VisParamEntry lists. */ supported = 0; break; } } if(widgets) (*widgets)[index] = param_widget; if(!supported) continue; ret[index].name = bg_strdup(NULL, param_entry->name); ret[index].long_name = bg_strdup(NULL, param_entry->name); index++; } return ret; } bg_plugin_info_t * bg_lv_get_info(const char * filename) { int i; VisVideoAttributeOptions *vidoptions; bg_x11_window_t * win; bg_plugin_info_t * ret; VisPluginRef * ref; VisList * list; VisActor * actor; VisPluginInfo * info; char * tmp_string; const char * actor_name = NULL; check_init(); list = visual_plugin_get_registry(); /* Find out if there is a plugin matching the filename */ while((actor_name = visual_actor_get_next_by_name(actor_name))) { ref = visual_plugin_find(list, actor_name); if(ref && !strcmp(ref->file, filename)) break; } if(!actor_name) return NULL; actor = visual_actor_new(actor_name); if(!actor) return NULL; ret = calloc(1, sizeof(*ret)); info = visual_plugin_get_info(visual_actor_get_plugin(actor)); ret->name = bg_sprintf("vis_lv_%s", actor_name); ret->long_name = bg_strdup(NULL, info->name); ret->type = BG_PLUGIN_VISUALIZATION; ret->api = BG_PLUGIN_API_LV; ret->description = bg_sprintf(TR("libvisual plugin")); ret->module_filename = bg_strdup(NULL, filename); /* Optional info */ if(info->author && *info->author) { tmp_string = bg_sprintf(TR("\nAuthor: %s"), info->author); ret->description = bg_strcat(ret->description, tmp_string); free(tmp_string); } if(info->version && *info->version) { tmp_string = bg_sprintf(TR("\nVersion: %s"), info->version); ret->description = bg_strcat(ret->description, tmp_string); free(tmp_string); } if(info->about && *info->about) { tmp_string = bg_sprintf(TR("\nAbout: %s"), info->about); ret->description = bg_strcat(ret->description, tmp_string); free(tmp_string); } if(info->help && *info->help) { tmp_string = bg_sprintf(TR("\nHelp: %s"), info->help); ret->description = bg_strcat(ret->description, tmp_string); free(tmp_string); } if(info->license && *info->license) { tmp_string = bg_sprintf(TR("\nLicense: %s"), info->license); ret->description = bg_strcat(ret->description, tmp_string); free(tmp_string); } /* Check out if it's an OpenGL plugin */ if(visual_actor_get_supported_depth(actor) & VISUAL_VIDEO_DEPTH_GL) { ret->flags |= BG_PLUGIN_VISUALIZE_GL; win = bg_x11_window_create(NULL); /* Create an OpenGL context. For this, we need the OpenGL attributes */ vidoptions = visual_actor_get_video_attribute_options(actor); for(i = 0; i < VISUAL_GL_ATTRIBUTE_LAST; i++) { if((vidoptions->gl_attributes[i].mutated) && (bg_attributes[i] >= 0)) { bg_x11_window_set_gl_attribute(win, bg_attributes[i], vidoptions->gl_attributes[i].value); } } /* Set bogus dimensions, will be corrected by the size_callback */ bg_x11_window_set_size(win, 640, 480); bg_x11_window_realize(win); if(!bg_x11_window_start_gl(win)) { ret->flags |= BG_PLUGIN_UNSUPPORTED; } else bg_x11_window_set_gl(win); } else { ret->flags |= BG_PLUGIN_VISUALIZE_FRAME; win = NULL; } ret->priority = 1; /* Must realize the actor to get the parameters */ if(!(ret->flags & BG_PLUGIN_UNSUPPORTED)) { visual_actor_realize(actor); ret->parameters = create_parameters(actor, NULL, NULL); visual_object_unref(VISUAL_OBJECT(actor)); } if(win) { bg_x11_window_unset_gl(win); bg_x11_window_stop_gl(win); bg_x11_window_destroy(win); } return ret; } /* Private structure */ typedef struct { int gl; VisActor * actor; VisVideo * video; VisAudio * audio; gavl_audio_format_t audio_format; /* OpenGL */ bg_x11_window_t * win; bg_x11_window_callbacks_t window_callbacks; bg_parameter_info_t * parameters; VisUIWidget ** widgets; VisParamEntry ** params; bg_ov_callbacks_t * ov_callbacks; int have_audio; } lv_priv_t; static void set_callbacks_lv(void * data, bg_ov_callbacks_t * cb) { lv_priv_t * priv; priv = (lv_priv_t*)data; priv->ov_callbacks = cb; } static void draw_frame_gl_lv(void * data, gavl_video_frame_t * frame) { lv_priv_t * priv; priv = (lv_priv_t*)data; bg_x11_window_set_gl(priv->win); visual_actor_run(priv->actor, priv->audio); bg_x11_window_unset_gl(priv->win); priv->have_audio = 0; } static void draw_frame_ov_lv(void * data, gavl_video_frame_t * frame) { lv_priv_t * priv; priv = (lv_priv_t*)data; visual_video_set_buffer(priv->video, frame->planes[0]); visual_video_set_pitch(priv->video, frame->strides[0]); visual_actor_run(priv->actor, priv->audio); priv->have_audio = 0; } static void update_lv(void * data, gavl_audio_frame_t * frame) { lv_priv_t * priv; VisBuffer buffer; priv = (lv_priv_t*)data; visual_buffer_init(&buffer, frame->samples.s_16, frame->valid_samples * 2, NULL); visual_audio_samplepool_input(priv->audio->samplepool, &buffer, VISUAL_AUDIO_SAMPLE_RATE_44100, VISUAL_AUDIO_SAMPLE_FORMAT_S16, VISUAL_AUDIO_SAMPLE_CHANNEL_STEREO); visual_audio_analyze(priv->audio); } static void close_lv(void * data) { lv_priv_t * priv; priv = (lv_priv_t*)data; // if(priv->win) // bg_x11_window_show(priv->win, 0); } static void adjust_audio_format(gavl_audio_format_t * f) { f->num_channels = 2; f->channel_locations[0] = GAVL_CHID_NONE; gavl_set_channel_setup(f); f->interleave_mode = GAVL_INTERLEAVE_ALL; f->sample_format = GAVL_SAMPLE_S16; f->samples_per_frame = SAMPLES_PER_FRAME; } static int open_ov_lv(void * data, gavl_audio_format_t * audio_format, gavl_video_format_t * video_format) { int depths, depth; lv_priv_t * priv; priv = (lv_priv_t*)data; adjust_audio_format(audio_format); /* Get the depth */ depths = visual_actor_get_supported_depth(priv->actor); if(depths & VISUAL_VIDEO_DEPTH_32BIT) /**< 32 bits surface flag. */ { video_format->pixelformat = GAVL_BGR_32; depth = VISUAL_VIDEO_DEPTH_32BIT; } else if(depths & VISUAL_VIDEO_DEPTH_24BIT) /**< 24 bits surface flag. */ { video_format->pixelformat = GAVL_BGR_24; depth = VISUAL_VIDEO_DEPTH_24BIT; } else if(depths & VISUAL_VIDEO_DEPTH_16BIT) /**< 16 bits 5-6-5 surface flag. */ { video_format->pixelformat = GAVL_RGB_16; depth = VISUAL_VIDEO_DEPTH_16BIT; } else if(depths & VISUAL_VIDEO_DEPTH_8BIT) /**< 8 bits indexed surface flag. */ { video_format->pixelformat = GAVL_BGR_24; depth = VISUAL_VIDEO_DEPTH_24BIT; } else return 0; visual_video_set_depth(priv->video, depth); visual_video_set_dimension(priv->video, video_format->image_width, video_format->image_height); visual_actor_set_video(priv->actor, priv->video); visual_actor_video_negotiate(priv->actor, 0, FALSE, FALSE); return 1; } static void size_changed(void * data, int width, int height) { lv_priv_t * priv; priv = (lv_priv_t*)data; visual_video_set_dimension(priv->video, width, height); visual_actor_set_video(priv->actor, priv->video); visual_actor_video_negotiate(priv->actor, 0, FALSE, FALSE); } static int open_gl_lv(void * data, gavl_audio_format_t * audio_format, const char * window_id) { int width, height; lv_priv_t * priv; priv = (lv_priv_t*)data; visual_video_set_depth(priv->video, VISUAL_VIDEO_DEPTH_GL); adjust_audio_format(audio_format); gavl_audio_format_copy(&priv->audio_format, audio_format); bg_x11_window_set_gl(priv->win); visual_actor_set_video(priv->actor, priv->video); bg_x11_window_unset_gl(priv->win); /* Set the size changed callback after initializing the libvisual stuff */ bg_x11_window_set_callbacks(priv->win, &priv->window_callbacks); bg_x11_window_show(priv->win, 1); bg_x11_window_set_gl(priv->win); bg_x11_window_get_size(priv->win, &width, &height); /* We cannot use the size callback above since it's called before the actor is realized */ visual_video_set_dimension(priv->video, width, height); visual_actor_video_negotiate(priv->actor, 0, FALSE, FALSE); bg_x11_window_unset_gl(priv->win); return 1; } static void show_frame_lv(void * data) { lv_priv_t * priv; priv = (lv_priv_t*)data; bg_x11_window_set_gl(priv->win); bg_x11_window_swap_gl(priv->win); bg_x11_window_handle_events(priv->win, 0); bg_x11_window_unset_gl(priv->win); } static const bg_parameter_info_t * get_parameters_lv(void * data) { lv_priv_t * priv; priv = (lv_priv_t*)data; return priv->parameters; } static void set_parameter_lv(void * data, const char * name, const bg_parameter_value_t * val) { int supported; lv_priv_t * priv; int index; int i_tmp; uint8_t r, g, b; char * tmp_string; VisParamEntry * param; VisListEntry * list_entry; VisColor * color; const bg_parameter_info_t * info; if(!name) return; priv = (lv_priv_t*)data; info = bg_parameter_find(priv->parameters, name); if(!info) return; /* This would crash if multi_parameters were supported */ index = info - priv->parameters; tmp_string = bg_strdup(NULL, name); param = visual_param_entry_new(tmp_string); free(tmp_string); /* Menus have to be treated specially */ if(info->type == BG_PARAMETER_STRINGLIST) { if(!priv->widgets[index]) return; /* Get the selected index */ supported = 0; list_entry = NULL; while(visual_list_next(&VISUAL_UI_CHOICE(priv->widgets[index])->choices.choices, &list_entry)) { if(!strcmp(((VisUIChoiceEntry*)(list_entry->data))->name, val->val_str)) { visual_param_entry_set_from_param(param, ((VisUIChoiceEntry*)(list_entry->data))->value); supported = 1; break; } } } else { supported = 1; switch(priv->params[index]->type) { case VISUAL_PARAM_ENTRY_TYPE_NULL: /**< No parameter. */ supported = 0; break; case VISUAL_PARAM_ENTRY_TYPE_STRING: /**< String parameter. */ if(val->val_str) visual_param_entry_set_string(param, val->val_str); else supported = 0; break; case VISUAL_PARAM_ENTRY_TYPE_INTEGER: /**< Integer parameter. */ visual_param_entry_set_integer(param, val->val_i); break; case VISUAL_PARAM_ENTRY_TYPE_FLOAT: /**< Floating point parameter. */ visual_param_entry_set_float(param, val->val_f); break; case VISUAL_PARAM_ENTRY_TYPE_DOUBLE: /**< Double floating point parameter. */ visual_param_entry_set_double(param, val->val_f); break; case VISUAL_PARAM_ENTRY_TYPE_COLOR: /**< VisColor parameter. */ i_tmp = (int)(val->val_color[0] * 255.0 + 0.5); if(i_tmp < 0) i_tmp = 0; if(i_tmp > 255) i_tmp = 255; r = i_tmp; i_tmp = (int)(val->val_color[1] * 255.0 + 0.5); if(i_tmp < 0) i_tmp = 0; if(i_tmp > 255) i_tmp = 255; g = i_tmp; i_tmp = (int)(val->val_color[2] * 255.0 + 0.5); if(i_tmp < 0) i_tmp = 0; if(i_tmp > 255) i_tmp = 255; b = i_tmp; color = visual_color_new(); visual_color_set(color, r, g, b); visual_param_entry_set_color_by_color(param, color); visual_object_unref(VISUAL_OBJECT(color)); break; case VISUAL_PARAM_ENTRY_TYPE_PALETTE: /**< VisPalette parameter. */ case VISUAL_PARAM_ENTRY_TYPE_OBJECT: /**< VisObject parameter. */ case VISUAL_PARAM_ENTRY_TYPE_END: /**< List end, and used as terminator for VisParamEntry lists. */ supported = 0; break; } } if(supported) { visual_event_queue_add_param(visual_plugin_get_eventqueue(visual_actor_get_plugin(priv->actor)), param); } else visual_object_unref(VISUAL_OBJECT(param)); } /* High level load/unload */ int bg_lv_load(bg_plugin_handle_t * ret, const char * name, int plugin_flags, const char * window_id) { lv_priv_t * priv; int i; bg_visualization_plugin_t * p; VisVideoAttributeOptions *vidoptions; check_init(); /* Set up callbacks */ p = calloc(1, sizeof(*p)); ret->plugin_nc = (bg_plugin_common_t*)p; ret->plugin = ret->plugin_nc; if(plugin_flags & BG_PLUGIN_VISUALIZE_GL) { p->open_win = open_gl_lv; p->draw_frame = draw_frame_gl_lv; p->show_frame = show_frame_lv; } else { p->open_ov = open_ov_lv; p->draw_frame = draw_frame_ov_lv; } p->update = update_lv; p->close = close_lv; p->set_callbacks = set_callbacks_lv; p->common.get_parameters = get_parameters_lv; p->common.set_parameter = set_parameter_lv; /* Set up private data */ priv = calloc(1, sizeof(*priv)); ret->priv = priv; priv->audio = visual_audio_new(); #if 0 priv->ov_callbacks.data = priv; priv->ov_callbacks.key_callback = key_callback; priv->ov_callbacks.key_release_callback = key_release_callback; priv->ov_callbacks.button_callback = button_callback; priv->ov_callbacks.button_release_callback = button_release_callback; priv->ov_callbacks.motion_callback = motion_callback; #endif /* Remove gmerlin added prefix from the plugin name */ priv->actor = visual_actor_new(name + 7); if(plugin_flags & BG_PLUGIN_VISUALIZE_GL) { priv->win = bg_x11_window_create(window_id); priv->window_callbacks.data = priv; priv->window_callbacks.size_changed = size_changed; priv->window_callbacks.key_callback = key_callback; priv->window_callbacks.key_release_callback = key_release_callback; priv->window_callbacks.button_callback = button_callback; priv->window_callbacks.button_release_callback = button_release_callback; priv->window_callbacks.motion_callback = motion_callback; /* Create an OpenGL context. For this, we need the OpenGL attributes */ vidoptions = visual_actor_get_video_attribute_options(priv->actor); for(i = 0; i < VISUAL_GL_ATTRIBUTE_LAST; i++) { if((vidoptions->gl_attributes[i].mutated) && (bg_attributes[i] >= 0)) { bg_x11_window_set_gl_attribute(priv->win, bg_attributes[i], vidoptions->gl_attributes[i].value); } } /* Set bogus dimensions, will be corrected by the size_callback */ bg_x11_window_set_size(priv->win, 640, 480); bg_x11_window_realize(priv->win); bg_x11_window_start_gl(priv->win); bg_x11_window_set_gl(priv->win); } visual_actor_realize(priv->actor); if(plugin_flags & BG_PLUGIN_VISUALIZE_GL) bg_x11_window_unset_gl(priv->win); priv->parameters = create_parameters(priv->actor, &priv->widgets, &priv->params); priv->video = visual_video_new(); return 1; } void bg_lv_unload(bg_plugin_handle_t * h) { lv_priv_t * priv; check_init(); priv = (lv_priv_t *)(h->priv); if(priv->win) bg_x11_window_set_gl(priv->win); visual_object_unref(VISUAL_OBJECT(priv->audio)); visual_object_unref(VISUAL_OBJECT(priv->video)); visual_object_unref(VISUAL_OBJECT(priv->actor)); if(priv->win) { bg_x11_window_unset_gl(priv->win); bg_x11_window_stop_gl(priv->win); bg_x11_window_destroy(priv->win); } free(h->plugin_nc); free(priv); } /* Callbacks */ static const struct { int bg_code; VisKey lv_code; VisKeyState state; } keycodes[] = { { BG_KEY_0, VKEY_0 }, //!< 0 { BG_KEY_1, VKEY_1 }, //!< 1 { BG_KEY_2, VKEY_2 }, //!< 2 { BG_KEY_3, VKEY_3 }, //!< 3 { BG_KEY_4, VKEY_4 }, //!< 4 { BG_KEY_5, VKEY_5 }, //!< 5 { BG_KEY_6, VKEY_6 }, //!< 6 { BG_KEY_7, VKEY_7 }, //!< 7 { BG_KEY_8, VKEY_8 }, //!< 8 { BG_KEY_9, VKEY_9 }, //!< 9 { BG_KEY_SPACE, VKEY_SPACE }, //!< Space { BG_KEY_RETURN, VKEY_RETURN }, //!< Return (Enter) { BG_KEY_LEFT, VKEY_LEFT }, //!< Left { BG_KEY_RIGHT, VKEY_RIGHT }, //!< Right { BG_KEY_UP, VKEY_UP }, //!< Up { BG_KEY_DOWN, VKEY_DOWN }, //!< Down { BG_KEY_PAGE_UP, VKEY_PAGEUP }, //!< Page Up { BG_KEY_PAGE_DOWN, VKEY_PAGEDOWN }, //!< Page Down { BG_KEY_HOME, VKEY_HOME }, //!< Page Down { BG_KEY_PLUS, VKEY_PLUS }, //!< Plus { BG_KEY_MINUS, VKEY_MINUS }, //!< Minus { BG_KEY_TAB, VKEY_TAB }, //!< Tab { BG_KEY_ESCAPE, VKEY_ESCAPE }, //!< Esc { BG_KEY_MENU, VKEY_MENU }, //!< Menu key { BG_KEY_QUESTION, VKEY_QUESTION }, //!< ? { BG_KEY_EXCLAM, VKEY_EXCLAIM }, //!< ! { BG_KEY_QUOTEDBL, VKEY_QUOTEDBL }, //!< " { BG_KEY_DOLLAR, VKEY_DOLLAR },//!< $ // { BG_KEY_PERCENT, }, //!< % { BG_KEY_APMERSAND, VKEY_AMPERSAND }, //!< & { BG_KEY_SLASH, VKEY_SLASH },//!< / { BG_KEY_LEFTPAREN, VKEY_LEFTPAREN },//!< ( { BG_KEY_RIGHTPAREN, VKEY_RIGHTPAREN }, //!< ) { BG_KEY_EQUAL, VKEY_EQUALS }, //!< = { BG_KEY_BACKSLASH, VKEY_BACKSLASH },//!< :-) { BG_KEY_A, VKEY_a, VKMOD_SHIFT },//!< A { BG_KEY_B, VKEY_b, VKMOD_SHIFT },//!< B { BG_KEY_C, VKEY_c, VKMOD_SHIFT },//!< C { BG_KEY_D, VKEY_d, VKMOD_SHIFT },//!< D { BG_KEY_E, VKEY_e, VKMOD_SHIFT },//!< E { BG_KEY_F, VKEY_f, VKMOD_SHIFT },//!< F { BG_KEY_G, VKEY_g, VKMOD_SHIFT },//!< G { BG_KEY_H, VKEY_h, VKMOD_SHIFT },//!< H { BG_KEY_I, VKEY_i, VKMOD_SHIFT },//!< I { BG_KEY_J, VKEY_j, VKMOD_SHIFT },//!< J { BG_KEY_K, VKEY_k, VKMOD_SHIFT },//!< K { BG_KEY_L, VKEY_l, VKMOD_SHIFT },//!< L { BG_KEY_M, VKEY_m, VKMOD_SHIFT },//!< M { BG_KEY_N, VKEY_n, VKMOD_SHIFT },//!< N { BG_KEY_O, VKEY_o, VKMOD_SHIFT },//!< O { BG_KEY_P, VKEY_p, VKMOD_SHIFT },//!< P { BG_KEY_Q, VKEY_q, VKMOD_SHIFT },//!< Q { BG_KEY_R, VKEY_r, VKMOD_SHIFT },//!< R { BG_KEY_S, VKEY_s, VKMOD_SHIFT },//!< S { BG_KEY_T, VKEY_t, VKMOD_SHIFT },//!< T { BG_KEY_U, VKEY_u, VKMOD_SHIFT },//!< U { BG_KEY_V, VKEY_v, VKMOD_SHIFT },//!< V { BG_KEY_W, VKEY_w, VKMOD_SHIFT },//!< W { BG_KEY_X, VKEY_x, VKMOD_SHIFT },//!< X { BG_KEY_Y, VKEY_y, VKMOD_SHIFT },//!< Y { BG_KEY_Z, VKEY_z, VKMOD_SHIFT },//!< Z { BG_KEY_a, VKEY_a },//!< a { BG_KEY_b, VKEY_b },//!< b { BG_KEY_c, VKEY_c },//!< c { BG_KEY_d, VKEY_d },//!< d { BG_KEY_e, VKEY_e },//!< e { BG_KEY_f, VKEY_f },//!< f { BG_KEY_g, VKEY_g },//!< g { BG_KEY_h, VKEY_h },//!< h { BG_KEY_i, VKEY_i },//!< i { BG_KEY_j, VKEY_j },//!< j { BG_KEY_k, VKEY_k },//!< k { BG_KEY_l, VKEY_l },//!< l { BG_KEY_m, VKEY_m },//!< m { BG_KEY_n, VKEY_n },//!< n { BG_KEY_o, VKEY_o },//!< o { BG_KEY_p, VKEY_p },//!< p { BG_KEY_q, VKEY_q },//!< q { BG_KEY_r, VKEY_r },//!< r { BG_KEY_s, VKEY_s },//!< s { BG_KEY_t, VKEY_t },//!< t { BG_KEY_u, VKEY_u },//!< u { BG_KEY_v, VKEY_v },//!< v { BG_KEY_w, VKEY_w },//!< w { BG_KEY_x, VKEY_x },//!< x { BG_KEY_y, VKEY_y },//!< y { BG_KEY_z, VKEY_z },//!< z { BG_KEY_F1, VKEY_F1 },//!< F1 { BG_KEY_F2, VKEY_F2 },//!< F2 { BG_KEY_F3, VKEY_F3 },//!< F3 { BG_KEY_F4, VKEY_F3 },//!< F4 { BG_KEY_F5, VKEY_F5 },//!< F5 { BG_KEY_F6, VKEY_F6 },//!< F6 { BG_KEY_F7, VKEY_F7 },//!< F7 { BG_KEY_F8, VKEY_F8 },//!< F8 { BG_KEY_F9, VKEY_F9 },//!< F9 { BG_KEY_F10, VKEY_F10 },//!< F10 { BG_KEY_F11, VKEY_F11 },//!< F11 { BG_KEY_F12, VKEY_F12 },//!< F12 }; static int get_key_mask(int bg_mask) { int ret = 0; if(bg_mask & BG_KEY_SHIFT_MASK) ret |= VKMOD_SHIFT; if(bg_mask & BG_KEY_CONTROL_MASK) ret |= VKMOD_CTRL; if(bg_mask & BG_KEY_ALT_MASK) ret |= VKMOD_ALT; return ret; } static int get_key_code(int bg_code, int bg_mask, int * lv_code, int * lv_mask) { int i; *lv_mask = get_key_mask(bg_mask); for(i = 0; i < sizeof(keycodes) / sizeof(keycodes[0]); i++) { if(bg_code == keycodes[i].bg_code) { *lv_mask |= keycodes[i].state; *lv_code = keycodes[i].lv_code; return 1; } } return 0; } static int key_callback(void * data, int key, int mask) { VisEventQueue *eventqueue; int lv_key, lv_mask; lv_priv_t * priv = (lv_priv_t*)data; if(!get_key_code(key, mask, &lv_key, &lv_mask)) return 0; eventqueue = visual_plugin_get_eventqueue(visual_actor_get_plugin(priv->actor)); visual_event_queue_add_keyboard(eventqueue, lv_key, lv_mask, VISUAL_KEY_DOWN); return 1; } static int key_release_callback(void * data, int key, int mask) { VisEventQueue *eventqueue; int lv_key, lv_mask; lv_priv_t * priv = (lv_priv_t*)data; if(!get_key_code(key, mask, &lv_key, &lv_mask)) return 0; eventqueue = visual_plugin_get_eventqueue(visual_actor_get_plugin(priv->actor)); visual_event_queue_add_keyboard(eventqueue, lv_key, lv_mask, VISUAL_KEY_UP); return 1; } static int motion_callback(void * data, int x, int y, int mask) { VisEventQueue *eventqueue; lv_priv_t * priv = (lv_priv_t*)data; eventqueue = visual_plugin_get_eventqueue(visual_actor_get_plugin(priv->actor)); visual_event_queue_add_mousemotion(eventqueue, x, y); if(priv->ov_callbacks && priv->ov_callbacks->motion_callback) { priv->ov_callbacks->motion_callback(priv->ov_callbacks->data, x, y, mask); } return 1; } static int button_callback(void * data, int x, int y, int button, int mask) { VisEventQueue *eventqueue; lv_priv_t * priv = (lv_priv_t*)data; eventqueue = visual_plugin_get_eventqueue(visual_actor_get_plugin(priv->actor)); visual_event_queue_add_mousebutton(eventqueue, button, VISUAL_MOUSE_DOWN, x, y); if(priv->ov_callbacks && priv->ov_callbacks->button_callback) { priv->ov_callbacks->button_callback(priv->ov_callbacks->data, x, y, button, mask); } return 1; } static int button_release_callback(void * data, int x, int y, int button, int mask) { VisEventQueue *eventqueue; lv_priv_t * priv = (lv_priv_t*)data; eventqueue = visual_plugin_get_eventqueue(visual_actor_get_plugin(priv->actor)); visual_event_queue_add_mousebutton(eventqueue, button, VISUAL_MOUSE_UP, x, y); if(priv->ov_callbacks && priv->ov_callbacks->button_release_callback) { priv->ov_callbacks->button_release_callback(priv->ov_callbacks->data, x, y, button, mask); } return 1; } gmerlin-1.2.0~dfsg/lib/utf8.c0000644000175000017500000001001711764363410015675 0ustar alessioalessio/***************************************************************** * gmerlin - a general purpose multimedia framework and applications * * Copyright (c) 2001 - 2011 Members of the Gmerlin project * gmerlin-general@lists.sourceforge.net * http://gmerlin.sourceforge.net * * 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 of the License, 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 this program. If not, see . * *****************************************************************/ #include #include #include #include #include #include #include #define BYTES_INCREMENT 10 static char * do_convert(iconv_t cd, char * in_string, int len, int * got_error) { char * ret; char *inbuf; char *outbuf; int alloc_size; int output_pos; int keep_going = 1; size_t inbytesleft; size_t outbytesleft; alloc_size = len + BYTES_INCREMENT; inbytesleft = len; outbytesleft = alloc_size; ret = malloc(alloc_size); inbuf = in_string; outbuf = ret; while(keep_going) { if(iconv(cd, &inbuf, &inbytesleft, &outbuf, &outbytesleft) == (size_t)-1) { switch(errno) { case E2BIG: output_pos = (int)(outbuf - ret); alloc_size += BYTES_INCREMENT; outbytesleft += BYTES_INCREMENT; ret = realloc(ret, alloc_size); outbuf = &ret[output_pos]; break; default: keep_going = 0; if(got_error) *got_error = 1; break; } } if(!inbytesleft) break; } /* Zero terminate */ output_pos = (int)(outbuf - ret); if(!outbytesleft) { alloc_size++; ret = realloc(ret, alloc_size); outbuf = &ret[output_pos]; } *outbuf = '\0'; return ret; } static char const * const try_charsets[] = { "ISO8859-1", "UTF-8", NULL, }; char * bg_system_to_utf8(const char * str, int len) { int i; iconv_t cd; char * system_charset; char * ret; int got_error = 0; char * tmp_string; if(len < 0) len = strlen(str); system_charset = nl_langinfo(CODESET); // if(!strcmp(system_charset, "UTF-8")) // return bg_strndup(NULL, str, str+len); tmp_string = malloc(len+1); memcpy(tmp_string, str, len); tmp_string[len] = '\0'; // system_charset = "ISO-8859-1"; cd = iconv_open("UTF-8", system_charset); ret = do_convert(cd, tmp_string, len, &got_error); iconv_close(cd); if(got_error) { if(ret) free(ret); i = 0; while(try_charsets[i]) { got_error = 0; cd = iconv_open("UTF-8", try_charsets[i]); ret = do_convert(cd, tmp_string, len, &got_error); iconv_close(cd); if(!got_error) { free(tmp_string); return ret; } else if(ret) free(ret); i++; } strncpy(tmp_string, str, len); tmp_string[len] = '\0'; } free(tmp_string); return ret; } #if 1 char * bg_utf8_to_system(const char * str, int len) { iconv_t cd; char * system_charset; char * ret; char * tmp_string; if(len < 0) len = strlen(str); system_charset = nl_langinfo(CODESET); if(!strcmp(system_charset, "UTF-8")) return bg_strndup(NULL, str, str+len); tmp_string = malloc(len+1); memcpy(tmp_string, str, len); tmp_string[len] = '\0'; cd = iconv_open(system_charset, "UTF-8"); ret = do_convert(cd, tmp_string, len, NULL); iconv_close(cd); free(tmp_string); return ret; } #endif gmerlin-1.2.0~dfsg/lib/osd.c0000644000175000017500000002032711764363410015601 0ustar alessioalessio/***************************************************************** * gmerlin - a general purpose multimedia framework and applications * * Copyright (c) 2001 - 2011 Members of the Gmerlin project * gmerlin-general@lists.sourceforge.net * http://gmerlin.sourceforge.net * * 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 of the License, 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 this program. If not, see . * *****************************************************************/ #include #include #include #include #include #include #include #include struct bg_osd_s { bg_text_renderer_t * renderer; int enable; gavl_overlay_t * ovl; gavl_time_t duration; float font_size; }; bg_osd_t * bg_osd_create() { bg_parameter_value_t val; bg_osd_t * ret; ret = calloc(1, sizeof(*ret)); ret->renderer = bg_text_renderer_create(); /* We set special parameters for the textrenderer */ val.val_str = bg_search_file_read("osd", "GmerlinOSD.pfb"); bg_text_renderer_set_parameter(ret->renderer, "font_file", &val); free(val.val_str); val.val_f = 20.0; bg_text_renderer_set_parameter(ret->renderer, "font_size", &val); val.val_i = 20; bg_text_renderer_set_parameter(ret->renderer, "cache_size", &val); return ret; } void bg_osd_destroy(bg_osd_t * osd) { bg_text_renderer_destroy(osd->renderer); free(osd); } static const bg_parameter_info_t parameters[] = { { .name = "enable_osd", .long_name = TRS("Enable OSD"), .type = BG_PARAMETER_CHECKBUTTON, .val_default = { .val_i = 1 }, }, /* The following stuff is copied from textrenderer.c */ { .name = "font_size", .long_name = TRS("Size"), .type = BG_PARAMETER_FLOAT, .num_digits = 2, .val_min = { .val_f = 12.0 }, .val_max = { .val_f = 100.0 }, .val_default = { .val_f = 30.0 }, .help_string = TRS("Specify fontsize for OSD. The value you enter, is for an image width of 640. For other \ widths, the value will be scaled"), }, { .name = "color", .long_name = TRS("Foreground color"), .type = BG_PARAMETER_COLOR_RGBA, .val_default = { .val_color = { 1.0, 1.0, 1.0, 1.0 } }, }, #ifdef FT_STROKER_H { .name = "border_color", .long_name = TRS("Border color"), .type = BG_PARAMETER_COLOR_RGB, .val_default = { .val_color = { 0.0, 0.0, 0.0, 1.0 } }, }, { .name = "border_width", .long_name = TRS("Border width"), .type = BG_PARAMETER_FLOAT, .val_min = { .val_f = 0.0 }, .val_max = { .val_f = 10.0 }, .val_default = { .val_f = 2.0 }, .num_digits = 2, }, #endif { .name = "justify_h", .long_name = TRS("Horizontal justify"), .type = BG_PARAMETER_STRINGLIST, .val_default = { .val_str = "center" }, .multi_names = (char const *[]){ "center", "left", "right", NULL }, .multi_labels = (char const *[]){ TRS("Center"), TRS("Left"), TRS("Right"), NULL }, }, { .name = "justify_v", .long_name = TRS("Vertical justify"), .type = BG_PARAMETER_STRINGLIST, .val_default = { .val_str = "center" }, .multi_names = (char const *[]){ "center", "top", "bottom", NULL }, .multi_labels = (char const *[]){ TRS("Center"), TRS("Top"), TRS("Bottom"), NULL }, }, { .name = "border_left", .long_name = TRS("Left border"), .type = BG_PARAMETER_INT, .val_min = { .val_i = 0 }, .val_max = { .val_i = 65535 }, .val_default = { .val_i = 10 }, .help_string = TRS("Distance from the left text border to the image border"), }, { .name = "border_right", .long_name = TRS("Right border"), .type = BG_PARAMETER_INT, .val_min = { .val_i = 0 }, .val_max = { .val_i = 65535 }, .val_default = { .val_i = 10 }, .help_string = TRS("Distance from the right text border to the image border"), }, { .name = "border_top", .long_name = TRS("Top border"), .type = BG_PARAMETER_INT, .val_min = { .val_i = 0 }, .val_max = { .val_i = 65535 }, .val_default = { .val_i = 10 }, .help_string = TRS("Distance from the top text border to the image border"), }, { .name = "border_bottom", .long_name = TRS("Bottom border"), .type = BG_PARAMETER_INT, .val_min = { .val_i = 0 }, .val_max = { .val_i = 65535 }, .val_default = { .val_i = 10 }, .help_string = TRS("Distance from the bottom text border to the image border"), }, { .name = "duration", .long_name = TRS("Duration (milliseconds)"), .type = BG_PARAMETER_INT, .val_min = { .val_i = 0 }, .val_max = { .val_i = 10000 }, .val_default = { .val_i = 2000 }, }, { /* End of parameters */ } }; const bg_parameter_info_t * bg_osd_get_parameters(bg_osd_t * osd) { return parameters; } void bg_osd_set_parameter(void * data, const char * name, const bg_parameter_value_t * val) { bg_osd_t * osd; if(!name) return; osd = (bg_osd_t*)data; if(!strcmp(name, "enable_osd")) osd->enable = val->val_i; else if(!strcmp(name, "duration")) osd->duration = val->val_i * ((GAVL_TIME_SCALE) / 1000); else bg_text_renderer_set_parameter(osd->renderer, name, val); } void bg_osd_set_overlay(bg_osd_t * osd, gavl_overlay_t * ovl) { osd->ovl = ovl; ovl->frame->timestamp = -1; } void bg_osd_init(bg_osd_t * osd, const gavl_video_format_t * format, gavl_video_format_t * overlay_format) { bg_text_renderer_init(osd->renderer, format, overlay_format); } int bg_osd_overlay_valid(bg_osd_t * osd, gavl_time_t time) { if(!osd->enable || (osd->ovl->frame->timestamp < 0)) return 0; if(time < osd->ovl->frame->timestamp) return 0; else if(time > osd->ovl->frame->timestamp + osd->ovl->frame->duration) { osd->ovl->frame->timestamp = -1; return 0; } return 1; } #define FLOAT_BAR_SIZE 18 #define FLOAT_BAR_SIZE_TOTAL 20 static void print_float(bg_osd_t * osd, float val, char c, gavl_time_t time) { char _buf[FLOAT_BAR_SIZE_TOTAL+3]; char * buf = _buf; int i, val_i; *buf = c; buf++; *buf = '\n'; buf++; *buf = '['; buf++; val_i = (int)(val * FLOAT_BAR_SIZE + 0.5); if(val_i > FLOAT_BAR_SIZE) val_i = FLOAT_BAR_SIZE; for(i = 0; i < val_i; i++) { *buf = '|'; buf++; } for(i = val_i; i < FLOAT_BAR_SIZE; i++) { *buf = '.'; buf++; } *buf = ']'; buf++; *buf = '\0'; bg_text_renderer_render(osd->renderer, _buf, osd->ovl); osd->ovl->frame->timestamp = time; osd->ovl->frame->duration = osd->duration; } void bg_osd_set_volume_changed(bg_osd_t * osd, float val, gavl_time_t time) { if(!osd->enable) return; print_float(osd, val, 'V', time); } void bg_osd_set_brightness_changed(bg_osd_t * osd, float val, gavl_time_t time) { if(!osd->enable) return; print_float(osd, val, 'B', time); } void bg_osd_set_contrast_changed(bg_osd_t * osd, float val, gavl_time_t time) { if(!osd->enable) return; print_float(osd, val, 'C', time); } void bg_osd_set_saturation_changed(bg_osd_t * osd, float val, gavl_time_t time) { if(!osd->enable) return; print_float(osd, val, 'S', time); } gmerlin-1.2.0~dfsg/lib/mediafiledevice.c0000644000175000017500000003306111764363410020112 0ustar alessioalessio/***************************************************************** * gmerlin - a general purpose multimedia framework and applications * * Copyright (c) 2001 - 2011 Members of the Gmerlin project * gmerlin-general@lists.sourceforge.net * http://gmerlin.sourceforge.net * * 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 of the License, 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 this program. If not, see . * *****************************************************************/ #include #include #include #include #include #include #include #include #include #include #include #include #include #define LOG_DOMAIN "mediafiledevice" #define SAMPLES_PER_FRAME 1024 typedef struct { bg_plugin_registry_t * plugin_reg; gavl_audio_format_t in_format; gavl_audio_format_t out_format; bg_audio_converter_t * cnv; gavl_audio_options_t * opt; int num_files; int files_alloc; int current; int do_shuffle; char * album_file; struct { char * location; char * plugin; int track; } * files; /* Shuffle list */ int * indices; bg_plugin_handle_t * h; bg_input_plugin_t * plugin; bg_read_audio_func_t in_func; void * in_data; int in_stream; gavl_audio_frame_t * frame; int64_t sample_counter; gavl_timer_t * timer; bg_recorder_callbacks_t * callbacks; time_t mtime; } audiofile_t; static int get_mtime(const char * file, time_t * ret) { struct stat st; if(stat(file, &st)) return 0; *ret = st.st_mtime; return 1; } static const bg_parameter_info_t parameters_audio[] = { { .name = "channel_mode", .long_name = TRS("Channel Mode"), .type = BG_PARAMETER_STRINGLIST, .val_default = { .val_str = "stereo" }, .multi_names = (char const *[]){ "mono", "stereo", NULL }, .multi_labels = (char const *[]){ TRS("Mono"), TRS("Stereo"), NULL }, }, { .name = "samplerate", .long_name = TRS("Samplerate [Hz]"), .type = BG_PARAMETER_INT, .val_default = { .val_i = 44100 }, .val_min = { .val_i = 8000 }, .val_max = { .val_i = 96000 }, }, { .name = "album", .long_name = TRS("Album"), .type = BG_PARAMETER_FILE, }, { .name = "shuffle", .long_name = TRS("Shuffle"), .type = BG_PARAMETER_CHECKBUTTON, }, { /* End of parameters */ } }; static const bg_parameter_info_t * get_parameters_audio(void * priv) { return parameters_audio; } static void set_parameter_audio(void * p, const char * name, const bg_parameter_value_t * val) { audiofile_t * m = p; if(!name) return; if(!strcmp(name, "channel_mode")) { if(!strcmp(val->val_str, "mono")) m->out_format.num_channels = 1; else if(!strcmp(val->val_str, "stereo")) m->out_format.num_channels = 2; } else if(!strcmp(name, "samplerate")) m->out_format.samplerate = val->val_i; else if(!strcmp(name, "album")) m->album_file = bg_strdup(m->album_file, val->val_str); else if(!strcmp(name, "shuffle")) m->do_shuffle = val->val_i; } static void destroy_audio(void * p) { audiofile_t * m = p; bg_audio_converter_destroy(m->cnv); gavl_audio_options_destroy(m->opt); gavl_timer_destroy(m->timer); } static void free_track_list(audiofile_t * m) { int i; if(m->files) { for(i = 0; i < m->num_files; i++) { if(m->files[i].location) free(m->files[i].location); if(m->files[i].plugin) free(m->files[i].plugin); } free(m->files); m->files = NULL; } if(m->indices) { free(m->indices); m->indices = NULL; } m->num_files = 0; m->files_alloc = 0; m->current = 0; } static void append_track(audiofile_t * m, const char * location, const char * plugin, int track) { if(m->num_files + 1 > m->files_alloc) { m->files_alloc += 128; m->files = realloc(m->files, sizeof(*m->files) * m->files_alloc); memset(m->files + m->num_files, 0, sizeof(*m->files) * (m->files_alloc - m->num_files)); } m->files[m->num_files].location = bg_strdup(m->files[m->num_files].location, location); m->files[m->num_files].plugin = bg_strdup(m->files[m->num_files].plugin, plugin); m->files[m->num_files].track = track; m->num_files++; } static int build_track_list(audiofile_t * m) { bg_album_entry_t * entries; bg_album_entry_t * e; char * album_xml; free_track_list(m); if(!m->album_file) { bg_log(BG_LOG_ERROR, LOG_DOMAIN, "No album file given"); return 0; } album_xml = bg_read_file(m->album_file, NULL); if(!album_xml) { bg_log(BG_LOG_ERROR, LOG_DOMAIN, "Album file %s could not be opened", m->album_file); return 0; } entries = bg_album_entries_new_from_xml(album_xml); free(album_xml); if(!entries) { bg_log(BG_LOG_ERROR, LOG_DOMAIN, "Album file %s contains no entries", m->album_file); return 0; } e = entries; while(e) { if(!e->num_audio_streams) { e = e->next; continue; } append_track(m, e->location, e->plugin, e->index); e = e->next; } if(entries) bg_album_entries_destroy(entries); if(!m->num_files) { bg_log(BG_LOG_ERROR, LOG_DOMAIN, "Album file %s contains no usable entries", m->album_file); return 0; } if(m->do_shuffle) { int i, index; int tmp; m->indices = malloc(sizeof(*m->indices) * m->num_files); for(i = 0; i < m->num_files; i++) m->indices[i] = i; for(i = 0; i < m->num_files; i++) { index = rand() % m->num_files; tmp = m->indices[i]; m->indices[i] = m->indices[index]; m->indices[index] = tmp; } } return m->num_files; } static int open_file(audiofile_t * m) { bg_track_info_t * ti; int num_tracks; const bg_plugin_info_t * info; int idx; time_t new_mtime; if(get_mtime(m->album_file, &new_mtime) && (new_mtime != m->mtime)) { bg_log(BG_LOG_INFO, LOG_DOMAIN, "Reloading album (file changed)"); m->mtime = new_mtime; if(!build_track_list(m)) return 0; } idx = m->indices ? m->indices[m->current] : m->current; if(m->h) { bg_plugin_unref(m->h); m->h = NULL; } if(m->files[idx].plugin) info = bg_plugin_find_by_name(m->plugin_reg, m->files[idx].plugin); else info = NULL; if(!bg_input_plugin_load(m->plugin_reg, m->files[idx].location, info, &m->h, NULL, 0)) return 0; m->plugin = (bg_input_plugin_t *)m->h->plugin; /* Select track */ if(m->plugin->get_num_tracks) num_tracks = m->plugin->get_num_tracks(m->h->priv); else num_tracks = 1; if(num_tracks <= m->files[idx].track) return 0; ti = m->plugin->get_track_info(m->h->priv, m->files[idx].track); if(m->plugin->set_track) m->plugin->set_track(m->h->priv, m->files[idx].track); if(!ti->num_audio_streams) return 0; m->plugin->set_audio_stream(m->h->priv, 0, BG_STREAM_ACTION_DECODE); if(m->callbacks && m->callbacks->metadata_changed) { if(ti->name) m->callbacks->metadata_changed(m->callbacks->data, ti->name, &ti->metadata); else { char * tmp_string = bg_get_track_name_default(m->files[idx].location, m->files[idx].track, num_tracks); m->callbacks->metadata_changed(m->callbacks->data, tmp_string, &ti->metadata); free(tmp_string); } } if(!m->plugin->start(m->h->priv)) return 0; gavl_audio_format_copy(&m->in_format, &ti->audio_streams[0].format); /* Input channel */ m->in_func = m->plugin->read_audio; m->in_data = m->h->priv; m->in_stream = 0; /* Set up format converter */ if(bg_audio_converter_init(m->cnv, &m->in_format, &m->out_format)) { bg_audio_converter_connect_input(m->cnv, m->in_func, m->in_data, m->in_stream); m->in_func = bg_audio_converter_read; m->in_data = m->cnv; m->in_stream = 0; } return 1; } static int open_audio(void * p, gavl_audio_format_t * format, gavl_video_format_t * video_format) { audiofile_t * m = p; /* Finalize audio format */ m->sample_counter = 0; m->out_format.channel_locations[0] = GAVL_CHID_NONE; gavl_set_channel_setup(&m->out_format); gavl_audio_format_copy(format, &m->out_format); m->frame = gavl_audio_frame_create(&m->out_format); if(!get_mtime(m->album_file, &m->mtime)) return 0; /* Create track list */ if(!build_track_list(m)) return 0; m->current = 0; /* Open first file */ if(!open_file(m)) return 0; gavl_timer_start(m->timer); return 1; } static void close_audio(void * p) { audiofile_t * m = p; gavl_timer_stop(m->timer); } static int read_frame_audio(void * p, gavl_audio_frame_t * f, int stream, int num_samples) { int samples_read; int samples_to_read; gavl_time_t current_time; gavl_time_t diff_time; audiofile_t * m = p; f->valid_samples = 0; while(f->valid_samples < num_samples) { samples_to_read = SAMPLES_PER_FRAME; if(samples_to_read + f->valid_samples > num_samples) samples_to_read = num_samples - f->valid_samples; samples_read = m->in_func(m->in_data, m->frame, m->in_stream, samples_to_read); if(samples_read > 0) { gavl_audio_frame_copy(&m->out_format, f, m->frame, f->valid_samples /* dst_pos */, 0 /* src_pos */, samples_read, samples_read); f->valid_samples += samples_read; } else /* Open next file */ { while(1) { m->current++; if(m->current >= m->num_files) m->current = 0; if(open_file(m)) break; } } } /* Wait until we can output the data */ current_time = gavl_timer_get(m->timer); diff_time = gavl_time_unscale(m->out_format.samplerate, m->sample_counter) - current_time; if(diff_time > 0) gavl_time_delay(&diff_time); m->sample_counter += f->valid_samples; return f->valid_samples; } static void set_callbacks_audio(void * p, bg_recorder_callbacks_t * callbacks) { audiofile_t * m = p; m->callbacks = callbacks; } static const bg_recorder_plugin_t audiofile_input = { .common = { BG_LOCALE, .name = bg_audiofiledevice_name, .long_name = TRS("Audiofile recorder"), .description = TRS("Take a bunch of audio file and make them available as a recording device"), .type = BG_PLUGIN_RECORDER_AUDIO, .flags = BG_PLUGIN_RECORDER, .priority = 1, .destroy = destroy_audio, .get_parameters = get_parameters_audio, .set_parameter = set_parameter_audio, }, .set_callbacks = set_callbacks_audio, .open = open_audio, .read_audio = read_frame_audio, .close = close_audio, }; bg_plugin_info_t * bg_audiofiledevice_info(bg_plugin_registry_t * reg) { bg_plugin_info_t * ret; const bg_recorder_plugin_t * plugin = &audiofile_input; if(!bg_plugin_registry_get_num_plugins(reg, BG_PLUGIN_INPUT, BG_PLUGIN_FILE)) return NULL; ret = calloc(1, sizeof(*ret)); ret->gettext_domain = bg_strdup(ret->gettext_domain, plugin->common.gettext_domain); ret->gettext_directory = bg_strdup(ret->gettext_directory, plugin->common.gettext_directory); ret->name = bg_strdup(ret->name, plugin->common.name); ret->long_name = bg_strdup(ret->long_name, plugin->common.long_name); ret->description = bg_strdup(ret->description, plugin->common.description); ret->priority = plugin->common.priority; ret->type = plugin->common.type; ret->flags = plugin->common.flags; ret->parameters = bg_parameter_info_copy_array(parameters_audio); return ret; } const bg_plugin_common_t * bg_audiofiledevice_get() { return (const bg_plugin_common_t*)(&audiofile_input); } void * bg_audiofiledevice_create(bg_plugin_registry_t * reg) { audiofile_t * ret = calloc(1, sizeof(*ret)); ret->plugin_reg = reg; /* Set common audio format parameters */ ret->out_format.sample_format = GAVL_SAMPLE_FLOAT; ret->out_format.interleave_mode = GAVL_INTERLEAVE_NONE; ret->out_format.samples_per_frame = SAMPLES_PER_FRAME; ret->opt = gavl_audio_options_create(); ret->cnv = bg_audio_converter_create(ret->opt); ret->timer = gavl_timer_create(); return ret; } gmerlin-1.2.0~dfsg/lib/ov.c0000644000175000017500000002045411764363410015441 0ustar alessioalessio/***************************************************************** * gmerlin - a general purpose multimedia framework and applications * * Copyright (c) 2001 - 2011 Members of the Gmerlin project * gmerlin-general@lists.sourceforge.net * http://gmerlin.sourceforge.net * * 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 of the License, 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 this program. If not, see . * *****************************************************************/ #include #include #include #include #include #include #define LOG_DOMAIN "ov" #define LOCK(p) bg_plugin_lock(p->h) #define UNLOCK(p) bg_plugin_unlock(p->h) #define FLAG_EMULATE_OVL (1<<0) #define FLAG_EMULATE_STILL (1<<1) #define FLAG_STILL_MODE (1<<2) #define FLAG_OPEN (1<<3) struct bg_ov_s { bg_plugin_handle_t * h; bg_ov_plugin_t * plugin; void * priv; gavl_video_format_t format; int flags; struct { gavl_overlay_blend_context_t * ctx; gavl_overlay_t * ovl; gavl_video_format_t format; } * ovl_str; int num_ovl_str; gavl_video_frame_t * still_frame; }; bg_ov_t * bg_ov_create(bg_plugin_handle_t * h) { bg_ov_t * ret = calloc(1, sizeof(*ret)); ret->h = h; bg_plugin_ref(h); ret->priv = h->priv; ret->plugin = (bg_ov_plugin_t*)(ret->h->plugin); return ret; } bg_plugin_handle_t * bg_ov_get_plugin(bg_ov_t * ov) { return ov->h; } void bg_ov_destroy(bg_ov_t * ov) { if(ov->flags & FLAG_OPEN) { LOCK(ov); ov->plugin->close(ov->priv); UNLOCK(ov); } bg_plugin_unref(ov->h); free(ov); } void bg_ov_set_window(bg_ov_t * ov, const char * window_id) { if(ov->plugin->set_window) { LOCK(ov); ov->plugin->set_window(ov->priv, window_id); UNLOCK(ov); } } const char * bg_ov_get_window(bg_ov_t * ov) { const char * ret; if(ov->plugin->get_window) { LOCK(ov); ret = ov->plugin->get_window(ov->priv); UNLOCK(ov); return ret; } return NULL; } void bg_ov_set_window_options(bg_ov_t * ov, const char * name, const char * klass, const gavl_video_frame_t * icon, const gavl_video_format_t * icon_format) { if(ov->plugin->set_window_options) { LOCK(ov); ov->plugin->set_window_options(ov->priv, name, klass, icon, icon_format); UNLOCK(ov); } } void bg_ov_set_window_title(bg_ov_t * ov, const char * title) { if(ov->plugin->set_window_title) { LOCK(ov); ov->plugin->set_window_title(ov->priv, title); UNLOCK(ov); } } void bg_ov_set_callbacks(bg_ov_t * ov, bg_ov_callbacks_t * callbacks) { if(ov->plugin->set_callbacks) { LOCK(ov); ov->plugin->set_callbacks(ov->priv, callbacks); UNLOCK(ov); } } int bg_ov_open(bg_ov_t * ov, gavl_video_format_t * format, int keep_aspect) { int ret; LOCK(ov); ret = ov->plugin->open(ov->priv, format, keep_aspect); UNLOCK(ov); gavl_video_format_copy(&ov->format, format); if(ret) ov->flags = FLAG_OPEN; return ret; } gavl_video_frame_t * bg_ov_get_frame(bg_ov_t * ov) { gavl_video_frame_t * ret; LOCK(ov); ret = ov->plugin->get_frame(ov->priv); UNLOCK(ov); return ret; } int bg_ov_add_overlay_stream(bg_ov_t * ov, gavl_video_format_t * format) { int ret; if(ov->plugin->add_overlay_stream) { /* Try hardware overlay */ LOCK(ov); ret = ov->plugin->add_overlay_stream(ov->priv, format); UNLOCK(ov); if(ret >= 0) { bg_log(BG_LOG_INFO, LOG_DOMAIN, "Using hardeware overlay for stream %d", ret); return ret; } } /* Software overlay */ ov->flags |= FLAG_EMULATE_OVL; bg_log(BG_LOG_INFO, LOG_DOMAIN, "Using software overlay for stream %d", ov->num_ovl_str); ov->ovl_str = realloc(ov->ovl_str, (ov->num_ovl_str+1)* sizeof(*ov->ovl_str)); memset(ov->ovl_str + ov->num_ovl_str, 0, sizeof(*ov->ovl_str)); ov->ovl_str[ov->num_ovl_str].ctx = gavl_overlay_blend_context_create(); gavl_overlay_blend_context_init(ov->ovl_str[ov->num_ovl_str].ctx, &ov->format, format); gavl_video_format_copy(&ov->ovl_str[ov->num_ovl_str].format, format); ov->num_ovl_str++; return ov->num_ovl_str-1; } gavl_overlay_t * bg_ov_create_overlay(bg_ov_t * ov, int id) { gavl_overlay_t * ret; if(!(ov->flags & FLAG_EMULATE_OVL)) { LOCK(ov); ret = ov->plugin->create_overlay(ov->priv, id); UNLOCK(ov); return ret; } else { ret = calloc(1, sizeof(*ret)); ret->frame = gavl_video_frame_create(&ov->ovl_str[id].format); gavl_video_frame_clear(ret->frame, &ov->ovl_str[id].format); return ret; } } void bg_ov_set_overlay(bg_ov_t * ov, int stream, gavl_overlay_t * ovl) { if(ov->flags & FLAG_EMULATE_OVL) { gavl_overlay_blend_context_set_overlay(ov->ovl_str[stream].ctx, ovl); ov->ovl_str[stream].ovl = ovl; } else { LOCK(ov); ov->plugin->set_overlay(ov->priv, stream, ovl); UNLOCK(ov); } } void bg_ov_destroy_overlay(bg_ov_t * ov, int id, gavl_overlay_t * ovl) { if(ov->flags & FLAG_EMULATE_OVL) { gavl_video_frame_destroy(ovl->frame); free(ovl); } else ov->plugin->destroy_overlay(ov->priv, id, ovl); } static void blend_overlays(bg_ov_t * ov, gavl_video_frame_t * f) { int i; for(i = 0; i < ov->num_ovl_str; i++) { if(ov->ovl_str[i].ovl) { // fprintf(stderr, "Blend overlay\n"); gavl_overlay_blend(ov->ovl_str[i].ctx, f); } } } void bg_ov_put_video(bg_ov_t * ov, gavl_video_frame_t*frame) { ov->flags &= ~FLAG_STILL_MODE; if(ov->flags & FLAG_EMULATE_OVL) blend_overlays(ov, frame); LOCK(ov); ov->plugin->put_video(ov->priv, frame); UNLOCK(ov); } void bg_ov_put_still(bg_ov_t * ov, gavl_video_frame_t*frame) { ov->flags |= FLAG_STILL_MODE; if(ov->plugin->put_still) { LOCK(ov); ov->plugin->put_still(ov->priv, frame); UNLOCK(ov); return; } /* Still frames not supported */ else { if(!ov->still_frame) ov->still_frame = gavl_video_frame_create(&ov->format); } gavl_video_frame_copy(&ov->format, ov->still_frame, frame); ov->flags |= FLAG_EMULATE_STILL; LOCK(ov); ov->plugin->put_video(ov->priv, frame); UNLOCK(ov); } void bg_ov_handle_events(bg_ov_t * ov) { if((ov->flags & FLAG_STILL_MODE) && (ov->flags & FLAG_EMULATE_STILL)) { gavl_video_frame_t * f; LOCK(ov); f = ov->plugin->get_frame(ov->priv); gavl_video_frame_copy(&ov->format, f, ov->still_frame); ov->plugin->put_video(ov->priv, f); UNLOCK(ov); } if(ov->plugin->handle_events) { LOCK(ov); ov->plugin->handle_events(ov->priv); UNLOCK(ov); } } void bg_ov_update_aspect(bg_ov_t * ov, int pixel_width, int pixel_height) { if(ov->plugin->update_aspect) { LOCK(ov); ov->plugin->update_aspect(ov->priv, pixel_width, pixel_height); UNLOCK(ov); } } void bg_ov_close(bg_ov_t * ov) { LOCK(ov); ov->plugin->close(ov->priv); UNLOCK(ov); if(ov->still_frame) { gavl_video_frame_destroy(ov->still_frame); ov->still_frame = NULL; } if(ov->num_ovl_str) { int i; for(i = 0; i < ov->num_ovl_str; i++) gavl_overlay_blend_context_destroy(ov->ovl_str[i].ctx); free(ov->ovl_str); ov->ovl_str = NULL; ov->num_ovl_str = 0; } } void bg_ov_show_window(bg_ov_t * ov, int show) { if(ov->plugin->show_window) { LOCK(ov); ov->plugin->show_window(ov->priv, show); UNLOCK(ov); } } gmerlin-1.2.0~dfsg/lib/bgladspa.c0000644000175000017500000005055211764363410016574 0ustar alessioalessio/***************************************************************** * gmerlin - a general purpose multimedia framework and applications * * Copyright (c) 2001 - 2011 Members of the Gmerlin project * gmerlin-general@lists.sourceforge.net * http://gmerlin.sourceforge.net * * 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 of the License, 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 this program. If not, see . * *****************************************************************/ #include #include #include #include #include #include #include #include #include #include #include #define LOG_DOMAIN "ladspa" static bg_parameter_info_t * create_parameters(const LADSPA_Descriptor * desc) { int num_parameters = 0; int index; int i; bg_parameter_info_t * ret; int is_int; float val_default = 0.0; for(i = 0; i < desc->PortCount; i++) { if(LADSPA_IS_PORT_INPUT(desc->PortDescriptors[i]) && LADSPA_IS_PORT_CONTROL(desc->PortDescriptors[i])) num_parameters++; } if(desc->set_run_adding_gain) num_parameters++; if(desc->run_adding) num_parameters++; if(!num_parameters) return NULL; index = 0; ret = calloc(num_parameters+1, sizeof(*ret)); for(i = 0; i < desc->PortCount; i++) { if(LADSPA_IS_PORT_INPUT(desc->PortDescriptors[i]) && LADSPA_IS_PORT_CONTROL(desc->PortDescriptors[i])) { is_int = 0; ret[index].name = bg_sprintf("%s", desc->PortNames[i]); ret[index].long_name = bg_sprintf("%s", desc->PortNames[i]); if(desc->PortRangeHints[i].HintDescriptor & LADSPA_HINT_TOGGLED) { is_int = 1; ret[index].type = BG_PARAMETER_CHECKBUTTON; if((desc->PortRangeHints[i].HintDescriptor & LADSPA_HINT_DEFAULT_MASK) == LADSPA_HINT_DEFAULT_1) ret[index].val_default.val_i = 1; } else if(desc->PortRangeHints[i].HintDescriptor & LADSPA_HINT_INTEGER) { is_int = 1; if((desc->PortRangeHints[i].HintDescriptor & LADSPA_HINT_BOUNDED_BELOW) && (desc->PortRangeHints[i].HintDescriptor & LADSPA_HINT_BOUNDED_ABOVE)) { ret[index].type = BG_PARAMETER_SLIDER_INT; ret[index].val_min.val_i = (int)(desc->PortRangeHints[i].LowerBound); ret[index].val_max.val_i = (int)(desc->PortRangeHints[i].UpperBound); } else ret[index].type = BG_PARAMETER_INT; } else if((desc->PortRangeHints[i].HintDescriptor & LADSPA_HINT_BOUNDED_BELOW) && (desc->PortRangeHints[i].HintDescriptor & LADSPA_HINT_BOUNDED_ABOVE)) { ret[index].type = BG_PARAMETER_SLIDER_FLOAT; ret[index].val_min.val_f = desc->PortRangeHints[i].LowerBound; ret[index].val_max.val_f = desc->PortRangeHints[i].UpperBound; ret[index].num_digits = 3; } else { ret[index].type = BG_PARAMETER_FLOAT; ret[index].num_digits = 3; } if((desc->PortRangeHints[i].HintDescriptor & LADSPA_HINT_DEFAULT_MASK) == LADSPA_HINT_DEFAULT_MINIMUM) val_default = desc->PortRangeHints[i].LowerBound; else if((desc->PortRangeHints[i].HintDescriptor & LADSPA_HINT_DEFAULT_MASK) == LADSPA_HINT_DEFAULT_MAXIMUM) val_default = desc->PortRangeHints[i].UpperBound; else if((desc->PortRangeHints[i].HintDescriptor & LADSPA_HINT_DEFAULT_MASK) == LADSPA_HINT_DEFAULT_LOW) { if(desc->PortRangeHints[i].HintDescriptor & LADSPA_HINT_LOGARITHMIC) { val_default = exp(log(desc->PortRangeHints[i].LowerBound) * 0.75 + log(desc->PortRangeHints[i].UpperBound) * 0.25); } else { val_default = desc->PortRangeHints[i].LowerBound * 0.75 + desc->PortRangeHints[i].UpperBound * 0.25; } } else if((desc->PortRangeHints[i].HintDescriptor & LADSPA_HINT_DEFAULT_MASK) == LADSPA_HINT_DEFAULT_MIDDLE) { if(desc->PortRangeHints[i].HintDescriptor & LADSPA_HINT_LOGARITHMIC) { val_default = sqrt(desc->PortRangeHints[i].LowerBound * desc->PortRangeHints[i].UpperBound); } else { val_default = 0.5 * (desc->PortRangeHints[i].LowerBound + desc->PortRangeHints[i].UpperBound); } } else if((desc->PortRangeHints[i].HintDescriptor & LADSPA_HINT_DEFAULT_MASK) == LADSPA_HINT_DEFAULT_HIGH) { if(desc->PortRangeHints[i].HintDescriptor & LADSPA_HINT_LOGARITHMIC) { val_default = exp(log(desc->PortRangeHints[i].LowerBound) * 0.25 + log(desc->PortRangeHints[i].UpperBound) * 0.75); } else { val_default = desc->PortRangeHints[i].LowerBound * 0.25 + desc->PortRangeHints[i].UpperBound * 0.75; } } else if((desc->PortRangeHints[i].HintDescriptor & LADSPA_HINT_DEFAULT_MASK) == LADSPA_HINT_DEFAULT_100) { val_default = 100.0; } else if((desc->PortRangeHints[i].HintDescriptor & LADSPA_HINT_DEFAULT_MASK) == LADSPA_HINT_DEFAULT_440) { val_default = 440.0; } if(is_int) ret[index].val_default.val_i = (int)(val_default); else ret[index].val_default.val_f = val_default; ret[index].flags |= BG_PARAMETER_SYNC; index++; } } if(desc->run_adding) { ret[index].name = bg_strdup(ret[index].name, "$run_adding"); ret[index].long_name = bg_strdup(ret[index].long_name, TR("Add effect to input data")); ret[index].type = BG_PARAMETER_CHECKBUTTON; ret[index].val_default.val_i = 0; ret[index].flags = BG_PARAMETER_SYNC; index++; } if(desc->set_run_adding_gain) { ret[index].name = bg_strdup(ret[index].name, "$run_adding_gain"); ret[index].long_name = bg_strdup(ret[index].long_name, TR("Add gain (dB)")); ret[index].type = BG_PARAMETER_SLIDER_FLOAT; ret[index].num_digits = 2; ret[index].val_min.val_f = -70.0; ret[index].val_max.val_f = 0.0; ret[index].val_default.val_f = 0.0; ret[index].help_string = bg_strdup(ret[index].help_string, TR("Overall gain for this filter. This is only valid if you add the effect to the input data")); ret[index].flags = BG_PARAMETER_SYNC; index++; } return ret; } static void count_ports(const LADSPA_Descriptor * desc, int * in_ports, int * out_ports, int * in_control_ports, int * out_control_ports) { int i; *in_ports = 0; *out_ports = 0; *in_control_ports = 0; *out_control_ports = 0; for(i = 0; i < desc->PortCount; i++) { if(LADSPA_IS_PORT_AUDIO(desc->PortDescriptors[i])) { if(LADSPA_IS_PORT_INPUT(desc->PortDescriptors[i])) (*in_ports)++; else if(LADSPA_IS_PORT_OUTPUT(desc->PortDescriptors[i])) (*out_ports)++; } else if(LADSPA_IS_PORT_CONTROL(desc->PortDescriptors[i])) { if(LADSPA_IS_PORT_INPUT(desc->PortDescriptors[i])) (*in_control_ports)++; else if(LADSPA_IS_PORT_OUTPUT(desc->PortDescriptors[i])) (*out_control_ports)++; } } } static bg_plugin_info_t * get_info(const LADSPA_Descriptor * desc) { bg_plugin_info_t * ret; int in_ports, out_ports, in_control_ports, out_control_ports; ret = calloc(1, sizeof(*ret)); ret->name = bg_sprintf("fa_ladspa_%s", desc->Label); ret->long_name = bg_strdup(NULL, desc->Name); ret->type = BG_PLUGIN_FILTER_AUDIO; ret->api = BG_PLUGIN_API_LADSPA; ret->flags = BG_PLUGIN_FILTER_1; ret->description = bg_sprintf(TR("ladspa plugin\nAuthor:\t%s\nCopyright:\t%s"), desc->Maker, desc->Copyright); /* Check for ports */ count_ports(desc, &in_ports, &out_ports, &in_control_ports, &out_control_ports); if((in_ports != out_ports) || (in_ports < 1) || ((in_ports > 2))) { /* Unsupported */ ret->flags |= BG_PLUGIN_UNSUPPORTED; } ret->parameters = create_parameters(desc); return ret; } bg_plugin_info_t * bg_ladspa_get_info(void * dll_handle, const char * filename) { bg_plugin_info_t * ret = NULL; bg_plugin_info_t * end = NULL; bg_plugin_info_t * new = NULL; int index; const LADSPA_Descriptor * desc; LADSPA_Descriptor_Function desc_func; desc_func = dlsym(dll_handle, "ladspa_descriptor"); if(!desc_func) { bg_log(BG_LOG_WARNING, LOG_DOMAIN, "No symbol \"ladspa_descriptor\" found: %s", dlerror()); return NULL; } index = 0; while((desc = desc_func(index))) { new = get_info(desc); new->index = index; new->module_filename = bg_strdup(NULL, filename); if(ret) { end->next = new; end = end->next; } else { ret = new; end = ret; } index++; } return ret; } typedef struct { LADSPA_Data * config_ports; gavl_audio_format_t format; gavl_audio_frame_t * frame; const LADSPA_Descriptor * desc; float run_adding_gain; int run_adding; bg_read_audio_func_t read_func; void * read_data; int read_stream; bg_parameter_info_t * parameters; /* Port maps */ int num_in_ports; int * in_ports; int num_out_ports; int * out_ports; int num_in_c_ports; int * in_c_ports; int num_out_c_ports; int * out_c_ports; int num_instances; int inplace_broken; struct { LADSPA_Handle Instance; int input_port; int output_port; int run; } channels[GAVL_MAX_CHANNELS]; } ladspa_priv_t; static void cleanup_ladspa(ladspa_priv_t * lp) { int i; for(i = 0; i < lp->num_instances; i++) { if(lp->desc->deactivate) lp->desc->deactivate(lp->channels[i].Instance); if(lp->desc->cleanup) lp->desc->cleanup(lp->channels[i].Instance); } lp->num_instances = 0; if(lp->frame) { gavl_audio_frame_destroy(lp->frame); lp->frame = NULL; } } /* Initialize instances, called after the input format is known */ static void init_ladspa(ladspa_priv_t * lp) { int i, j; cleanup_ladspa(lp); if(lp->num_out_ports == 1) { lp->num_instances = lp->format.num_channels; } else if(lp->format.num_channels != lp->num_out_ports) { bg_log(BG_LOG_WARNING, LOG_DOMAIN, "Remixing to stereo for filter \"%s\"", lp->desc->Name); lp->format.num_channels = 2; lp->format.channel_locations[0] = GAVL_CHID_NONE; gavl_set_channel_setup(&lp->format); lp->num_instances = 1; } else /* Stereo -> Stereo */ lp->num_instances = 1; lp->format.samples_per_frame = 0; for(i = 0; i < lp->num_instances; i++) { lp->channels[i].Instance = lp->desc->instantiate(lp->desc, lp->format.samplerate); for(j = 0; j < lp->num_in_c_ports; j++) { lp->desc->connect_port(lp->channels[i].Instance, lp->in_c_ports[j], &lp->config_ports[lp->in_c_ports[j]]); } for(j = 0; j < lp->num_out_c_ports; j++) { lp->desc->connect_port(lp->channels[i].Instance, lp->out_c_ports[j], &lp->config_ports[lp->out_c_ports[j]]); } if(lp->desc->activate) lp->desc->activate(lp->channels[i].Instance); if(lp->desc->set_run_adding_gain) lp->desc->set_run_adding_gain(lp->channels[i].Instance, lp->run_adding_gain); lp->channels[i].input_port = lp->in_ports[0]; lp->channels[i].output_port = lp->out_ports[0]; } for(i = lp->num_instances; i < lp->format.num_channels; i++) { lp->channels[i].Instance = lp->channels[0].Instance; lp->channels[i].input_port = lp->in_ports[i]; lp->channels[i].output_port = lp->out_ports[i]; } } static void set_input_format_ladspa(void * priv, gavl_audio_format_t * format, int port) { ladspa_priv_t * lp; lp = (ladspa_priv_t *)priv; if(!port) { format->interleave_mode = GAVL_INTERLEAVE_NONE; format->sample_format = GAVL_SAMPLE_FLOAT; gavl_audio_format_copy(&lp->format, format); init_ladspa(lp); gavl_audio_format_copy(format, &lp->format); } } static void connect_input_port_ladspa(void * priv, bg_read_audio_func_t func, void * data, int stream, int port) { ladspa_priv_t * lp; lp = (ladspa_priv_t *)priv; if(!port) { lp->read_func = func; lp->read_data = data; lp->read_stream = stream; } } static void get_output_format_ladspa(void * priv, gavl_audio_format_t * format) { ladspa_priv_t * lp; lp = (ladspa_priv_t *)priv; gavl_audio_format_copy(format, &lp->format); } static void connect_input(ladspa_priv_t * lp, gavl_audio_frame_t * f) { int i; for(i = 0; i < lp->format.num_channels; i++) { lp->desc->connect_port(lp->channels[i].Instance, lp->channels[i].input_port, f->channels.f[i]); } } static void connect_output(ladspa_priv_t * lp, gavl_audio_frame_t * f) { int i; for(i = 0; i < lp->format.num_channels; i++) { lp->desc->connect_port(lp->channels[i].Instance, lp->channels[i].output_port, f->channels.f[i]); } } static int read_audio_ladspa(void * priv, gavl_audio_frame_t * frame, int stream, int num_samples) { int i; ladspa_priv_t * lp; int ret; lp = (ladspa_priv_t *)priv; /* Check whether to (re)allocate the frame */ if(lp->frame && lp->inplace_broken && (num_samples > lp->format.samples_per_frame)) { gavl_audio_frame_destroy(lp->frame); lp->frame = NULL; } if(!lp->frame && lp->inplace_broken) { lp->format.samples_per_frame = num_samples + 1024; lp->frame = gavl_audio_frame_create(&lp->format); connect_input(lp, lp->frame); } if(!lp->inplace_broken) { ret = lp->read_func(lp->read_data, frame, lp->read_stream, num_samples); if(!ret) return 0; connect_input(lp, frame); } else { ret = lp->read_func(lp->read_data, lp->frame, lp->read_stream, num_samples); if(!ret) return 0; if(lp->run_adding) gavl_audio_frame_copy(&lp->format, frame, lp->frame, 0, 0, lp->frame->valid_samples, lp->frame->valid_samples); frame->timestamp = lp->frame->timestamp; } connect_output(lp, frame); /* Run */ for(i = 0; i < lp->num_instances; i++) { if(lp->run_adding) lp->desc->run_adding(lp->channels[i].Instance, ret); else lp->desc->run(lp->channels[i].Instance, ret); } frame->valid_samples = ret; return ret; } static void reset_ladspa(void * priv) { int i; ladspa_priv_t * lp; lp = (ladspa_priv_t *)priv; /* Reset */ if(lp->desc->deactivate) { for(i = 0; i < lp->num_instances; i++) lp->desc->deactivate(lp->channels[i].Instance); } if(lp->desc->activate) { for(i = 0; i < lp->num_instances; i++) lp->desc->activate(lp->channels[i].Instance); } } static const bg_parameter_info_t * get_parameters_ladspa(void * priv) { ladspa_priv_t * lp; lp = (ladspa_priv_t *)priv; return lp->parameters; } static void set_parameter_ladspa(void * priv, const char * name, const bg_parameter_value_t * val) { int i; ladspa_priv_t * lp; float gain_lin; if(!name) return; lp = (ladspa_priv_t *)priv; if(!strcmp(name, "$run_adding_gain")) { gain_lin = pow(10, val->val_f / 20.0); for(i = 0; i < lp->num_instances; i++) { lp->desc->set_run_adding_gain(lp->channels[i].Instance, gain_lin); } lp->run_adding_gain = gain_lin; return; } if(!strcmp(name, "$run_adding")) { if(lp->desc->run_adding) lp->run_adding = val->val_i; else lp->run_adding = 0; return; } for(i = 0; i < lp->num_in_c_ports; i++) { if(!strcmp(name, lp->desc->PortNames[lp->in_c_ports[i]])) { if(lp->desc->PortRangeHints[lp->in_c_ports[i]].HintDescriptor & (LADSPA_HINT_INTEGER | LADSPA_HINT_TOGGLED)) lp->config_ports[lp->in_c_ports[i]] = val->val_i; else lp->config_ports[lp->in_c_ports[i]] = val->val_f; break; } } } int bg_ladspa_load(bg_plugin_handle_t * ret, const bg_plugin_info_t * info) { int i; LADSPA_Descriptor_Function desc_func; int in_port_index = 0, out_port_index = 0; int in_c_port_index = 0, out_c_port_index = 0; ladspa_priv_t * priv; bg_fa_plugin_t * af; af = calloc(1, sizeof(*af)); ret->plugin_nc = (bg_plugin_common_t*)af; ret->plugin = ret->plugin_nc; af->set_input_format = set_input_format_ladspa; af->connect_input_port = connect_input_port_ladspa; af->get_output_format = get_output_format_ladspa; af->read_audio = read_audio_ladspa; af->reset = reset_ladspa; if(info->parameters) { ret->plugin_nc->get_parameters = get_parameters_ladspa; ret->plugin_nc->set_parameter = set_parameter_ladspa; } priv = calloc(1, sizeof(*priv)); ret->priv = priv; priv->parameters = info->parameters; desc_func = dlsym(ret->dll_handle, "ladspa_descriptor"); if(!desc_func) { bg_log(BG_LOG_ERROR, LOG_DOMAIN, "No symbol \"ladspa_descriptor\" found: %s", dlerror()); return 0; } priv->desc = desc_func(info->index); if(priv->desc->Properties & LADSPA_PROPERTY_INPLACE_BROKEN) priv->inplace_broken = 1; priv->config_ports = calloc(priv->desc->PortCount, sizeof(*priv->config_ports)); // lp->Instance = count_ports(priv->desc, &priv->num_in_ports, &priv->num_out_ports, &priv->num_in_c_ports, &priv->num_out_c_ports); if(priv->num_in_ports) priv->in_ports = malloc(priv->num_in_ports* sizeof(*priv->in_ports)); if(priv->num_out_ports) priv->out_ports = malloc(priv->num_out_ports* sizeof(*priv->out_ports)); if(priv->num_in_c_ports) priv->in_c_ports = malloc(priv->num_in_c_ports* sizeof(*priv->in_c_ports)); if(priv->num_out_c_ports) priv->out_c_ports = malloc(priv->num_out_c_ports* sizeof(*priv->out_c_ports)); for(i = 0; i < priv->desc->PortCount; i++) { if(LADSPA_IS_PORT_AUDIO(priv->desc->PortDescriptors[i])) { if(LADSPA_IS_PORT_INPUT(priv->desc->PortDescriptors[i])) priv->in_ports[in_port_index++] = i; else if(LADSPA_IS_PORT_OUTPUT(priv->desc->PortDescriptors[i])) priv->out_ports[out_port_index++] = i; } else if(LADSPA_IS_PORT_CONTROL(priv->desc->PortDescriptors[i])) { if(LADSPA_IS_PORT_INPUT(priv->desc->PortDescriptors[i])) priv->in_c_ports[in_c_port_index++] = i; else if(LADSPA_IS_PORT_OUTPUT(priv->desc->PortDescriptors[i])) priv->out_c_ports[out_c_port_index++] = i; } } return 1; } #define FREE(p) if(p) free(p) void bg_ladspa_unload(bg_plugin_handle_t * h) { ladspa_priv_t * lp; lp = (ladspa_priv_t *)h->priv; FREE(lp->config_ports); FREE(lp->in_ports); FREE(lp->out_ports); FREE(lp->in_c_ports); FREE(lp->out_c_ports); cleanup_ladspa(lp); free(h->plugin_nc); free(lp); } #undef FREE gmerlin-1.2.0~dfsg/lib/cfg_item.c0000644000175000017500000001347111764363410016573 0ustar alessioalessio/***************************************************************** * gmerlin - a general purpose multimedia framework and applications * * Copyright (c) 2001 - 2011 Members of the Gmerlin project * gmerlin-general@lists.sourceforge.net * http://gmerlin.sourceforge.net * * 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 of the License, 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 this program. If not, see . * *****************************************************************/ #include #include #include #include #include bg_cfg_item_t * bg_cfg_item_create_empty(const char * name) { bg_cfg_item_t * ret = calloc(1, sizeof(*ret)); ret->name = bg_strdup(ret->name, name); return ret; } bg_cfg_item_t * bg_cfg_item_create(const bg_parameter_info_t * info, bg_parameter_value_t * value) { bg_cfg_type_t type = BG_PARAMETER_CHECKBUTTON; // kee gcc quiet bg_cfg_item_t * ret; switch(info->type) { case BG_PARAMETER_CHECKBUTTON: case BG_PARAMETER_INT: case BG_PARAMETER_SLIDER_INT: type = BG_CFG_INT; break; case BG_PARAMETER_FLOAT: case BG_PARAMETER_SLIDER_FLOAT: type = BG_CFG_FLOAT; break; case BG_PARAMETER_COLOR_RGB: case BG_PARAMETER_COLOR_RGBA: type = BG_CFG_COLOR; break; case BG_PARAMETER_STRING: case BG_PARAMETER_STRINGLIST: case BG_PARAMETER_FONT: case BG_PARAMETER_DEVICE: case BG_PARAMETER_FILE: case BG_PARAMETER_DIRECTORY: case BG_PARAMETER_MULTI_MENU: case BG_PARAMETER_MULTI_LIST: case BG_PARAMETER_MULTI_CHAIN: type = BG_CFG_STRING; break; case BG_PARAMETER_STRING_HIDDEN: type = BG_CFG_STRING_HIDDEN; break; case BG_PARAMETER_TIME: type = BG_CFG_TIME; break; case BG_PARAMETER_POSITION: type = BG_CFG_POSITION; break; case BG_PARAMETER_SECTION: case BG_PARAMETER_BUTTON: return NULL; break; } ret = calloc(1, sizeof(*ret)); ret->type = type; ret->name = bg_strdup(ret->name, info->name); switch(ret->type) { case BG_CFG_INT: if(value) ret->value.val_i = value->val_i; else ret->value.val_i = info->val_default.val_i; break; case BG_CFG_TIME: if(value) ret->value.val_time = value->val_time; else ret->value.val_time = info->val_default.val_time; break; case BG_CFG_FLOAT: if(value) ret->value.val_f = value->val_f; else ret->value.val_f = info->val_default.val_f; break; case BG_CFG_COLOR: if(value) { ret->value.val_color[0] = value->val_color[0]; ret->value.val_color[1] = value->val_color[1]; ret->value.val_color[2] = value->val_color[2]; ret->value.val_color[3] = value->val_color[3]; } else { ret->value.val_color[0] = info->val_default.val_color[0]; ret->value.val_color[1] = info->val_default.val_color[1]; ret->value.val_color[2] = info->val_default.val_color[2]; ret->value.val_color[3] = info->val_default.val_color[3]; } break; case BG_CFG_STRING: case BG_CFG_STRING_HIDDEN: if(value && value->val_str) { ret->value.val_str = bg_strdup(ret->value.val_str, value->val_str); } else if(info->val_default.val_str) { ret->value.val_str = bg_strdup(ret->value.val_str, info->val_default.val_str); } break; case BG_CFG_POSITION: if(value) { ret->value.val_pos[0] = value->val_pos[0]; ret->value.val_pos[1] = value->val_pos[1]; } else { ret->value.val_pos[0] = info->val_default.val_pos[0]; ret->value.val_pos[1] = info->val_default.val_pos[1]; } } return ret; } void bg_cfg_destroy_item(bg_cfg_item_t * item) { free(item->name); switch(item->type) { case BG_CFG_STRING: case BG_CFG_STRING_HIDDEN: if(item->value.val_str) free(item->value.val_str); default: break; } free(item); } void bg_cfg_item_to_parameter(bg_cfg_item_t * src, bg_parameter_info_t * info) { memset(info, 0, sizeof(*info)); info->name = src->name; switch(src->type) { case BG_CFG_INT: info->type = BG_PARAMETER_INT; break; case BG_CFG_FLOAT: info->type = BG_PARAMETER_FLOAT; break; case BG_CFG_STRING: info->type = BG_PARAMETER_STRING; break; case BG_CFG_STRING_HIDDEN: info->type = BG_PARAMETER_STRING_HIDDEN; break; case BG_CFG_COLOR: info->type = BG_PARAMETER_COLOR_RGBA; break; case BG_CFG_TIME: /* int64 */ info->type = BG_PARAMETER_TIME; break; case BG_CFG_POSITION: info->type = BG_PARAMETER_POSITION; break; } } void bg_cfg_item_transfer(bg_cfg_item_t * src, bg_cfg_item_t * dst) { bg_parameter_info_t info; bg_cfg_item_to_parameter(src, &info); bg_parameter_value_copy(&dst->value, &src->value, &info); } bg_cfg_item_t * bg_cfg_item_copy(bg_cfg_item_t * src) { bg_cfg_item_t * ret; ret = calloc(1, sizeof(*ret)); ret->name = bg_strdup(ret->name, src->name); ret->type = src->type; bg_cfg_item_transfer(src, ret); return ret; } gmerlin-1.2.0~dfsg/lib/charset.c0000644000175000017500000000666411764363410016455 0ustar alessioalessio/***************************************************************** * gmerlin - a general purpose multimedia framework and applications * * Copyright (c) 2001 - 2011 Members of the Gmerlin project * gmerlin-general@lists.sourceforge.net * http://gmerlin.sourceforge.net * * 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 of the License, 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 this program. If not, see . * *****************************************************************/ #include #include #include #include #include #include #include #include #define LOG_DOMAIN "charset" struct bg_charset_converter_s { iconv_t cd; }; bg_charset_converter_t * bg_charset_converter_create(const char * in_charset, const char * out_charset) { bg_charset_converter_t * ret = calloc(1, sizeof(*ret)); ret->cd = iconv_open(out_charset, in_charset); return ret; } void bg_charset_converter_destroy(bg_charset_converter_t * cnv) { iconv_close(cnv->cd); free(cnv); } #define BYTES_INCREMENT 10 static char * do_convert(iconv_t cd, char * in_string, int len, int * out_len) { char * ret; char *inbuf; char *outbuf; int alloc_size; int output_pos; size_t inbytesleft; size_t outbytesleft; int done = 0; alloc_size = len + BYTES_INCREMENT; inbytesleft = len; outbytesleft = alloc_size; ret = malloc(alloc_size); inbuf = in_string; outbuf = ret; while(!done) { if(iconv(cd, &inbuf, &inbytesleft, &outbuf, &outbytesleft) == (size_t)-1) { switch(errno) { case E2BIG: output_pos = (int)(outbuf - ret); alloc_size += BYTES_INCREMENT; outbytesleft += BYTES_INCREMENT; ret = realloc(ret, alloc_size); outbuf = &ret[output_pos]; break; case EILSEQ: bg_log(BG_LOG_ERROR, LOG_DOMAIN, "Invalid Multibyte sequence"); done = 1; break; case EINVAL: bg_log(BG_LOG_ERROR, LOG_DOMAIN, "Incomplete Multibyte sequence"); done = 1; break; } } if(!inbytesleft) break; } /* Zero terminate */ output_pos = (int)(outbuf - ret); if(outbytesleft < 4) { alloc_size+=4; ret = realloc(ret, alloc_size); outbuf = &ret[output_pos]; } outbuf[0] = '\0'; outbuf[1] = '\0'; outbuf[2] = '\0'; outbuf[3] = '\0'; if(out_len) *out_len = outbuf - ret; return ret; } char * bg_convert_string(bg_charset_converter_t * cnv, const char * str, int len, int * out_len) { char * ret; char * tmp_string; if(len < 0) len = strlen(str); tmp_string = malloc(len+1); memcpy(tmp_string, str, len); tmp_string[len] = '\0'; ret = do_convert(cnv->cd, tmp_string, len, out_len); free(tmp_string); return ret; } gmerlin-1.2.0~dfsg/lib/pluginfuncs.c0000644000175000017500000000676411764363410017362 0ustar alessioalessio/***************************************************************** * gmerlin - a general purpose multimedia framework and applications * * Copyright (c) 2001 - 2011 Members of the Gmerlin project * gmerlin-general@lists.sourceforge.net * http://gmerlin.sourceforge.net * * 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 of the License, 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 this program. If not, see . * *****************************************************************/ #include #include #include #include #include int bg_encoder_cb_create_output_file(bg_encoder_callbacks_t * cb, const char * filename) { if(cb && cb->create_output_file) return cb->create_output_file(cb->data, filename); else return 1; } int bg_encoder_cb_create_temp_file(bg_encoder_callbacks_t * cb, const char * filename) { if(cb && cb->create_temp_file) return cb->create_temp_file(cb->data, filename); else return 1; } int bg_iw_cb_create_output_file(bg_iw_callbacks_t * cb, const char * filename) { if(cb && cb->create_output_file) return cb->create_output_file(cb->data, filename); else return 1; } int bg_encoder_set_framerate_parameter(bg_encoder_framerate_t * f, const char * name, const bg_parameter_value_t * val) { if(!strcmp(name, "default_timescale")) { f->timescale = val->val_i; return 1; } else if(!strcmp(name, "default_frame_duration")) { f->frame_duration = val->val_i; return 1; } return 0; } void bg_encoder_set_framerate(const bg_encoder_framerate_t * f, gavl_video_format_t * format) { if(format->framerate_mode != GAVL_FRAMERATE_CONSTANT) { format->framerate_mode = GAVL_FRAMERATE_CONSTANT; format->timescale = f->timescale; format->frame_duration = f->frame_duration; } } void bg_encoder_set_framerate_nearest(const bg_encoder_framerate_t * rate_default, const bg_encoder_framerate_t * rates_supported, gavl_video_format_t * format) { int i, min_index = 0; double diff = 0.0, diff_min = 0.0; double rate_d; /* Set default is we don't already have one */ bg_encoder_set_framerate(rate_default, format); /* Set to nearest value */ rate_d = (double)(format->timescale) / (double)(format->frame_duration); i = 0; while(rates_supported[i].timescale) { diff = fabs(rate_d - (double)(rates_supported[i].timescale) / (double)(rates_supported[i].frame_duration)); if(!i || (diff < diff_min)) { diff_min = diff; min_index = i; } i++; } format->timescale = rates_supported[min_index].timescale; format->frame_duration = rates_supported[min_index].frame_duration; } gmerlin-1.2.0~dfsg/lib/lcdproc.c0000644000175000017500000005644511764363410016454 0ustar alessioalessio/***************************************************************** * gmerlin - a general purpose multimedia framework and applications * * Copyright (c) 2001 - 2011 Members of the Gmerlin project * gmerlin-general@lists.sourceforge.net * http://gmerlin.sourceforge.net * * 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 of the License, 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 this program. If not, see . * *****************************************************************/ #include #include #include #include #include #include #include #include #include /* pid_t */ #include #include #include #define LOG_DOMAIN "lcdproc" static const char * const formats_name = "formats"; static const char * const name_time_name = "name_time"; static const char * const descriptions_name = "descriptions"; static const char * const audio_format_name = "audio_format"; static const char * const video_format_name = "video_format"; static const char * const audio_description_name = "audio_description"; static const char * const video_description_name = "video_description"; static const char * const name_name = "name"; static const char * const time_name = "time"; struct bg_lcdproc_s { int player_state; int fd; int enable_lcdproc; int display_name_time; int display_formats; int display_descriptions; char * answer; int answer_alloc; /* Values used for the current connection */ char * hostname; int port; /* Config values */ char * hostname_cfg; int port_cfg; /* Connection to the player */ bg_msg_queue_t * queue; pthread_mutex_t config_mutex; /* screens */ int have_name_time; int have_formats; int have_descriptions; /* Thread handling */ pthread_t thread; pthread_mutex_t state_mutex; int is_running; int do_stop; /* Screen size (got from server welcome line) */ int width, height; bg_player_t * player; }; static const bg_parameter_info_t parameters[] = { { .name = "enable_lcdproc", .long_name = TRS("Enable LCDproc"), .type = BG_PARAMETER_CHECKBUTTON, .val_default = { .val_i = 0 }, }, { .name = "hostname", .long_name = TRS("Hostname"), .type = BG_PARAMETER_STRING, .val_default = { .val_str = "localhost" }, }, { .name = "port", .long_name = TRS("Port"), .type = BG_PARAMETER_INT, .val_min = { .val_i = 1024 }, .val_max = { .val_i = 65535 }, .val_default = { .val_i = 13666 }, }, { .name = "display_name_time", .long_name = TRS("Display track name and time"), .type = BG_PARAMETER_CHECKBUTTON, .val_default = { .val_i = 1 }, }, { .name = "display_formats", .long_name = TRS("Display audio/video formats"), .type = BG_PARAMETER_CHECKBUTTON, .val_default = { .val_i = 1 }, }, { .name = "display_descriptions", .long_name = TRS("Display audio/video descriptions"), .type = BG_PARAMETER_CHECKBUTTON, .val_default = { .val_i = 1 }, }, { /* End of parameters */ } }; bg_lcdproc_t * bg_lcdproc_create(bg_player_t * player) { bg_lcdproc_t * ret; ret = calloc(1, sizeof(*ret)); ret->fd = -1; ret->queue = bg_msg_queue_create(); pthread_mutex_init(&ret->config_mutex, NULL); pthread_mutex_init(&ret->state_mutex, NULL); ret->player = player; return ret; } static int send_command(bg_lcdproc_t * l, char * command) { char nl = '\n'; // bg_log(BG_LOG_DEBUG, LOG_DOMAIN, "Sending command %s", command); if(!bg_socket_write_data(l->fd, (uint8_t*)command, strlen(command))) { bg_log(BG_LOG_ERROR, LOG_DOMAIN, "Sending command failed"); return 0; } if(!bg_socket_write_data(l->fd, (uint8_t*)&nl, 1)) { bg_log(BG_LOG_ERROR, LOG_DOMAIN, "Sending command failed"); return 0; } while(1) { if(!bg_socket_read_line(l->fd, &l->answer, &l->answer_alloc, 0)) { // bg_log(BG_LOG_ERROR, LOG_DOMAIN, "Reading answer failed"); // return 0; break; } // bg_log(BG_LOG_DEBUG, LOG_DOMAIN, "Got answer %s", l->answer); if(!strncmp(l->answer, "success", 7)) break; else if(!strncmp(l->answer, "listen", 6)) break; else if(!strncmp(l->answer, "huh", 3)) { bg_log(BG_LOG_ERROR, LOG_DOMAIN, "Command \"%s\" not unserstood by server", command); return 0; } } return 1; } /* Here comes the real working stuff */ static int do_connect(bg_lcdproc_t* l) { int i; char ** answer_args; char * cmd = NULL; bg_host_address_t * addr = bg_host_address_create(); if(!bg_host_address_set(addr, l->hostname_cfg, l->port_cfg, SOCK_STREAM)) { bg_log(BG_LOG_ERROR, LOG_DOMAIN, "Could not resolve adress for: %s", l->hostname_cfg); goto fail; } l->fd = bg_socket_connect_inet(addr, 500); if(l->fd < 0) { bg_log(BG_LOG_ERROR, LOG_DOMAIN, "Could not connect to server at %s:%d", l->hostname_cfg, l->port_cfg); goto fail; } // bg_log(BG_LOG_DEBUG, LOG_DOMAIN, "Sending hello"); /* Send hello and get answer */ if(!bg_socket_write_data(l->fd, (uint8_t*)"hello\n", 6)) { bg_log(BG_LOG_ERROR, LOG_DOMAIN, "Could not send hello message"); goto fail; } if(!bg_socket_read_line(l->fd, &l->answer, &l->answer_alloc, 1000)) { bg_log(BG_LOG_ERROR, LOG_DOMAIN, "Could not get server welcome line"); goto fail; } // bg_log(BG_LOG_DEBUG, LOG_DOMAIN, "Got welcome line: %s", l->answer); if(strncmp(l->answer, "connect LCDproc", 15)) { bg_log(BG_LOG_ERROR, LOG_DOMAIN, "Invalid answer: %s", l->answer); goto fail; } answer_args = bg_strbreak(l->answer, ' '); i = 0; while(answer_args[i]) { if(!strcmp(answer_args[i], "wid")) { i++; l->width = atoi(answer_args[i]); } else if(!strcmp(answer_args[i], "hgt")) { i++; l->height = atoi(answer_args[i]); } i++; } bg_strbreak_free(answer_args); /* Set client attributes */ cmd = bg_sprintf("client_set name {gmerlin%d}", getpid()); if(!send_command(l, cmd)) goto fail; free(cmd); bg_log(BG_LOG_INFO, LOG_DOMAIN, "Connection to server established, display size: %dx%d", l->width, l->height); return 1; fail: bg_host_address_destroy(addr); if(cmd) free(cmd); if(l->fd >= 0) { bg_log(BG_LOG_INFO, LOG_DOMAIN, "Connection to server closed due to error"); close(l->fd); l->fd = -1; } return 0; } static int set_name(bg_lcdproc_t * l, const char * name) { char * command; if(strlen(name) > l->width) command = bg_sprintf("widget_set %s %s 1 2 %d 3 m 1 {%s *** }", name_time_name, name_name, l->width, name); else command = bg_sprintf("widget_set %s %s 1 2 %d 3 m 1 {%s}", name_time_name, name_name, l->width, name); if(!send_command(l, command)) goto fail; free(command); return 1; fail: free(command); return 0; } static int set_time(bg_lcdproc_t * l, gavl_time_t time) { char * command, *format; char buffer[16]; /* MUST be larger than GAVL_TIME_STRING_LEN */ if(time == GAVL_TIME_UNDEFINED) { gethostname(buffer, 16); command = bg_sprintf("widget_set %s %s 1 1 {%s}", name_time_name, time_name, buffer); if(!send_command(l, command)) goto fail; } else { gavl_time_prettyprint(time, buffer); format = bg_sprintf("widget_set %%s %%s 1 1 {T: %%%ds}", l->width - 3); command = bg_sprintf(format, name_time_name, time_name, buffer); if(!send_command(l, command)) goto fail; free(format); } free(command); return 1; fail: free(command); return 0; } static int create_name_time(bg_lcdproc_t * l) { // char time_buf[GAVL_TIME_STRING_LEN]; char * command; command = bg_sprintf("screen_add %s", name_time_name); if(!send_command(l, command)) goto fail; free(command); command = bg_sprintf("screen_set %s -heartbeat off", name_time_name); if(!send_command(l, command)) goto fail; free(command); /* Time display */ command = bg_sprintf("widget_add %s %s string", name_time_name, time_name); if(!send_command(l, command)) goto fail; free(command); set_time(l, GAVL_TIME_UNDEFINED); /* Name display */ command = bg_sprintf("widget_add %s %s scroller", name_time_name, name_name); if(!send_command(l, command)) goto fail; free(command); set_name(l, PACKAGE"-"VERSION); l->have_name_time = 1; return 1; fail: free(command); return 0; } static int destroy_name_time(bg_lcdproc_t * l) { char * command; command = bg_sprintf("screen_del %s", name_time_name); if(!send_command(l, command)) goto fail; free(command); l->have_name_time = 0; return 1; fail: free(command); return 0; } static int set_audio_format(bg_lcdproc_t * l, gavl_audio_format_t * f) { char * command; char * format_string; if(!f) { command = bg_sprintf("widget_set %s %s 1 1 16 2 m 1 {Audio: none}", formats_name, audio_format_name); } else { if(f->num_channels == 1) format_string = bg_sprintf("%d Hz Mono", f->samplerate); else if(f->num_channels == 2) format_string = bg_sprintf("%d Hz Stereo", f->samplerate); else format_string = bg_sprintf("%d Hz %d Ch", f->samplerate, f->num_channels); if(strlen(format_string) > l->width) command = bg_sprintf("widget_set %s %s 1 1 16 2 m 1 {%s *** }", formats_name, audio_format_name, format_string); else command = bg_sprintf("widget_set %s %s 1 1 16 2 m 1 {%s}", formats_name, audio_format_name, format_string); free(format_string); } if(!send_command(l, command)) goto fail; free(command); return 1; fail: free(command); return 0; } static int set_video_format(bg_lcdproc_t * l, gavl_video_format_t * f) { char * command, *format_string; if(!f) { command = bg_sprintf("widget_set %s %s 1 2 16 3 m 1 {Video: none}", formats_name, video_format_name); } else { if(f->framerate_mode == GAVL_FRAMERATE_CONSTANT) { format_string = bg_sprintf("%dx%d %.2f fps", f->image_width, f->image_height, (float)(f->timescale)/ (float)(f->frame_duration)); } else { format_string = bg_sprintf("%dx%d", f->image_width, f->image_height); } if(strlen(format_string) > l->width) command = bg_sprintf("widget_set %s %s 1 2 16 3 m 1 {%s *** }", formats_name, video_format_name, format_string); else command = bg_sprintf("widget_set %s %s 1 2 16 3 m 1 {%s}", formats_name, video_format_name, format_string); free(format_string); } if(!send_command(l, command)) goto fail; free(command); return 1; fail: free(command); return 0; } static int create_formats(bg_lcdproc_t * l) { char * command; command = bg_sprintf("screen_add %s", formats_name); if(!send_command(l, command)) goto fail; free(command); command = bg_sprintf("screen_set %s -heartbeat off", formats_name); if(!send_command(l, command)) goto fail; free(command); /* Audio format */ command = bg_sprintf("widget_add %s %s scroller", formats_name, audio_format_name); if(!send_command(l, command)) goto fail; free(command); set_audio_format(l, NULL); /* Video format */ command = bg_sprintf("widget_add %s %s scroller", formats_name, video_format_name); if(!send_command(l, command)) goto fail; free(command); set_video_format(l, NULL); l->have_formats = 1; return 1; fail: free(command); return 0; } static int destroy_formats(bg_lcdproc_t * l) { char * command; command = bg_sprintf("screen_del %s", formats_name); if(!send_command(l, command)) goto fail; free(command); l->have_formats = 0; return 1; fail: free(command); return 0; } static int set_audio_description(bg_lcdproc_t * l, gavl_metadata_t * m) { char * desc; char * command; const char * format_str = NULL; int bitrate = 0; if(m) { format_str = gavl_metadata_get(m, GAVL_META_FORMAT); if(!gavl_metadata_get_int(m, GAVL_META_BITRATE, &bitrate)) bitrate = 0; } if(!format_str) desc = NULL; else { if(bitrate) desc = bg_sprintf("%s %d kbps", format_str, bitrate); else desc = bg_sprintf("%s", format_str); } if(!desc) { command = bg_sprintf("widget_set %s %s 1 1 16 2 m 1 {A: Off}", descriptions_name, audio_description_name); } else { if(strlen(desc) > l->width) command = bg_sprintf("widget_set %s %s 1 1 16 2 m 1 {A: %s *** }", descriptions_name, audio_description_name, desc); else command = bg_sprintf("widget_set %s %s 1 1 16 2 m 1 {A: %s}", descriptions_name, audio_description_name, desc); free(desc); } if(!send_command(l, command)) goto fail; free(command); return 1; fail: free(command); return 0; } static int set_video_description(bg_lcdproc_t * l, gavl_metadata_t * m) { char * desc; const char * format_str = NULL; char * command; if(m) format_str = gavl_metadata_get(m, GAVL_META_FORMAT); if(!format_str) desc = NULL; else { desc = bg_sprintf("%s", format_str); } if(!desc) { command = bg_sprintf("widget_set %s %s 1 2 16 3 m 1 {V: Off}", descriptions_name, video_description_name); } else { if(strlen(desc) > l->width) command = bg_sprintf("widget_set %s %s 1 2 16 3 m 1 {V: %s *** }", descriptions_name, video_description_name, desc); else command = bg_sprintf("widget_set %s %s 1 2 16 3 m 1 {V: %s}", descriptions_name, video_description_name, desc); free(desc); } if(!send_command(l, command)) goto fail; free(command); return 1; fail: free(command); return 0; } static int create_descriptions(bg_lcdproc_t * l) { char * command; command = bg_sprintf("screen_add %s", descriptions_name); if(!send_command(l, command)) goto fail; free(command); command = bg_sprintf("screen_set %s -heartbeat off", descriptions_name); if(!send_command(l, command)) goto fail; free(command); /* Audio description */ command = bg_sprintf("widget_add %s %s scroller", descriptions_name, audio_description_name); if(!send_command(l, command)) goto fail; free(command); set_audio_description(l, NULL); /* Video format */ command = bg_sprintf("widget_add %s %s scroller", descriptions_name, video_description_name); if(!send_command(l, command)) goto fail; free(command); set_video_description(l, NULL); l->have_descriptions = 1; return 1; fail: free(command); return 0; } static int destroy_descriptions(bg_lcdproc_t * l) { char * command; command = bg_sprintf("screen_del %s", descriptions_name); if(!send_command(l, command)) goto fail; free(command); l->have_descriptions = 1; return 1; fail: free(command); return 0; } static void * thread_func(void * data) { int result = 1; int arg_i_1; char * arg_str_1; int id; gavl_time_t time; bg_msg_t * msg; bg_lcdproc_t * l = (bg_lcdproc_t *)data; gavl_time_t delay_time = GAVL_TIME_SCALE / 20; gavl_audio_format_t audio_format; gavl_video_format_t video_format; /* We add and remove our message queue at the beginning and end of the thread */ bg_player_add_message_queue(l->player, l->queue); while(1) { /* Check if we must stop the thread */ pthread_mutex_lock(&l->state_mutex); if(l->do_stop) { pthread_mutex_unlock(&l->state_mutex); break; } pthread_mutex_unlock(&l->state_mutex); /* Check whether to process a message */ pthread_mutex_lock(&l->config_mutex); while((msg = bg_msg_queue_try_lock_read(l->queue))) { if(l->fd < 0) { gavl_time_delay(&delay_time); continue; } id = bg_msg_get_id(msg); switch(id) { case BG_PLAYER_MSG_TIME_CHANGED: if(l->have_name_time) { if(l->player_state != BG_PLAYER_STATE_STOPPED) time = bg_msg_get_arg_time(msg, 0); else time = GAVL_TIME_UNDEFINED; result = set_time(l, time); } break; case BG_PLAYER_MSG_STATE_CHANGED: arg_i_1 = bg_msg_get_arg_int(msg, 0); l->player_state = arg_i_1; switch(arg_i_1) { case BG_PLAYER_STATE_STOPPED: case BG_PLAYER_STATE_CHANGING: if(l->have_formats) { result = (set_audio_format(l, NULL) && set_video_format(l, NULL)); } if(l->have_descriptions) { result = (set_audio_description(l, NULL) && set_video_description(l, NULL)); } if(l->have_name_time) { result = (set_time(l, GAVL_TIME_UNDEFINED) && set_name(l, PACKAGE"-"VERSION)); } break; } break; case BG_PLAYER_MSG_TRACK_NAME: if(l->have_name_time) { arg_str_1 = bg_msg_get_arg_string(msg, 0); result = set_name(l, arg_str_1); free(arg_str_1); } break; case BG_PLAYER_MSG_AUDIO_STREAM_INFO: if(l->have_descriptions) { gavl_metadata_t m; gavl_metadata_init(&m); bg_msg_get_arg_metadata(msg, 1, &m); result = set_audio_description(l, &m); gavl_metadata_free(&m); } break; case BG_PLAYER_MSG_VIDEO_STREAM_INFO: if(l->have_descriptions) { gavl_metadata_t m; gavl_metadata_init(&m); bg_msg_get_arg_metadata(msg, 1, &m); result = set_audio_description(l, &m); gavl_metadata_free(&m); } break; case BG_PLAYER_MSG_AUDIO_STREAM: if(l->have_formats) { bg_msg_get_arg_audio_format(msg, 1, &audio_format, NULL); result = set_audio_format(l, &audio_format); } break; case BG_PLAYER_MSG_VIDEO_STREAM: if(l->have_formats) { bg_msg_get_arg_video_format(msg, 1, &video_format, NULL); result = set_video_format(l, &video_format); } break; } bg_msg_queue_unlock_read(l->queue); } pthread_mutex_unlock(&l->config_mutex); /* Sleep */ gavl_time_delay(&delay_time); if(!result && (l->fd >= 0)) { close(l->fd); bg_log(BG_LOG_INFO, LOG_DOMAIN, "Connection to server closed due to error"); l->fd = -1; } } bg_player_delete_message_queue(l->player, l->queue); return NULL; } static void start_thread(bg_lcdproc_t * l) { pthread_mutex_lock(&l->state_mutex); pthread_create(&l->thread, NULL, thread_func, l); l->is_running = 1; pthread_mutex_unlock(&l->state_mutex); } static void stop_thread(bg_lcdproc_t * l) { pthread_mutex_lock(&l->state_mutex); l->do_stop = 1; if(!l->is_running) { pthread_mutex_unlock(&l->state_mutex); return; } pthread_mutex_unlock(&l->state_mutex); pthread_join(l->thread, NULL); pthread_mutex_lock(&l->state_mutex); l->do_stop = 0; l->is_running = 0; pthread_mutex_unlock(&l->state_mutex); } #define FREE(p) if(l->p) free(l->p); void bg_lcdproc_destroy(bg_lcdproc_t* l) { stop_thread(l); FREE(answer); FREE(hostname); FREE(hostname_cfg); bg_msg_queue_destroy(l->queue); pthread_mutex_destroy(&l->config_mutex); pthread_mutex_destroy(&l->state_mutex); free(l); } /* * Config stuff. The function set_parameter automatically * starts and stops the thread */ const bg_parameter_info_t * bg_lcdproc_get_parameters(bg_lcdproc_t * l) { return parameters; } #define IPARAM(v) if(!strcmp(name, #v)) { l->v = val->val_i; } void bg_lcdproc_set_parameter(void * data, const char * name, const bg_parameter_value_t * val) { bg_lcdproc_t * l = (bg_lcdproc_t *)data; if(!name) { if(l->fd >= 0) stop_thread(l); /* Disable everything we don't want to show */ // if(!l-> /* Check wether to disconnect */ if((l->fd >= 0) && ((l->port != l->port_cfg) || strcmp(l->hostname, l->hostname_cfg) || !l->enable_lcdproc)) { close(l->fd); bg_log(BG_LOG_INFO, LOG_DOMAIN, "Server connection closed"); l->fd = -1; l->have_formats = 0; l->have_name_time = 0; l->have_descriptions = 0; } if(!l->enable_lcdproc) { return; } /* Switch off widgets we don't want */ if(!l->display_name_time && l->have_name_time) destroy_name_time(l); if(!l->display_formats && l->have_formats) destroy_formats(l); if(!l->display_descriptions && l->have_descriptions) destroy_descriptions(l); if(l->enable_lcdproc) { /* Check whether to reconnect */ if((l->fd < 0) && !do_connect(l)) return; if(l->display_name_time && !l->have_name_time) create_name_time(l); if(l->display_formats && !l->have_formats) create_formats(l); if(l->display_descriptions && !l->have_descriptions) create_descriptions(l); start_thread(l); } return; } if(!strcmp(name, "enable_lcdproc")) { l->enable_lcdproc = val->val_i; } else if(!strcmp(name, "hostname")) { l->hostname_cfg = bg_strdup(l->hostname_cfg, val->val_str); } else if(!strcmp(name, "port")) { l->port_cfg = val->val_i; } pthread_mutex_lock(&l->config_mutex); IPARAM(display_name_time); IPARAM(display_formats); IPARAM(display_descriptions); pthread_mutex_unlock(&l->config_mutex); } gmerlin-1.2.0~dfsg/lib/serialize.c0000644000175000017500000003727711764363410017017 0ustar alessioalessio/***************************************************************** * gmerlin - a general purpose multimedia framework and applications * * Copyright (c) 2001 - 2011 Members of the Gmerlin project * gmerlin-general@lists.sourceforge.net * http://gmerlin.sourceforge.net * * 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 of the License, 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 this program. If not, see . * *****************************************************************/ #include #include #include #include #include #define SERIALIZE_VERSION 0 /* Get/Set routines for structures */ static inline const uint8_t * get_8(const uint8_t * data, uint32_t * val) { *val = *data; data++; return data; } static inline const uint8_t * get_16(const uint8_t * data, uint32_t * val) { *val = ((data[0] << 8) | data[1]); data+=2; return data; } static inline const uint8_t * get_32(const uint8_t * data, uint32_t * val) { *val = ((data[0] << 24) | (data[1] << 16) | (data[2] << 8) | data[3]); data+=4; return data; } static inline const uint8_t * get_float(const uint8_t * data, float * val) { const uint8_t * ret; union { float f; uint32_t i; } v; ret = get_32(data, &v.i); *val = v.f; return ret; } static inline const uint8_t * get_64(const uint8_t * data, uint64_t * val) { *val = data[0]; *val <<= 8; *val |= data[1]; *val <<= 8; *val |= data[2]; *val <<= 8; *val |= data[3]; *val <<= 8; *val |= data[4]; *val <<= 8; *val |= data[5]; *val <<= 8; *val |= data[6]; *val <<= 8; *val |= data[7]; data+=8; return data; } static inline const uint8_t * get_str(const uint8_t * data, char ** val) { uint32_t len; const uint8_t * ret; ret = get_32(data, &len); if(len) { *val = malloc(len+1); memcpy(*val, ret, len); (*val)[len] = '\0'; } return ret + len; } static inline uint8_t * set_8(uint8_t * data, uint8_t val) { *data = val; data++; return data; } static inline uint8_t * set_16(uint8_t * data, uint16_t val) { data[0] = (val & 0xff00) >> 8; data[1] = (val & 0xff); data+=2; return data; } static inline uint8_t * set_32(uint8_t * data, uint32_t val) { data[0] = (val & 0xff000000) >> 24; data[1] = (val & 0xff0000) >> 16; data[2] = (val & 0xff00) >> 8; data[3] = (val & 0xff); data+=4; return data; } static inline uint8_t * set_float(uint8_t * data, float val) { uint8_t * ret; union { float f; uint32_t i; } v; v.f = val; ret = set_32(data, v.i); return ret; } static inline uint8_t * set_64(uint8_t * data, uint64_t val) { data[0] = (val & 0xff00000000000000LL) >> 56; data[1] = (val & 0x00ff000000000000LL) >> 48; data[2] = (val & 0x0000ff0000000000LL) >> 40; data[3] = (val & 0x000000ff00000000LL) >> 32; data[4] = (val & 0x00000000ff000000LL) >> 24; data[5] = (val & 0x0000000000ff0000LL) >> 16; data[6] = (val & 0x000000000000ff00LL) >> 8; data[7] = (val & 0x00000000000000ffLL); data+=8; return data; } #if 0 static int str_len(const char * str) { int ret = 4; if(str) ret += strlen(str); return ret; } #endif static inline uint8_t * set_str(uint8_t * data, const char * val) { uint32_t len; if(val) len = strlen(val); else len = 0; data = set_32(data, len); if(len) memcpy(data, val, len); return data + len; } int bg_serialize_audio_format(const gavl_audio_format_t * format, uint8_t * pos, int len) { int i; int len_needed = 2 + 25 + 8 * format->num_channels; if(len_needed > len) return len_needed; pos = set_16(pos, SERIALIZE_VERSION); #ifdef WORDS_BIGENDIAN pos = set_8(pos, 1); #else pos = set_8(pos, 0); #endif pos = set_32(pos, format->samples_per_frame); pos = set_32(pos, format->samplerate); pos = set_32(pos, format->num_channels); pos = set_8(pos, format->sample_format); pos = set_8(pos, format->interleave_mode); pos = set_float(pos, format->center_level); pos = set_float(pos, format->rear_level); for(i = 0; i < format->num_channels; i++) pos = set_8(pos, format->channel_locations[i]); return len_needed; } int bg_deserialize_audio_format(gavl_audio_format_t * format, const uint8_t * pos, int len, int * big_endian) { int i; uint32_t tmp; uint32_t version; pos = get_16(pos, &version); pos = get_8(pos, &tmp); *big_endian = tmp; pos = get_32(pos, &tmp); format->samples_per_frame = tmp; pos = get_32(pos, &tmp); format->samplerate = tmp; pos = get_32(pos, &tmp); format->num_channels = tmp; pos = get_8(pos, &tmp); format->sample_format = tmp; pos = get_8(pos, &tmp); format->interleave_mode = tmp; pos = get_float(pos, &format->center_level); pos = get_float(pos, &format->rear_level); for(i = 0; i < format->num_channels; i++) { pos = get_8(pos, &tmp); format->channel_locations[i] = tmp; } return 1; } int bg_serialize_video_format(const gavl_video_format_t * format, uint8_t * pos, int len) { int len_needed = 2 + 47; if(len < len_needed) return len_needed; pos = set_16(pos, SERIALIZE_VERSION); pos = set_32(pos, format->frame_width); pos = set_32(pos, format->frame_height); pos = set_32(pos, format->image_width); pos = set_32(pos, format->image_height); pos = set_32(pos, format->pixel_width); pos = set_32(pos, format->pixel_height); pos = set_32(pos, format->pixelformat); pos = set_32(pos, format->timescale); pos = set_32(pos, format->frame_duration); pos = set_8(pos, format->framerate_mode); pos = set_8(pos, format->interlace_mode); pos = set_8(pos, format->chroma_placement); pos = set_32(pos, format->timecode_format.int_framerate); pos = set_32(pos, format->timecode_format.flags); return len_needed; } int bg_deserialize_video_format(gavl_video_format_t * format, const uint8_t * pos, int len, int * big_endian) { uint32_t tmp; uint32_t version; pos = get_16(pos, &version); pos = get_32(pos, &tmp); format->frame_width = tmp; pos = get_32(pos, &tmp); format->frame_height = tmp; pos = get_32(pos, &tmp); format->image_width = tmp; pos = get_32(pos, &tmp); format->image_height = tmp; pos = get_32(pos, &tmp); format->pixel_width = tmp; pos = get_32(pos, &tmp); format->pixel_height = tmp; pos = get_32(pos, &tmp); format->pixelformat = tmp; pos = get_32(pos, &tmp); format->timescale = tmp; pos = get_32(pos, &tmp); format->frame_duration = tmp; pos = get_8(pos, &tmp); format->framerate_mode = tmp; pos = get_8(pos, &tmp); format->interlace_mode = tmp; pos = get_8(pos, &tmp); format->chroma_placement = tmp; pos = get_32(pos, &tmp); format->timecode_format.int_framerate = tmp; pos = get_32(pos, &tmp); format->timecode_format.flags = tmp; return 1; } /* Frames */ int bg_serialize_audio_frame_header(const gavl_audio_format_t * format, const gavl_audio_frame_t * frame, uint8_t * pos, int len) { int len_needed = 2 + /* Version */ 8 + /* timestamp */ 4; /* Duration */ if(len_needed > len) return len_needed; pos = set_16(pos, SERIALIZE_VERSION); pos = set_64(pos, frame->timestamp); pos = set_32(pos, frame->valid_samples); return len_needed; } int bg_deserialize_audio_frame_header(const gavl_audio_format_t * format, gavl_audio_frame_t * frame, const uint8_t * pos, int len) { uint32_t version; pos = get_16(pos, &version); pos = get_64(pos, (uint64_t*)(&frame->timestamp)); pos = get_32(pos, (uint32_t*)(&frame->valid_samples)); return 1; } int bg_serialize_video_frame_header(const gavl_video_format_t * format, const gavl_video_frame_t * frame, uint8_t * pos, int len) { int len_needed = 2 + /* Version */ 8 + /* timestamp */ 8; /* Duration */ if(format->timecode_format.int_framerate) len_needed += 8; /* Timecode */ if(format->interlace_mode == GAVL_INTERLACE_MIXED) len_needed += 1; /* Interlace mode */ if(len_needed > len) return len_needed; pos = set_16(pos, SERIALIZE_VERSION); pos = set_64(pos, frame->timestamp); pos = set_64(pos, frame->duration); if(format->timecode_format.int_framerate) pos = set_64(pos, frame->timecode); if(format->interlace_mode == GAVL_INTERLACE_MIXED) pos = set_8(pos, frame->interlace_mode); return len_needed; } int bg_deserialize_video_frame_header(const gavl_video_format_t * format, gavl_video_frame_t * frame, const uint8_t * pos, int len) { uint32_t tmp; uint32_t version; pos = get_16(pos, &version); pos = get_64(pos, (uint64_t*)(&frame->timestamp)); pos = get_64(pos, (uint64_t*)(&frame->duration)); if(format->timecode_format.int_framerate) pos = get_64(pos, (uint64_t*)(&frame->timecode)); if(format->interlace_mode == GAVL_INTERLACE_MIXED) { pos = get_8(pos, &tmp); frame->interlace_mode = tmp; } return 1; } int bg_serialize_audio_frame(const gavl_audio_format_t * format, const gavl_audio_frame_t * frame, bg_serialize_write_callback_t cb, void * cb_data) { int len, bytes_per_sample, i; bytes_per_sample = gavl_bytes_per_sample(format->sample_format); switch(format->interleave_mode) { case GAVL_INTERLEAVE_NONE: len = bytes_per_sample * frame->valid_samples; for(i = 0; i < format->num_channels; i++) { if(cb(cb_data, frame->channels.u_8[i], len) < len) return 0; } break; case GAVL_INTERLEAVE_2: len = bytes_per_sample * frame->valid_samples * 2; for(i = 0; i < format->num_channels/2; i++) { if(cb(cb_data, frame->channels.u_8[2*i], len) < len) return 0; } if(format->num_channels % 2) { len = bytes_per_sample * frame->valid_samples; if(cb(cb_data, frame->channels.u_8[format->num_channels-1], len) < len) return 0; } break; case GAVL_INTERLEAVE_ALL: len = bytes_per_sample * frame->valid_samples * format->num_channels; if(cb(cb_data, frame->samples.u_8, len) < len) return 0; break; } return 1; } int bg_deserialize_audio_frame(gavl_dsp_context_t * ctx, const gavl_audio_format_t * format, gavl_audio_frame_t * frame, bg_serialize_read_callback_t cb, void * cb_data, int big_endian) { int len, bytes_per_sample, i; bytes_per_sample = gavl_bytes_per_sample(format->sample_format); switch(format->interleave_mode) { case GAVL_INTERLEAVE_NONE: len = bytes_per_sample * frame->valid_samples; for(i = 0; i < format->num_channels; i++) { if(cb(cb_data, frame->channels.u_8[i], len) < len) return 0; } break; case GAVL_INTERLEAVE_2: len = bytes_per_sample * frame->valid_samples * 2; for(i = 0; i < format->num_channels/2; i++) { if(cb(cb_data, frame->channels.u_8[2*i], len) < len) return 0; } if(format->num_channels % 2) { len = bytes_per_sample * frame->valid_samples; if(cb(cb_data, frame->channels.u_8[format->num_channels-1], len) < len) return 0; } break; case GAVL_INTERLEAVE_ALL: len = bytes_per_sample * frame->valid_samples * format->num_channels; if(cb(cb_data, frame->samples.u_8, len) < len) return 0; break; } #ifndef WORDS_BIGENDIAN if(big_endian) gavl_dsp_audio_frame_swap_endian(ctx, frame, format); #else if(!big_endian) gavl_dsp_audio_frame_swap_endian(ctx, frame, format); #endif return 1; } static int write_plane(const uint8_t * plane, int stride, int bytes_per_line, int height, bg_serialize_write_callback_t cb, void * cb_data) { int i; for(i = 0; i < height; i++) { if(cb(cb_data, plane, bytes_per_line) < bytes_per_line) return 0; plane += stride; } return 1; } int bg_serialize_video_frame(const gavl_video_format_t * format, const gavl_video_frame_t * frame, bg_serialize_write_callback_t cb, void * cb_data) { int i; int num_planes; int bytes_per_line; int sub_h, sub_v; num_planes = gavl_pixelformat_num_planes(format->pixelformat); if(num_planes == 1) { bytes_per_line = gavl_pixelformat_bytes_per_pixel(format->pixelformat) * format->image_width; return write_plane(frame->planes[0], frame->strides[0], bytes_per_line, format->image_height, cb, cb_data); } else { int h = format->image_height; bytes_per_line = format->image_width * gavl_pixelformat_bytes_per_component(format->pixelformat); gavl_pixelformat_chroma_sub(format->pixelformat, &sub_h, &sub_v); for(i = 0; i < num_planes; i++) { if(!write_plane(frame->planes[i], frame->strides[i], bytes_per_line, h, cb, cb_data)) return 0; if(!i) { h /= sub_v; bytes_per_line /= sub_h; } } } return 1; } /* */ static int read_plane(uint8_t * plane, int stride, int bytes_per_line, int height, bg_serialize_read_callback_t cb, void * cb_data) { int i; for(i = 0; i < height; i++) { if(cb(cb_data, plane, bytes_per_line) < bytes_per_line) return 0; plane += stride; } return 1; } int bg_deserialize_video_frame(gavl_dsp_context_t * ctx, const gavl_video_format_t * format, gavl_video_frame_t * frame, bg_serialize_read_callback_t cb, void * cb_data, int big_endian) { int i; int num_planes; int bytes_per_line; int sub_h, sub_v; num_planes = gavl_pixelformat_num_planes(format->pixelformat); if(num_planes == 1) { bytes_per_line = gavl_pixelformat_bytes_per_pixel(format->pixelformat) * format->image_width; return read_plane(frame->planes[0], frame->strides[0], bytes_per_line, format->image_height, cb, cb_data); } else { int h = format->image_height; bytes_per_line = format->image_width * gavl_pixelformat_bytes_per_component(format->pixelformat); gavl_pixelformat_chroma_sub(format->pixelformat, &sub_h, &sub_v); for(i = 0; i < num_planes; i++) { if(!read_plane(frame->planes[i], frame->strides[i], bytes_per_line, h, cb, cb_data)) return 0; if(!i) { h /= sub_v; bytes_per_line /= sub_h; } } } #ifndef WORDS_BIGENDIAN if(big_endian) gavl_dsp_video_frame_swap_endian(ctx, frame, format); #else if(!big_endian) gavl_dsp_video_frame_swap_endian(ctx, frame, format); #endif return 1; } gmerlin-1.2.0~dfsg/lib/log.c0000644000175000017500000001375111764363410015600 0ustar alessioalessio/***************************************************************** * gmerlin - a general purpose multimedia framework and applications * * Copyright (c) 2001 - 2011 Members of the Gmerlin project * gmerlin-general@lists.sourceforge.net * http://gmerlin.sourceforge.net * * 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 of the License, 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 this program. If not, see . * *****************************************************************/ #include #ifdef HAVE_VASPRINTF #define _GNU_SOURCE #endif #include #include #include #include #include #include #include static int log_mask = BG_LOG_ERROR | BG_LOG_WARNING | BG_LOG_INFO; static char * last_error = NULL; pthread_mutex_t last_error_mutex = PTHREAD_MUTEX_INITIALIZER; // #define DUMP_LOG static const struct { bg_log_level_t level; const char * name; } level_names[] = { { BG_LOG_DEBUG, "Debug" }, { BG_LOG_WARNING, "Warning" }, { BG_LOG_ERROR, "Error" }, { BG_LOG_INFO, "Info" }, { 0, NULL } }; const char * bg_log_level_to_string(bg_log_level_t level) { int index = 0; while(level_names[index].name) { if(level_names[index].level == level) return level_names[index].name; index++; } return NULL; } static bg_msg_queue_t * log_queue = NULL; static void logs_internal(bg_log_level_t level, const char * domain, const char * msg_string) { bg_msg_t * msg; char ** lines; int i; FILE * out = stderr; #ifndef DUMP_LOG if(!log_queue) { #endif if(level & log_mask) { lines = bg_strbreak(msg_string, '\n'); i = 0; while(lines[i]) { fprintf(out, "[%s] %s: %s\n", domain, bg_log_level_to_string(level), lines[i]); if(level == BG_LOG_ERROR) { pthread_mutex_lock(&last_error_mutex); last_error = bg_strdup(last_error, lines[i]); pthread_mutex_unlock(&last_error_mutex); } i++; } bg_strbreak_free(lines); } #ifndef DUMP_LOG } else #else if(log_queue) #endif { msg = bg_msg_queue_lock_write(log_queue); bg_msg_set_id(msg, level); bg_msg_set_arg_string(msg, 0, domain); bg_msg_set_arg_string(msg, 1, msg_string); bg_msg_queue_unlock_write(log_queue); } } static void log_internal(bg_log_level_t level, const char * domain, const char * format, va_list argp) { char * msg_string; #ifndef HAVE_VASPRINTF int len; len = vsnprintf(NULL, 0, format, argp); msg_string = malloc(len+1); vsnprintf(msg_string, len+1, format, argp); #else if(vasprintf(&msg_string, format, argp) < 0) return; // Should never happen #endif logs_internal(level, domain, msg_string); free(msg_string); } void bg_log_notranslate(bg_log_level_t level, const char * domain, const char * format, ...) { va_list argp; /* arg ptr */ va_start( argp, format); log_internal(level, domain, format, argp); va_end(argp); } void bg_logs_notranslate(bg_log_level_t level, const char * domain, const char * str) { logs_internal(level, domain, str); } void bg_log_translate(const char * translation_domain, bg_log_level_t level, const char * domain, const char * format, ...) { va_list argp; /* arg ptr */ /* Translate format string */ format = dgettext(translation_domain, format); va_start( argp, format); log_internal(level, domain, format, argp); va_end(argp); } void bg_log_set_dest(bg_msg_queue_t * q) { log_queue = q; } void bg_log_set_verbose(int mask) { log_mask = mask; } char * bg_log_last_error() { char * ret; pthread_mutex_lock(&last_error_mutex); ret = bg_strdup(NULL, last_error); pthread_mutex_unlock(&last_error_mutex); return ret; } /* Syslog stuff */ static bg_msg_queue_t * syslog_queue = NULL; static struct { int gmerlin_level; int syslog_level; } loglevels[] = { { BG_LOG_ERROR, LOG_ERR }, { BG_LOG_WARNING, LOG_WARNING }, { BG_LOG_INFO, LOG_INFO }, { BG_LOG_DEBUG, LOG_DEBUG }, }; void bg_log_syslog_init(const char * name) { syslog_queue = bg_msg_queue_create(); bg_log_set_dest(syslog_queue); /* Initialize Logging */ openlog(name, LOG_PID, LOG_USER); } void bg_log_syslog_flush() { bg_msg_t * msg; char * domain; char * message; int i; int gmerlin_level; int syslog_level = LOG_INFO; while((msg = bg_msg_queue_try_lock_read(syslog_queue))) { gmerlin_level = bg_msg_get_id(msg); if(!(gmerlin_level & log_mask)) { bg_msg_queue_unlock_read(syslog_queue); continue; } domain = bg_msg_get_arg_string(msg, 0); message = bg_msg_get_arg_string(msg, 1); i = 0; for(i = 0; i < sizeof(loglevels) / sizeof(loglevels[0]); i++) { if(loglevels[i].gmerlin_level == gmerlin_level) { loglevels[i].syslog_level = syslog_level; break; } } syslog(syslog_level, "%s: %s", domain, message); free(domain); free(message); bg_msg_queue_unlock_read(syslog_queue); } } #if defined(__GNUC__) static void cleanup_log() __attribute__ ((destructor)); static void cleanup_log() { if(last_error) free(last_error); if(syslog_queue) bg_msg_queue_destroy(syslog_queue); } #endif gmerlin-1.2.0~dfsg/lib/player_oa.c0000644000175000017500000002061211764363410016764 0ustar alessioalessio/***************************************************************** * gmerlin - a general purpose multimedia framework and applications * * Copyright (c) 2001 - 2011 Members of the Gmerlin project * gmerlin-general@lists.sourceforge.net * http://gmerlin.sourceforge.net * * 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 of the License, 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 this program. If not, see . * *****************************************************************/ #include #include #include #include #include #include #define LOG_DOMAIN "player.audio_output" #define CHECK_PEAK(id, pos) \ index = gavl_channel_index(&s->fifo_format, id); \ if(index >= 0) \ { \ if(d.peak_out[pos] < peak[index]) \ d.peak_out[pos] = peak[index]; \ } #define CHECK_PEAK_2(id) \ index = gavl_channel_index(&s->fifo_format, id); \ if(index >= 0) \ { \ if(d.peak_out[0] < peak[index]) \ d.peak_out[0] = peak[index]; \ if(d.peak_out[1] < peak[index]) \ d.peak_out[1] = peak[index]; \ } typedef struct { double peak_out[2]; int num_samples; } peak_data_t; static void msg_peak(bg_msg_t * msg, const void * data) { const peak_data_t * d = data; bg_msg_set_id(msg, BG_PLAYER_MSG_AUDIO_PEAK); bg_msg_set_arg_int(msg, 0, d->num_samples); bg_msg_set_arg_float(msg, 1, d->peak_out[0]); bg_msg_set_arg_float(msg, 2, d->peak_out[1]); } static void do_peak(bg_player_t * p, gavl_audio_frame_t * frame) { peak_data_t d; int index; bg_player_audio_stream_t * s; double peak[GAVL_MAX_CHANNELS]; s = &p->audio_stream; d.peak_out[0] = 0.0; d.peak_out[1] = 0.0; d.num_samples = frame->valid_samples; gavl_peak_detector_reset(s->peak_detector); gavl_peak_detector_update(s->peak_detector, frame); gavl_peak_detector_get_peaks(s->peak_detector, NULL, NULL, peak); /* Collect channels and merge into 2 */ CHECK_PEAK(GAVL_CHID_FRONT_LEFT, 0); CHECK_PEAK(GAVL_CHID_FRONT_RIGHT, 1); CHECK_PEAK(GAVL_CHID_REAR_LEFT, 0); CHECK_PEAK(GAVL_CHID_REAR_RIGHT, 1); CHECK_PEAK(GAVL_CHID_SIDE_LEFT, 0); CHECK_PEAK(GAVL_CHID_SIDE_RIGHT, 1); CHECK_PEAK(GAVL_CHID_FRONT_CENTER_LEFT, 0); CHECK_PEAK(GAVL_CHID_FRONT_CENTER_RIGHT, 1); CHECK_PEAK_2(GAVL_CHID_FRONT_CENTER); CHECK_PEAK_2(GAVL_CHID_LFE); /* Broadcast */ bg_msg_queue_list_send(p->message_queues, msg_peak, &d); } /* Audio output thread */ static void process_frame(bg_player_t * p, gavl_audio_frame_t * frame) { int do_mute; bg_player_audio_stream_t * s; char tmp_string[128]; s = &p->audio_stream; if(!s->has_first_timestamp_o) { if(frame->timestamp) { sprintf(tmp_string, "%" PRId64, frame->timestamp); bg_log(BG_LOG_INFO, LOG_DOMAIN, "Got initial audio timestamp: %s", tmp_string); pthread_mutex_lock(&s->time_mutex); s->samples_written += frame->timestamp; pthread_mutex_unlock(&s->time_mutex); } s->has_first_timestamp_o = 1; } if(frame->valid_samples) { pthread_mutex_lock(&s->mute_mutex); do_mute = s->mute; pthread_mutex_unlock(&s->mute_mutex); if(DO_VISUALIZE(p->flags)) bg_visualizer_update(p->visualizer, frame); if(DO_PEAK(p->flags)) do_peak(p, frame); if(do_mute) { gavl_audio_frame_mute(frame, &s->fifo_format); } else { pthread_mutex_lock(&s->volume_mutex); gavl_volume_control_apply(s->volume, frame); pthread_mutex_unlock(&s->volume_mutex); } } } #if 0 static void read_audio_callback(void * priv, gavl_audio_frame_t* frame, int stream, int num_samples) { } #endif void * bg_player_oa_thread(void * data) { bg_player_audio_stream_t * s; gavl_time_t wait_time; bg_player_t * p = data; s = &p->audio_stream; /* Wait for playback */ bg_player_thread_wait_for_start(s->th); while(1) { if(!bg_player_thread_check(s->th)) break; if(s->send_silence) { gavl_audio_frame_mute(s->fifo_frame, &s->fifo_format); } else { if(!bg_player_read_audio(p, s->fifo_frame)) { if(bg_player_audio_set_eof(p)) { if(!bg_player_thread_wait_for_start(s->th)) break; continue; } } } process_frame(p, s->fifo_frame); if(s->fifo_frame->valid_samples) { if(s->do_convert_out) { gavl_audio_convert(s->cnv_out, s->fifo_frame, s->output_frame); bg_plugin_lock(s->plugin_handle); s->plugin->write_audio(s->priv, s->output_frame); bg_plugin_unlock(s->plugin_handle); } else { bg_plugin_lock(s->plugin_handle); s->plugin->write_audio(s->priv, s->fifo_frame); bg_plugin_unlock(s->plugin_handle); } pthread_mutex_lock(&s->time_mutex); s->samples_written += s->fifo_frame->valid_samples; pthread_mutex_unlock(&s->time_mutex); /* Now, wait a while to give other threads a chance to access the player time */ wait_time = gavl_samples_to_time(s->output_format.samplerate, s->fifo_frame->valid_samples)/2; } if(wait_time != GAVL_TIME_UNDEFINED) gavl_time_delay(&wait_time); } return NULL; } int bg_player_oa_init(bg_player_audio_stream_t * ctx) { int result; bg_plugin_lock(ctx->plugin_handle); result = ctx->plugin->open(ctx->priv, &ctx->output_format); if(result) ctx->output_open = 1; else ctx->output_open = 0; ctx->has_first_timestamp_o = 0; bg_plugin_unlock(ctx->plugin_handle); ctx->samples_written = 0; return result; } void bg_player_oa_cleanup(bg_player_audio_stream_t * ctx) { bg_plugin_lock(ctx->plugin_handle); ctx->plugin->close(ctx->priv); ctx->output_open = 0; bg_plugin_unlock(ctx->plugin_handle); } int bg_player_oa_start(bg_player_audio_stream_t * ctx) { int result = 1; bg_plugin_lock(ctx->plugin_handle); if(ctx->plugin->start) result = ctx->plugin->start(ctx->priv); bg_plugin_unlock(ctx->plugin_handle); return result; } void bg_player_oa_stop(bg_player_audio_stream_t * ctx) { bg_plugin_lock(ctx->plugin_handle); if(ctx->plugin->stop) ctx->plugin->stop(ctx->priv); bg_plugin_unlock(ctx->plugin_handle); } void bg_player_oa_set_volume(bg_player_audio_stream_t * ctx, float volume) { pthread_mutex_lock(&ctx->volume_mutex); gavl_volume_control_set_volume(ctx->volume, volume); pthread_mutex_unlock(&ctx->volume_mutex); } int bg_player_oa_get_latency(bg_player_audio_stream_t * ctx) { int ret; if(!ctx->priv || !ctx->plugin || !ctx->plugin->get_delay || !ctx->output_open) { return 0; } bg_plugin_lock(ctx->plugin_handle); ret = ctx->plugin->get_delay(ctx->priv); bg_plugin_unlock(ctx->plugin_handle); return ret; } void bg_player_oa_set_plugin(bg_player_t * player, bg_plugin_handle_t * handle) { bg_player_audio_stream_t * ctx; ctx = &player->audio_stream; if(ctx->plugin_handle) bg_plugin_unref(ctx->plugin_handle); ctx->plugin_handle = handle; if(handle) { ctx->plugin = (bg_oa_plugin_t*)(ctx->plugin_handle->plugin); ctx->priv = ctx->plugin_handle->priv; #if 0 bg_plugin_lock(ctx->plugin_handle); if(ctx->plugin->set_callbacks) ctx->plugin->set_callbacks(ctx->priv, &ctx->callbacks); bg_plugin_unlock(ctx->plugin_handle); #endif } } gmerlin-1.2.0~dfsg/lib/transcoder_pp.c0000644000175000017500000001521011764363410017652 0ustar alessioalessio/***************************************************************** * gmerlin - a general purpose multimedia framework and applications * * Copyright (c) 2001 - 2011 Members of the Gmerlin project * gmerlin-general@lists.sourceforge.net * http://gmerlin.sourceforge.net * * 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 of the License, 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 this program. If not, see . * *****************************************************************/ #include #include #include #include #include #include #include #include #include #define LOG_DOMAIN "postprocessor" struct bg_transcoder_pp_s { bg_plugin_handle_t * plugin; bg_encoder_pp_plugin_t * pp_plugin; bg_msg_queue_t * msg_in; bg_msg_queue_list_t * msg_out; /* Data, we save for each track */ int num_audio_streams, num_video_streams; char ** audio_filename; char ** video_filename; char * filename; gavl_metadata_t metadata; pthread_t thread; bg_e_pp_callbacks_t callbacks; gavl_timer_t * timer; gavl_time_t last_time; char * output_directory; int cleanup_pp; int num_tracks; }; static void action_callback(void * data, char * action) { bg_transcoder_pp_t * p; p = (bg_transcoder_pp_t*)data; bg_transcoder_send_msg_start(p->msg_out, action); p->last_time = 0; } static void progress_callback(void * data, float perc) { bg_transcoder_pp_t * p; gavl_time_t current_time; gavl_time_t remaining_time; p = (bg_transcoder_pp_t*)data; if(perc == 0.0) { gavl_timer_stop(p->timer); gavl_timer_set(p->timer, 0); gavl_timer_start(p->timer); } current_time = gavl_timer_get(p->timer); if(current_time - p->last_time < GAVL_TIME_SCALE) return; p->last_time = current_time; if(perc <= 0.0) remaining_time = GAVL_TIME_UNDEFINED; else remaining_time = (gavl_time_t)((double)current_time * (1.0 / perc - 1.0) + 0.5); bg_transcoder_send_msg_progress(p->msg_out, perc, remaining_time); } bg_transcoder_pp_t * bg_transcoder_pp_create() { bg_transcoder_pp_t * ret; ret = calloc(1, sizeof(*ret)); ret->callbacks.action_callback = action_callback; ret->callbacks.progress_callback = progress_callback; ret->callbacks.data = ret; ret->timer = gavl_timer_create(); ret->msg_out = bg_msg_queue_list_create(); ret->msg_in = bg_msg_queue_create(); return ret; } void bg_transcoder_pp_destroy(bg_transcoder_pp_t * p) { bg_msg_queue_list_destroy(p->msg_out); bg_msg_queue_destroy(p->msg_in); gavl_metadata_free(&p->metadata); gavl_timer_destroy(p->timer); if(p->plugin) bg_plugin_unref(p->plugin); free(p); } void bg_transcoder_pp_set_parameter(void * data, const char * name, const bg_parameter_value_t * val) { bg_transcoder_pp_t * w = (bg_transcoder_pp_t*)data; if(!name) return; if(!strcmp(name, "output_path")) { w->output_directory = bg_strdup(w->output_directory, val->val_str); } #if 0 else if(!strcmp(name, "send_finished")) { w->send_finished = val->val_i; } #endif else if(!strcmp(name, "cleanup_pp")) { w->cleanup_pp = val->val_i; } } int bg_transcoder_pp_init(bg_transcoder_pp_t* p, bg_plugin_handle_t * plugin) { if(p->plugin) bg_plugin_unref(p->plugin); p->num_tracks = 0; p->plugin = plugin; bg_plugin_ref(p->plugin); p->pp_plugin = (bg_encoder_pp_plugin_t*)(p->plugin->plugin); if(p->pp_plugin->set_callbacks) p->pp_plugin->set_callbacks(p->plugin->priv, &p->callbacks); if(!p->pp_plugin->init(p->plugin->priv)) return 0; gavl_timer_start(p->timer); return 1; } void bg_transcoder_pp_connect(bg_transcoder_pp_t * p, bg_transcoder_t * t) { bg_transcoder_add_message_queue(t, p->msg_in); } void bg_transcoder_pp_update(bg_transcoder_pp_t * p) { bg_msg_t *msg; char * str = NULL; char * ext; int pp_only = 0; while((msg = bg_msg_queue_try_lock_read(p->msg_in))) { switch(bg_msg_get_id(msg)) { case BG_TRANSCODER_MSG_START: break; case BG_TRANSCODER_MSG_FINISHED: break; case BG_TRANSCODER_MSG_METADATA: gavl_metadata_free(&p->metadata); bg_msg_get_arg_metadata(msg, 0, &p->metadata); break; case BG_TRANSCODER_MSG_FILE: str = bg_msg_get_arg_string(msg, 0); pp_only = bg_msg_get_arg_int(msg, 1); break; case BG_TRANSCODER_MSG_PROGRESS: break; } if(str) { if(p->pp_plugin->supported_extensions) { ext = strrchr(str, '.'); if(!ext || !bg_string_match(ext+1, p->pp_plugin->supported_extensions)) { bg_log(BG_LOG_WARNING, LOG_DOMAIN, "Not adding %s: Unsupported filename", str); free(str); str = NULL; } } if(str) { p->pp_plugin->add_track(p->plugin->priv, str, &p->metadata, pp_only); p->num_tracks++; bg_log(BG_LOG_INFO, LOG_DOMAIN, "Scheduling %s for postprocessing", str); free(str); str = NULL; } } bg_msg_queue_unlock_read(p->msg_in); } } static void * thread_func(void * data) { bg_transcoder_pp_t * p; p = (bg_transcoder_pp_t *)data; if(p->num_tracks) p->pp_plugin->run(p->plugin->priv, p->output_directory, p->cleanup_pp); else bg_log(BG_LOG_WARNING, LOG_DOMAIN, "Skipping postprocessing (no suitable files found)"); bg_transcoder_send_msg_finished(p->msg_out); return NULL; } void bg_transcoder_pp_stop(bg_transcoder_pp_t * p) { if(p->pp_plugin && p->pp_plugin->stop) p->pp_plugin->stop(p->plugin->priv); } void bg_transcoder_pp_run(bg_transcoder_pp_t * p) { pthread_create(&p->thread, NULL, thread_func, p); } void bg_transcoder_pp_finish(bg_transcoder_pp_t * p) { pthread_join(p->thread, NULL); } void bg_transcoder_pp_add_message_queue(bg_transcoder_pp_t * p, bg_msg_queue_t * message_queue) { bg_msg_queue_list_add(p->msg_out, message_queue); } gmerlin-1.2.0~dfsg/lib/player_time.c0000644000175000017500000001032411764363410017322 0ustar alessioalessio/***************************************************************** * gmerlin - a general purpose multimedia framework and applications * * Copyright (c) 2001 - 2011 Members of the Gmerlin project * gmerlin-general@lists.sourceforge.net * http://gmerlin.sourceforge.net * * 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 of the License, 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 this program. If not, see . * *****************************************************************/ #include #include #include #include #include void bg_player_time_init(bg_player_t * player) { bg_player_audio_stream_t * s = &player->audio_stream; if(s->plugin && (s->plugin->get_delay) && DO_AUDIO(player->flags)) s->sync_mode = SYNC_SOUNDCARD; else s->sync_mode = SYNC_SOFTWARE; } void bg_player_time_start(bg_player_t * player) { bg_player_audio_stream_t * ctx = &player->audio_stream; /* Set timer */ if(ctx->sync_mode == SYNC_SOFTWARE) { pthread_mutex_lock(&ctx->time_mutex); gavl_timer_set(ctx->timer, ctx->current_time); gavl_timer_start(ctx->timer); pthread_mutex_unlock(&ctx->time_mutex); } } void bg_player_time_stop(bg_player_t * player) { bg_player_audio_stream_t * ctx = &player->audio_stream; if(ctx->sync_mode == SYNC_SOFTWARE) { pthread_mutex_lock(&ctx->time_mutex); gavl_timer_stop(ctx->timer); pthread_mutex_unlock(&ctx->time_mutex); } } void bg_player_time_reset(bg_player_t * player) { bg_player_audio_stream_t * ctx = &player->audio_stream; if(ctx->sync_mode == SYNC_SOFTWARE) { pthread_mutex_lock(&ctx->time_mutex); gavl_timer_stop(ctx->timer); ctx->current_time = 0; pthread_mutex_unlock(&ctx->time_mutex); } else { pthread_mutex_lock(&ctx->time_mutex); ctx->current_time = 0; pthread_mutex_unlock(&ctx->time_mutex); } } /* Get the current time */ void bg_player_time_get(bg_player_t * player, int exact, gavl_time_t * ret) { bg_player_audio_stream_t * ctx = &player->audio_stream; gavl_time_t test_time; int samples_in_soundcard; if(!exact) { pthread_mutex_lock(&ctx->time_mutex); *ret = ctx->current_time; pthread_mutex_unlock(&ctx->time_mutex); } else { if(ctx->sync_mode == SYNC_SOFTWARE) { pthread_mutex_lock(&ctx->time_mutex); ctx->current_time = gavl_timer_get(ctx->timer); *ret = ctx->current_time; pthread_mutex_unlock(&ctx->time_mutex); } else { samples_in_soundcard = 0; bg_plugin_lock(ctx->plugin_handle); if(ctx->output_open) samples_in_soundcard = ctx->plugin->get_delay(ctx->priv); bg_plugin_unlock(ctx->plugin_handle); pthread_mutex_lock(&ctx->time_mutex); test_time = gavl_samples_to_time(ctx->output_format.samplerate, ctx->samples_written-samples_in_soundcard); if(test_time > ctx->current_time) ctx->current_time = test_time; *ret = ctx->current_time; pthread_mutex_unlock(&ctx->time_mutex); } } } void bg_player_time_set(bg_player_t * player, gavl_time_t time) { bg_player_audio_stream_t * ctx = &player->audio_stream; pthread_mutex_lock(&ctx->time_mutex); if(ctx->sync_mode == SYNC_SOFTWARE) gavl_timer_set(ctx->timer, time); else if(ctx->sync_mode == SYNC_SOUNDCARD) { ctx->samples_written = gavl_time_to_samples(ctx->output_format.samplerate, time); /* If time is set explicitely, we don't do that timestamp offset stuff */ ctx->has_first_timestamp_o = 1; } ctx->current_time = time; pthread_mutex_unlock(&ctx->time_mutex); } gmerlin-1.2.0~dfsg/lib/transcoder_track_xml.c0000644000175000017500000006042711764363410021231 0ustar alessioalessio/***************************************************************** * gmerlin - a general purpose multimedia framework and applications * * Copyright (c) 2001 - 2011 Members of the Gmerlin project * gmerlin-general@lists.sourceforge.net * http://gmerlin.sourceforge.net * * 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 of the License, 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 this program. If not, see . * *****************************************************************/ #include #include #include #include #include #include static void section_2_xml(bg_cfg_section_t * s, xmlNodePtr node) { BG_XML_SET_PROP(node, "name", bg_cfg_section_get_name(s)); bg_cfg_section_2_xml(s, node); } static void audio_stream_2_xml(xmlNodePtr parent, bg_transcoder_track_audio_t * s) { xmlNodePtr node; if(s->label) BG_XML_SET_PROP(parent, "label", s->label); node = xmlNewTextChild(parent, NULL, (xmlChar*)"GENERAL", NULL); section_2_xml(s->general_section, node); xmlAddChild(parent, BG_XML_NEW_TEXT("\n")); if(s->filter_section) { node = xmlNewTextChild(parent, NULL, (xmlChar*)"FILTER", NULL); section_2_xml(s->filter_section, node); xmlAddChild(parent, BG_XML_NEW_TEXT("\n")); } if(s->encoder_section) { node = xmlNewTextChild(parent, NULL, (xmlChar*)"ENCODER", NULL); section_2_xml(s->encoder_section, node); xmlAddChild(parent, BG_XML_NEW_TEXT("\n")); } } static void video_stream_2_xml(xmlNodePtr parent, bg_transcoder_track_video_t * s) { xmlNodePtr node; if(s->label) BG_XML_SET_PROP(parent, "label", s->label); node = xmlNewTextChild(parent, NULL, (xmlChar*)"GENERAL", NULL); section_2_xml(s->general_section, node); xmlAddChild(parent, BG_XML_NEW_TEXT("\n")); if(s->filter_section) { node = xmlNewTextChild(parent, NULL, (xmlChar*)"FILTER", NULL); section_2_xml(s->filter_section, node); xmlAddChild(parent, BG_XML_NEW_TEXT("\n")); } if(s->encoder_section) { node = xmlNewTextChild(parent, NULL, (xmlChar*)"ENCODER", NULL); section_2_xml(s->encoder_section, node); xmlAddChild(parent, BG_XML_NEW_TEXT("\n")); } } static void subtitle_text_stream_2_xml(xmlNodePtr parent, bg_transcoder_track_subtitle_text_t * s) { xmlNodePtr node; char * tmp_string; tmp_string = bg_sprintf("%d", s->in_index); BG_XML_SET_PROP(parent, "in_index", tmp_string); free(tmp_string); if(s->label) BG_XML_SET_PROP(parent, "label", s->label); node = xmlNewTextChild(parent, NULL, (xmlChar*)"GENERAL", NULL); section_2_xml(s->general_section, node); xmlAddChild(parent, BG_XML_NEW_TEXT("\n")); node = xmlNewTextChild(parent, NULL, (xmlChar*)"TEXTRENDERER", NULL); section_2_xml(s->textrenderer_section, node); xmlAddChild(parent, BG_XML_NEW_TEXT("\n")); if(s->encoder_section_text) { node = xmlNewTextChild(parent, NULL, (xmlChar*)"ENCODER_TEXT", NULL); section_2_xml(s->encoder_section_text, node); xmlAddChild(parent, BG_XML_NEW_TEXT("\n")); } if(s->encoder_section_overlay) { node = xmlNewTextChild(parent, NULL, (xmlChar*)"ENCODER_OVERLAY", NULL); section_2_xml(s->encoder_section_overlay, node); xmlAddChild(parent, BG_XML_NEW_TEXT("\n")); } } static void subtitle_overlay_stream_2_xml(xmlNodePtr parent, bg_transcoder_track_subtitle_overlay_t * s) { xmlNodePtr node; char * tmp_string; tmp_string = bg_sprintf("%d", s->in_index); BG_XML_SET_PROP(parent, "in_index", tmp_string); free(tmp_string); if(s->label) BG_XML_SET_PROP(parent, "label", s->label); node = xmlNewTextChild(parent, NULL, (xmlChar*)"GENERAL", NULL); section_2_xml(s->general_section, node); if(s->encoder_section) { node = xmlNewTextChild(parent, NULL, (xmlChar*)"ENCODER", NULL); section_2_xml(s->encoder_section, node); xmlAddChild(parent, BG_XML_NEW_TEXT("\n")); } xmlAddChild(parent, BG_XML_NEW_TEXT("\n")); } static void track_2_xml(bg_transcoder_track_t * track, xmlNodePtr xml_track) { int i; xmlNodePtr node, stream_node; node = xmlNewTextChild(xml_track, NULL, (xmlChar*)"GENERAL", NULL); section_2_xml(track->general_section, node); xmlAddChild(xml_track, BG_XML_NEW_TEXT("\n")); node = xmlNewTextChild(xml_track, NULL, (xmlChar*)"GENERAL_PARAMS", NULL); bg_parameters_2_xml(track->general_parameters, node); xmlAddChild(xml_track, BG_XML_NEW_TEXT("\n")); node = xmlNewTextChild(xml_track, NULL, (xmlChar*)"METADATA", NULL); section_2_xml(track->metadata_section, node); xmlAddChild(xml_track, BG_XML_NEW_TEXT("\n")); node = xmlNewTextChild(xml_track, NULL, (xmlChar*)"METADATA_PARAMS", NULL); bg_parameters_2_xml(track->metadata_parameters, node); xmlAddChild(xml_track, BG_XML_NEW_TEXT("\n")); if(track->chapter_list) { node = xmlNewTextChild(xml_track, NULL, (xmlChar*)"CHAPTERS", NULL); bg_chapter_list_2_xml(track->chapter_list, node); xmlAddChild(xml_track, BG_XML_NEW_TEXT("\n")); } if(track->input_section) { node = xmlNewTextChild(xml_track, NULL, (xmlChar*)"INPUT", NULL); section_2_xml(track->input_section, node); xmlAddChild(xml_track, BG_XML_NEW_TEXT("\n")); } if(track->audio_encoder_section) { node = xmlNewTextChild(xml_track, NULL, (xmlChar*)"AUDIO_ENCODER", NULL); section_2_xml(track->audio_encoder_section, node); xmlAddChild(xml_track, BG_XML_NEW_TEXT("\n")); } if(track->video_encoder_section) { node = xmlNewTextChild(xml_track, NULL, (xmlChar*)"VIDEO_ENCODER", NULL); section_2_xml(track->video_encoder_section, node); xmlAddChild(xml_track, BG_XML_NEW_TEXT("\n")); } if(track->subtitle_text_encoder_section) { node = xmlNewTextChild(xml_track, NULL, (xmlChar*)"SUBTITLE_TEXT_ENCODER", NULL); section_2_xml(track->subtitle_text_encoder_section, node); xmlAddChild(xml_track, BG_XML_NEW_TEXT("\n")); } if(track->subtitle_overlay_encoder_section) { node = xmlNewTextChild(xml_track, NULL, (xmlChar*)"SUBTITLE_OVERLAY_ENCODER", NULL); section_2_xml(track->subtitle_overlay_encoder_section, node); xmlAddChild(xml_track, BG_XML_NEW_TEXT("\n")); } if(track->num_audio_streams) { node = xmlNewTextChild(xml_track, NULL, (xmlChar*)"AUDIO_STREAMS", NULL); xmlAddChild(node, BG_XML_NEW_TEXT("\n")); for(i = 0; i < track->num_audio_streams; i++) { stream_node = xmlNewTextChild(node, NULL, (xmlChar*)"STREAM", NULL); xmlAddChild(stream_node, BG_XML_NEW_TEXT("\n")); audio_stream_2_xml(stream_node, &track->audio_streams[i]); xmlAddChild(node, BG_XML_NEW_TEXT("\n")); } xmlAddChild(xml_track, BG_XML_NEW_TEXT("\n")); } if(track->num_video_streams) { node = xmlNewTextChild(xml_track, NULL, (xmlChar*)"VIDEO_STREAMS", NULL); xmlAddChild(node, BG_XML_NEW_TEXT("\n")); for(i = 0; i < track->num_video_streams; i++) { stream_node = xmlNewTextChild(node, NULL, (xmlChar*)"STREAM", NULL); xmlAddChild(stream_node, BG_XML_NEW_TEXT("\n")); video_stream_2_xml(stream_node, &track->video_streams[i]); xmlAddChild(node, BG_XML_NEW_TEXT("\n")); } xmlAddChild(xml_track, BG_XML_NEW_TEXT("\n")); } if(track->num_subtitle_text_streams) { node = xmlNewTextChild(xml_track, NULL, (xmlChar*)"SUBTITLE_TEXT_STREAMS", NULL); xmlAddChild(node, BG_XML_NEW_TEXT("\n")); for(i = 0; i < track->num_subtitle_text_streams; i++) { stream_node = xmlNewTextChild(node, NULL, (xmlChar*)"STREAM", NULL); xmlAddChild(stream_node, BG_XML_NEW_TEXT("\n")); subtitle_text_stream_2_xml(stream_node, &track->subtitle_text_streams[i]); xmlAddChild(node, BG_XML_NEW_TEXT("\n")); } } if(track->num_subtitle_overlay_streams) { node = xmlNewTextChild(xml_track, NULL, (xmlChar*)"SUBTITLE_OVERLAY_STREAMS", NULL); xmlAddChild(node, BG_XML_NEW_TEXT("\n")); for(i = 0; i < track->num_subtitle_overlay_streams; i++) { stream_node = xmlNewTextChild(node, NULL, (xmlChar*)"STREAM", NULL); xmlAddChild(stream_node, BG_XML_NEW_TEXT("\n")); subtitle_overlay_stream_2_xml(stream_node, &track->subtitle_overlay_streams[i]); xmlAddChild(node, BG_XML_NEW_TEXT("\n")); } } } static void global_2_xml(bg_transcoder_track_global_t * g, xmlNodePtr xml_global) { xmlNodePtr node; if(g->pp_plugin) { node = xmlNewTextChild(xml_global, NULL, (xmlChar*)"PP_PLUGIN", NULL); xmlAddChild(node, BG_XML_NEW_TEXT(g->pp_plugin)); xmlAddChild(xml_global, BG_XML_NEW_TEXT("\n")); node = xmlNewTextChild(xml_global, NULL, (xmlChar*)"PP_SECTION", NULL); section_2_xml(g->pp_section, node); xmlAddChild(xml_global, BG_XML_NEW_TEXT("\n")); } } static xmlDocPtr transcoder_tracks_2_xml(bg_transcoder_track_t * t, bg_transcoder_track_global_t * g, int selected_only) { bg_transcoder_track_t * tmp; xmlDocPtr xml_doc; xmlNodePtr root_node, node; xml_doc = xmlNewDoc((xmlChar*)"1.0"); root_node = xmlNewDocRawNode(xml_doc, NULL, (xmlChar*)"TRANSCODER_TRACKS", NULL); xmlDocSetRootElement(xml_doc, root_node); xmlAddChild(root_node, BG_XML_NEW_TEXT("\n")); if(g) { node = xmlNewTextChild(root_node, NULL, (xmlChar*)"GLOBAL", NULL); global_2_xml(g, node); xmlAddChild(root_node, BG_XML_NEW_TEXT("\n")); } tmp = t; while(tmp) { if(tmp->selected || !selected_only) { node = xmlNewTextChild(root_node, NULL, (xmlChar*)"TRACK", NULL); xmlAddChild(node, BG_XML_NEW_TEXT("\n")); track_2_xml(tmp, node); xmlAddChild(node, BG_XML_NEW_TEXT("\n")); xmlAddChild(root_node, BG_XML_NEW_TEXT("\n")); } tmp = tmp->next; } return xml_doc; } void bg_transcoder_tracks_save(bg_transcoder_track_t * t, bg_transcoder_track_global_t * g, const char * filename) { xmlDocPtr xml_doc; xml_doc = transcoder_tracks_2_xml(t, g, 0); xmlSaveFile(filename, xml_doc); xmlFreeDoc(xml_doc); } char * bg_transcoder_tracks_selected_to_xml(bg_transcoder_track_t * t) { bg_xml_output_mem_t ctx; xmlOutputBufferPtr b; xmlDocPtr xml_doc; xml_doc = transcoder_tracks_2_xml(t, NULL, 1); memset(&ctx, 0, sizeof(ctx)); b = xmlOutputBufferCreateIO(bg_xml_write_callback, bg_xml_close_callback, &ctx, NULL); xmlSaveFileTo(b, xml_doc, NULL); xmlFreeDoc(xml_doc); return ctx.buffer; } /* Load */ static bg_cfg_section_t * xml_2_section(xmlDocPtr xml_doc, xmlNodePtr xml_section) { char * name; bg_cfg_section_t * ret; name = BG_XML_GET_PROP(xml_section, "name"); ret = bg_cfg_section_create(name); if(name) xmlFree(name); bg_cfg_xml_2_section(xml_doc, xml_section, ret); return ret; } static void xml_2_audio(bg_transcoder_track_audio_t * s, xmlDocPtr xml_doc, xmlNodePtr xml_stream) { xmlNodePtr node; char * tmp_string; tmp_string = BG_XML_GET_PROP(xml_stream, "label"); if(tmp_string) { s->label = bg_strdup(s->label, tmp_string); xmlFree(tmp_string); } node = xml_stream->children; while(node) { if(!node->name) { node = node->next; continue; } if(!BG_XML_STRCMP(node->name, "GENERAL")) { s->general_section = xml_2_section(xml_doc, node); } else if(!BG_XML_STRCMP(node->name, "FILTER")) { s->filter_section = xml_2_section(xml_doc, node); } else if(!BG_XML_STRCMP(node->name, "ENCODER")) { s->encoder_section = xml_2_section(xml_doc, node); } node = node->next; } } static void xml_2_video(bg_transcoder_track_video_t * s, xmlDocPtr xml_doc, xmlNodePtr xml_stream) { xmlNodePtr node; char * tmp_string; tmp_string = BG_XML_GET_PROP(xml_stream, "label"); if(tmp_string) { s->label = bg_strdup(s->label, tmp_string); xmlFree(tmp_string); } node = xml_stream->children; while(node) { if(!node->name) { node = node->next; continue; } if(!BG_XML_STRCMP(node->name, "GENERAL")) { s->general_section = xml_2_section(xml_doc, node); } else if(!BG_XML_STRCMP(node->name, "FILTER")) { s->filter_section = xml_2_section(xml_doc, node); } else if(!BG_XML_STRCMP(node->name, "ENCODER")) { s->encoder_section = xml_2_section(xml_doc, node); } node = node->next; } } static void xml_2_subtitle_text(bg_transcoder_track_subtitle_text_t * s, xmlDocPtr xml_doc, xmlNodePtr xml_stream) { xmlNodePtr node; char * tmp_string; tmp_string = BG_XML_GET_PROP(xml_stream, "label"); if(tmp_string) { s->label = bg_strdup(s->label, tmp_string); xmlFree(tmp_string); } tmp_string = BG_XML_GET_PROP(xml_stream, "in_index"); if(tmp_string) { s->in_index = atoi(tmp_string); xmlFree(tmp_string); } node = xml_stream->children; while(node) { if(!node->name) { node = node->next; continue; } if(!BG_XML_STRCMP(node->name, "GENERAL")) { s->general_section = xml_2_section(xml_doc, node); } else if(!BG_XML_STRCMP(node->name, "TEXTRENDERER")) { s->textrenderer_section = xml_2_section(xml_doc, node); } else if(!BG_XML_STRCMP(node->name, "ENCODER_TEXT")) { s->encoder_section_text = xml_2_section(xml_doc, node); } else if(!BG_XML_STRCMP(node->name, "ENCODER_OVERLAY")) { s->encoder_section_overlay = xml_2_section(xml_doc, node); } node = node->next; } } static void xml_2_subtitle_overlay(bg_transcoder_track_subtitle_overlay_t * s, xmlDocPtr xml_doc, xmlNodePtr xml_stream) { xmlNodePtr node; char * tmp_string; tmp_string = BG_XML_GET_PROP(xml_stream, "label"); if(tmp_string) { s->label = bg_strdup(s->label, tmp_string); xmlFree(tmp_string); } tmp_string = BG_XML_GET_PROP(xml_stream, "in_index"); if(tmp_string) { s->in_index = atoi(tmp_string); xmlFree(tmp_string); } node = xml_stream->children; while(node) { if(!node->name) { node = node->next; continue; } if(!BG_XML_STRCMP(node->name, "GENERAL")) { s->general_section = xml_2_section(xml_doc, node); } else if(!BG_XML_STRCMP(node->name, "ENCODER")) { s->encoder_section = xml_2_section(xml_doc, node); } node = node->next; } } /* Upgrade saved tracks with older versions */ static void purge_track(bg_transcoder_track_t * t) { const char * video_name = NULL; const char * name; bg_cfg_section_get_parameter_string(t->general_section, "video_encoder", &video_name); if(!video_name) return; bg_cfg_section_get_parameter_string(t->general_section, "audio_encoder", &name); if(name && !strcmp(name, video_name)) bg_cfg_section_set_parameter_string(t->general_section, "audio_encoder", NULL); bg_cfg_section_get_parameter_string(t->general_section, "subtitle_text_encoder", &name); if(name && !strcmp(name, video_name)) bg_cfg_section_set_parameter_string(t->general_section, "subtitle_text_encoder", NULL); bg_cfg_section_get_parameter_string(t->general_section, "subtitle_overlay_encoder", &name); if(name && !strcmp(name, video_name)) bg_cfg_section_set_parameter_string(t->general_section, "subtitle_overlay_encoder", NULL); } static int xml_2_track(bg_transcoder_track_t * t, xmlDocPtr xml_doc, xmlNodePtr xml_track, bg_plugin_registry_t * plugin_reg) { int ret = 0; xmlNodePtr node, child_node; int i; node = xml_track->children; while(node) { if(!node->name) { node = node->next; continue; } if(!BG_XML_STRCMP(node->name, "GENERAL")) t->general_section = xml_2_section(xml_doc, node); else if(!BG_XML_STRCMP(node->name, "GENERAL_PARAMS")) t->general_parameters = bg_xml_2_parameters(xml_doc, node); else if(!BG_XML_STRCMP(node->name, "METADATA")) t->metadata_section = xml_2_section(xml_doc, node); else if(!BG_XML_STRCMP(node->name, "METADATA_PARAMS")) t->metadata_parameters = bg_xml_2_parameters(xml_doc, node); else if(!BG_XML_STRCMP(node->name, "CHAPTERS")) t->chapter_list = bg_xml_2_chapter_list(xml_doc, node); else if(!BG_XML_STRCMP(node->name, "INPUT")) t->input_section = xml_2_section(xml_doc, node); else if(!BG_XML_STRCMP(node->name, "AUDIO_ENCODER")) t->audio_encoder_section = xml_2_section(xml_doc, node); else if(!BG_XML_STRCMP(node->name, "VIDEO_ENCODER")) t->video_encoder_section = xml_2_section(xml_doc, node); else if(!BG_XML_STRCMP(node->name, "SUBTITLE_TEXT_ENCODER")) t->subtitle_text_encoder_section = xml_2_section(xml_doc, node); else if(!BG_XML_STRCMP(node->name, "SUBTITLE_OVERLAY_ENCODER")) t->subtitle_overlay_encoder_section = xml_2_section(xml_doc, node); else if(!BG_XML_STRCMP(node->name, "AUDIO_STREAMS")) { /* Count streams */ t->num_audio_streams = 0; child_node = node->children; while(child_node) { if(child_node->name && !BG_XML_STRCMP(child_node->name, "STREAM")) t->num_audio_streams++; child_node = child_node->next; } /* Allocate streams */ t->audio_streams = calloc(t->num_audio_streams, sizeof(*(t->audio_streams))); /* Load streams */ child_node = node->children; i = 0; while(child_node) { if(child_node->name && !BG_XML_STRCMP(child_node->name, "STREAM")) { xml_2_audio(&t->audio_streams[i], xml_doc, child_node); i++; } child_node = child_node->next; } } else if(!BG_XML_STRCMP(node->name, "VIDEO_STREAMS")) { /* Count streams */ t->num_video_streams = 0; child_node = node->children; while(child_node) { if(child_node->name && !BG_XML_STRCMP(child_node->name, "STREAM")) t->num_video_streams++; child_node = child_node->next; } /* Allocate streams */ t->video_streams = calloc(t->num_video_streams, sizeof(*(t->video_streams))); /* Load streams */ child_node = node->children; i = 0; while(child_node) { if(child_node->name && !BG_XML_STRCMP(child_node->name, "STREAM")) { xml_2_video(&t->video_streams[i], xml_doc, child_node); i++; } child_node = child_node->next; } } /* Subtitle text streams */ else if(!BG_XML_STRCMP(node->name, "SUBTITLE_TEXT_STREAMS")) { /* Count streams */ t->num_subtitle_text_streams = 0; child_node = node->children; while(child_node) { if(child_node->name && !BG_XML_STRCMP(child_node->name, "STREAM")) t->num_subtitle_text_streams++; child_node = child_node->next; } /* Allocate streams */ t->subtitle_text_streams = calloc(t->num_subtitle_text_streams, sizeof(*(t->subtitle_text_streams))); /* Load streams */ child_node = node->children; i = 0; while(child_node) { if(child_node->name && !BG_XML_STRCMP(child_node->name, "STREAM")) { xml_2_subtitle_text(&t->subtitle_text_streams[i], xml_doc, child_node); i++; } child_node = child_node->next; } } /* Subtitle overlay streams */ else if(!BG_XML_STRCMP(node->name, "SUBTITLE_OVERLAY_STREAMS")) { /* Count streams */ t->num_subtitle_overlay_streams = 0; child_node = node->children; while(child_node) { if(child_node->name && !BG_XML_STRCMP(child_node->name, "STREAM")) t->num_subtitle_overlay_streams++; child_node = child_node->next; } /* Allocate streams */ t->subtitle_overlay_streams = calloc(t->num_subtitle_overlay_streams, sizeof(*(t->subtitle_overlay_streams))); /* Load streams */ child_node = node->children; i = 0; while(child_node) { if(child_node->name && !BG_XML_STRCMP(child_node->name, "STREAM")) { xml_2_subtitle_overlay(&t->subtitle_overlay_streams[i], xml_doc, child_node); i++; } child_node = child_node->next; } } node = node->next; } bg_transcoder_track_create_parameters(t, plugin_reg); purge_track(t); ret = 1; return ret; } static int xml_2_global(bg_transcoder_track_global_t * g, xmlDocPtr xml_doc, xmlNodePtr node, bg_plugin_registry_t * plugin_reg) { int ret = 0; char * tmp_string; bg_transcoder_track_global_free(g); node = node->children; while(node) { if(!node->name) { node = node->next; continue; } if(!BG_XML_STRCMP(node->name, "PP_PLUGIN")) { tmp_string = (char*)xmlNodeListGetString(xml_doc, node->children, 1); if(tmp_string) { g->pp_plugin = bg_strdup(g->pp_plugin, tmp_string); xmlFree(tmp_string); } } else if(!BG_XML_STRCMP(node->name, "PP_SECTION")) { g->pp_section = xml_2_section(xml_doc, node); } node = node->next; } ret = 1; return ret; } static bg_transcoder_track_t * transcoder_tracks_load(xmlDocPtr xml_doc, bg_transcoder_track_global_t * g, bg_plugin_registry_t * plugin_reg) { xmlNodePtr node; bg_transcoder_track_t * ret = NULL; bg_transcoder_track_t * end = NULL; if(!xml_doc) return NULL; node = xml_doc->children; if(BG_XML_STRCMP(node->name, "TRANSCODER_TRACKS")) return NULL; node = node->children; while(node) { if(node->name && !BG_XML_STRCMP(node->name, "TRACK")) { /* Load track */ if(!ret) { ret = calloc(1, sizeof(*ret)); end = ret; } else { end->next = calloc(1, sizeof(*(end->next))); end = end->next; } xml_2_track(end, xml_doc, node, plugin_reg); } else if(node->name && !BG_XML_STRCMP(node->name, "GLOBAL") && g) { xml_2_global(g, xml_doc, node, plugin_reg); } node = node->next; } return ret; } bg_transcoder_track_t * bg_transcoder_tracks_load(const char * filename, bg_transcoder_track_global_t * g, bg_plugin_registry_t * plugin_reg) { xmlDocPtr xml_doc; bg_transcoder_track_t * ret; if(!filename) return NULL; xml_doc = bg_xml_parse_file(filename); ret = transcoder_tracks_load(xml_doc, g, plugin_reg); xmlFreeDoc(xml_doc); return ret; } bg_transcoder_track_t * bg_transcoder_tracks_from_xml(char * str, bg_plugin_registry_t * plugin_reg) { xmlDocPtr xml_doc; bg_transcoder_track_t * ret; xml_doc = xmlParseMemory(str, strlen(str)); ret = transcoder_tracks_load(xml_doc, NULL, plugin_reg); xmlFreeDoc(xml_doc); return ret; } gmerlin-1.2.0~dfsg/lib/edl_xml.c0000644000175000017500000003405311764363410016441 0ustar alessioalessio/***************************************************************** * gmerlin - a general purpose multimedia framework and applications * * Copyright (c) 2001 - 2011 Members of the Gmerlin project * gmerlin-general@lists.sourceforge.net * http://gmerlin.sourceforge.net * * 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 of the License, 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 this program. If not, see . * *****************************************************************/ #include #include #include #include #include static const char * const edl_key = "GMERLIN_EDL"; static const char * const tracks_key = "tracks"; static const char * const track_key = "track"; static const char * const audio_streams_key = "audio_streams"; static const char * const video_streams_key = "video_streams"; static const char * const subtitle_text_streams_key = "subtitle_text_streams"; static const char * const subtitle_overlay_streams_key = "subtitle_overlay_streams"; static const char * const stream_key = "stream"; static const char * const segment_key = "segment"; static const char * const segments_key = "segments"; static const char * const url_key = "url"; static const char * const track_index_key = "tindex"; static const char * const stream_index_key = "sindex"; static const char * const src_time_key = "stime"; static const char * const dst_time_key = "dtime"; static const char * const dst_duration_key = "duration"; static const char * const speed_key = "speed"; static void load_segments(xmlDocPtr doc, xmlNodePtr node, bg_edl_stream_t * s) { char * tmp_string; bg_edl_segment_t * seg; xmlNodePtr child_node; node = node->children; while(node) { if(!node->name) { node = node->next; continue; } if(!BG_XML_STRCMP(node->name, segment_key)) { seg = bg_edl_add_segment(s); tmp_string = BG_XML_GET_PROP(node, "scale"); if(tmp_string) { seg->timescale = atoi(tmp_string); xmlFree(tmp_string); } child_node = node->children; while(child_node) { if(!child_node->name) { child_node = child_node->next; continue; } if(!BG_XML_STRCMP(child_node->name, track_index_key)) { tmp_string = (char*)xmlNodeListGetString(doc, child_node->children, 1); seg->track = atoi(tmp_string); xmlFree(tmp_string); } if(!BG_XML_STRCMP(child_node->name, url_key)) { tmp_string = (char*)xmlNodeListGetString(doc, child_node->children, 1); seg->url = bg_strdup(seg->url, tmp_string); xmlFree(tmp_string); } if(!BG_XML_STRCMP(child_node->name, stream_index_key)) { tmp_string = (char*)xmlNodeListGetString(doc, child_node->children, 1); seg->stream = atoi(tmp_string); xmlFree(tmp_string); } if(!BG_XML_STRCMP(child_node->name, src_time_key)) { tmp_string = (char*)xmlNodeListGetString(doc, child_node->children, 1); sscanf(tmp_string, "%"PRId64, &seg->src_time); xmlFree(tmp_string); } if(!BG_XML_STRCMP(child_node->name, dst_time_key)) { tmp_string = (char*)xmlNodeListGetString(doc, child_node->children, 1); sscanf(tmp_string, "%"PRId64, &seg->dst_time); xmlFree(tmp_string); } if(!BG_XML_STRCMP(child_node->name, dst_duration_key)) { tmp_string = (char*)xmlNodeListGetString(doc, child_node->children, 1); sscanf(tmp_string, "%"PRId64, &seg->dst_duration); xmlFree(tmp_string); } if(!BG_XML_STRCMP(child_node->name, speed_key)) { tmp_string = (char*)xmlNodeListGetString(doc, child_node->children, 1); sscanf(tmp_string, "%d:%d", &seg->speed_num, &seg->speed_den); xmlFree(tmp_string); } child_node = child_node->next; } } node = node->next; } } static void load_streams(xmlDocPtr doc, xmlNodePtr node, bg_edl_stream_t * (*add_func)(bg_edl_track_t *), bg_edl_track_t * t) { char * tmp_string; bg_edl_stream_t * s; xmlNodePtr child_node; node = node->children; while(node) { if(!node->name) { node = node->next; continue; } if(!BG_XML_STRCMP(node->name, stream_key)) { s = add_func(t); tmp_string = BG_XML_GET_PROP(node, "scale"); if(tmp_string) { s->timescale = atoi(tmp_string); xmlFree(tmp_string); } child_node = node->children; while(child_node) { if(!child_node->name) { child_node = child_node->next; continue; } if(!BG_XML_STRCMP(child_node->name, segments_key)) { load_segments(doc, child_node, s); } child_node = child_node->next; } } node = node->next; } } static void load_track(xmlDocPtr doc, xmlNodePtr node, bg_edl_t * ret) { bg_edl_track_t * et; char * tmp_string; et = bg_edl_add_track(ret); tmp_string = BG_XML_GET_PROP(node, "name"); if(tmp_string) { et->name = bg_strdup(et->name, tmp_string); xmlFree(tmp_string); } node = node->children; while(node) { if(!node->name) { node = node->next; continue; } if(!BG_XML_STRCMP(node->name, audio_streams_key)) load_streams(doc, node, bg_edl_add_audio_stream, et); else if(!BG_XML_STRCMP(node->name, video_streams_key)) load_streams(doc, node, bg_edl_add_video_stream, et); else if(!BG_XML_STRCMP(node->name, subtitle_text_streams_key)) load_streams(doc, node, bg_edl_add_subtitle_text_stream, et); else if(!BG_XML_STRCMP(node->name, subtitle_overlay_streams_key)) load_streams(doc, node, bg_edl_add_subtitle_overlay_stream, et); node = node->next; } } bg_edl_t * bg_edl_load(const char * filename) { bg_edl_t * ret; char * tmp_string; xmlDocPtr xml_doc; xmlNodePtr node; xmlNodePtr child_node; xml_doc = bg_xml_parse_file(filename); if(!xml_doc) return NULL; node = xml_doc->children; if(BG_XML_STRCMP(node->name, edl_key)) { xmlFreeDoc(xml_doc); return NULL; } node = node->children; ret = bg_edl_create(); while(node) { if(!node->name) { node = node->next; continue; } if(!BG_XML_STRCMP(node->name, url_key)) { tmp_string = (char*)xmlNodeListGetString(xml_doc, node->children, 1); ret->url = bg_strdup(ret->url, tmp_string); xmlFree(tmp_string); } else if(!BG_XML_STRCMP(node->name, tracks_key)) { child_node = node->children; while(child_node) { if(!child_node->name) { child_node = child_node->next; continue; } if(!BG_XML_STRCMP(child_node->name, track_key)) { load_track(xml_doc, child_node, ret); } child_node = child_node->next; } } node = node->next; } return ret; } static void save_streams(xmlNodePtr parent, const bg_edl_stream_t * s, int num) { int i, j; xmlNodePtr stream_node; xmlNodePtr segments_node; xmlNodePtr segment_node; xmlNodePtr node; char * tmp_string; tmp_string = bg_sprintf("%d", num); BG_XML_SET_PROP(parent, "num", tmp_string); free(tmp_string); for(i = 0; i < num; i++) { stream_node = xmlNewTextChild(parent, NULL, (xmlChar*)stream_key, NULL); xmlAddChild(parent, BG_XML_NEW_TEXT("\n")); xmlAddChild(stream_node, BG_XML_NEW_TEXT("\n")); tmp_string = bg_sprintf("%d", s[i].timescale); BG_XML_SET_PROP(stream_node, "scale", tmp_string); free(tmp_string); segments_node = xmlNewTextChild(stream_node, NULL, (xmlChar*)segments_key, NULL); xmlAddChild(stream_node, BG_XML_NEW_TEXT("\n")); tmp_string = bg_sprintf("%d", s[i].num_segments); BG_XML_SET_PROP(segments_node, "num", tmp_string); free(tmp_string); xmlAddChild(segments_node, BG_XML_NEW_TEXT("\n")); for(j = 0; j < s[i].num_segments; j++) { segment_node = xmlNewTextChild(segments_node, NULL, (xmlChar*)segment_key, NULL); tmp_string = bg_sprintf("%d", s[i].segments[j].timescale); BG_XML_SET_PROP(segment_node, "scale", tmp_string); free(tmp_string); xmlAddChild(segment_node, BG_XML_NEW_TEXT("\n")); if(s[i].segments[j].url) { node = xmlNewTextChild(segment_node, NULL, (xmlChar*)url_key, NULL); xmlAddChild(node, BG_XML_NEW_TEXT(s[i].segments[j].url)); xmlAddChild(segment_node, BG_XML_NEW_TEXT("\n")); } node = xmlNewTextChild(segment_node, NULL, (xmlChar*)track_index_key, NULL); tmp_string = bg_sprintf("%d", s[i].segments[j].track); xmlAddChild(node, BG_XML_NEW_TEXT(tmp_string)); xmlAddChild(segment_node, BG_XML_NEW_TEXT("\n")); free(tmp_string); node = xmlNewTextChild(segment_node, NULL, (xmlChar*)stream_index_key, NULL); tmp_string = bg_sprintf("%d", s[i].segments[j].stream); xmlAddChild(node, BG_XML_NEW_TEXT(tmp_string)); xmlAddChild(segment_node, BG_XML_NEW_TEXT("\n")); free(tmp_string); node = xmlNewTextChild(segment_node, NULL, (xmlChar*)src_time_key, NULL); tmp_string = bg_sprintf("%"PRId64, s[i].segments[j].src_time); xmlAddChild(node, BG_XML_NEW_TEXT(tmp_string)); xmlAddChild(segment_node, BG_XML_NEW_TEXT("\n")); free(tmp_string); node = xmlNewTextChild(segment_node, NULL, (xmlChar*)dst_time_key, NULL); tmp_string = bg_sprintf("%"PRId64, s[i].segments[j].dst_time); xmlAddChild(node, BG_XML_NEW_TEXT(tmp_string)); xmlAddChild(segment_node, BG_XML_NEW_TEXT("\n")); free(tmp_string); node = xmlNewTextChild(segment_node, NULL, (xmlChar*)dst_duration_key, NULL); tmp_string = bg_sprintf("%"PRId64, s[i].segments[j].dst_duration); xmlAddChild(node, BG_XML_NEW_TEXT(tmp_string)); xmlAddChild(segment_node, BG_XML_NEW_TEXT("\n")); free(tmp_string); node = xmlNewTextChild(segment_node, NULL, (xmlChar*)speed_key, NULL); tmp_string = bg_sprintf("%d:%d", s[i].segments[j].speed_num, s[i].segments[j].speed_den); xmlAddChild(node, BG_XML_NEW_TEXT(tmp_string)); xmlAddChild(segment_node, BG_XML_NEW_TEXT("\n")); free(tmp_string); xmlAddChild(segments_node, BG_XML_NEW_TEXT("\n")); } } } void bg_edl_save(const bg_edl_t * edl, const char * filename) { int i; xmlDocPtr xml_doc; xmlNodePtr xml_edl; xmlNodePtr node; xmlNodePtr child_node; xmlNodePtr streams_node; xml_doc = xmlNewDoc((xmlChar*)"1.0"); xml_edl = xmlNewDocRawNode(xml_doc, NULL, (xmlChar*)edl_key, NULL); xmlDocSetRootElement(xml_doc, xml_edl); xmlAddChild(xml_edl, BG_XML_NEW_TEXT("\n")); if(edl->url) { node = xmlNewTextChild(xml_edl, NULL, (xmlChar*)url_key, NULL); xmlAddChild(node, BG_XML_NEW_TEXT(edl->url)); xmlAddChild(xml_edl, BG_XML_NEW_TEXT("\n")); } if(edl->num_tracks) { node = xmlNewTextChild(xml_edl, NULL, (xmlChar*)tracks_key, NULL); xmlAddChild(node, BG_XML_NEW_TEXT("\n")); for(i = 0; i < edl->num_tracks; i++) { child_node = xmlNewTextChild(node, NULL, (xmlChar*)track_key, NULL); xmlAddChild(child_node, BG_XML_NEW_TEXT("\n")); xmlAddChild(node, BG_XML_NEW_TEXT("\n")); if(edl->tracks[i].name) BG_XML_SET_PROP(child_node, "name", edl->tracks[i].name); if(edl->tracks[i].num_audio_streams) { streams_node = xmlNewTextChild(child_node, NULL, (xmlChar*)audio_streams_key, NULL); xmlAddChild(streams_node, BG_XML_NEW_TEXT("\n")); xmlAddChild(child_node, BG_XML_NEW_TEXT("\n")); save_streams(streams_node, edl->tracks[i].audio_streams, edl->tracks[i].num_audio_streams); } if(edl->tracks[i].num_video_streams) { streams_node = xmlNewTextChild(child_node, NULL, (xmlChar*)video_streams_key, NULL); xmlAddChild(streams_node, BG_XML_NEW_TEXT("\n")); xmlAddChild(child_node, BG_XML_NEW_TEXT("\n")); save_streams(streams_node, edl->tracks[i].video_streams, edl->tracks[i].num_video_streams); } if(edl->tracks[i].num_subtitle_text_streams) { streams_node = xmlNewTextChild(child_node, NULL, (xmlChar*)subtitle_text_streams_key, NULL); xmlAddChild(streams_node, BG_XML_NEW_TEXT("\n")); xmlAddChild(child_node, BG_XML_NEW_TEXT("\n")); save_streams(streams_node, edl->tracks[i].subtitle_text_streams, edl->tracks[i].num_subtitle_text_streams); } if(edl->tracks[i].num_subtitle_overlay_streams) { streams_node = xmlNewTextChild(child_node, NULL, (xmlChar*)subtitle_overlay_streams_key, NULL); xmlAddChild(streams_node, BG_XML_NEW_TEXT("\n")); xmlAddChild(child_node, BG_XML_NEW_TEXT("\n")); save_streams(streams_node, edl->tracks[i].subtitle_overlay_streams, edl->tracks[i].num_subtitle_overlay_streams); } xmlAddChild(xml_edl, BG_XML_NEW_TEXT("\n")); } } // xmlAddChild(xml_edl, BG_XML_NEW_TEXT("\n")); xmlSaveFile(filename, xml_doc); xmlFreeDoc(xml_doc); } gmerlin-1.2.0~dfsg/lib/visualize_slave.c0000644000175000017500000006336411764363410020231 0ustar alessioalessio/***************************************************************** * gmerlin - a general purpose multimedia framework and applications * * Copyright (c) 2001 - 2011 Members of the Gmerlin project * gmerlin-general@lists.sourceforge.net * http://gmerlin.sourceforge.net * * 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 of the License, 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 this program. If not, see . * *****************************************************************/ #include #include #include #include #include #include #include #include #include #include #include #define LOG_DOMAIN "visualizer_slave" #ifdef HAVE_LV #include #endif /* Messages from the application to the visualizer */ typedef struct { gavl_audio_converter_t * cnv; gavl_audio_frame_t * in_frame_1; gavl_audio_frame_t * in_frame_2; pthread_mutex_t in_mutex; int do_convert; gavl_audio_frame_t * out_frame; gavl_audio_format_t in_format; gavl_audio_format_t out_format; int last_samples_read; int frame_done; gavl_volume_control_t * gain_control; pthread_mutex_t gain_mutex; } audio_buffer_t; static audio_buffer_t * audio_buffer_create() { audio_buffer_t * ret; ret = calloc(1, sizeof(*ret)); ret->cnv = gavl_audio_converter_create(); pthread_mutex_init(&ret->in_mutex, NULL); pthread_mutex_init(&ret->gain_mutex, NULL); ret->gain_control = gavl_volume_control_create(); return ret; } static void audio_buffer_cleanup(audio_buffer_t * b) { if(b->in_frame_1) { gavl_audio_frame_destroy(b->in_frame_1); b->in_frame_1 = NULL; } if(b->in_frame_2) { gavl_audio_frame_destroy(b->in_frame_2); b->in_frame_2 = NULL; } if(b->out_frame) { gavl_audio_frame_destroy(b->out_frame); b->out_frame = NULL; } b->last_samples_read = 0; b->frame_done = 0; } static void audio_buffer_destroy(audio_buffer_t * b) { audio_buffer_cleanup(b); gavl_audio_converter_destroy(b->cnv); gavl_volume_control_destroy(b->gain_control); pthread_mutex_destroy(&b->in_mutex); pthread_mutex_destroy(&b->gain_mutex); free(b); } static void audio_buffer_init(audio_buffer_t * b, const gavl_audio_format_t * in_format, const gavl_audio_format_t * out_format) { gavl_audio_format_t frame_format; /* Cleanup */ audio_buffer_cleanup(b); gavl_audio_format_copy(&b->in_format, in_format); gavl_audio_format_copy(&b->out_format, out_format); /* For visualizations, we ignore the samplerate completely. Perfect synchronization is mathematically impossible anyway. */ b->out_format.samplerate = b->in_format.samplerate; b->do_convert = gavl_audio_converter_init(b->cnv, &b->in_format, &b->out_format); b->in_frame_1 = gavl_audio_frame_create(&b->in_format); gavl_audio_format_copy(&frame_format, out_format); frame_format.samples_per_frame = b->in_format.samples_per_frame; b->in_frame_2 = gavl_audio_frame_create(&frame_format); b->out_frame = gavl_audio_frame_create(&b->out_format); gavl_volume_control_set_format(b->gain_control, &frame_format); } static void audio_buffer_put(audio_buffer_t * b, const gavl_audio_frame_t * f) { pthread_mutex_lock(&b->in_mutex); b->in_frame_1->valid_samples = gavl_audio_frame_copy(&b->in_format, b->in_frame_1, f, 0, /* dst_pos */ 0, /* src_pos */ b->in_format.samples_per_frame, /* dst_size */ f->valid_samples /* src_size */ ); pthread_mutex_unlock(&b->in_mutex); } static void audio_buffer_set_gain(audio_buffer_t * b, float gain) { pthread_mutex_lock(&b->gain_mutex); gavl_volume_control_set_volume(b->gain_control, gain); pthread_mutex_unlock(&b->gain_mutex); } static gavl_audio_frame_t * audio_buffer_get(audio_buffer_t * b) { int samples_copied; /* Check if there is new audio */ pthread_mutex_lock(&b->in_mutex); if(b->in_frame_1->valid_samples) { if(b->do_convert) { gavl_audio_convert(b->cnv, b->in_frame_1, b->in_frame_2); samples_copied = b->in_frame_1->valid_samples; } else samples_copied = gavl_audio_frame_copy(&b->in_format, b->in_frame_2, b->in_frame_1, 0, /* dst_pos */ 0, /* src_pos */ b->in_format.samples_per_frame, /* dst_size */ b->in_frame_1->valid_samples /* src_size */ ); b->in_frame_2->valid_samples = samples_copied; b->last_samples_read = samples_copied; b->in_frame_1->valid_samples = 0; pthread_mutex_lock(&b->gain_mutex); gavl_volume_control_apply(b->gain_control, b->in_frame_2); pthread_mutex_unlock(&b->gain_mutex); } pthread_mutex_unlock(&b->in_mutex); /* If the frame was output the last time, set valid_samples to 0 */ if(b->frame_done) { b->out_frame->valid_samples = 0; b->frame_done = 0; } /* Copy to output frame and check if there are enough samples */ samples_copied = gavl_audio_frame_copy(&b->out_format, b->out_frame, b->in_frame_2, b->out_frame->valid_samples, /* dst_pos */ b->last_samples_read - b->in_frame_2->valid_samples, /* src_pos */ b->out_format.samples_per_frame - b->out_frame->valid_samples, /* dst_size */ b->in_frame_2->valid_samples /* src_size */ ); b->out_frame->valid_samples += samples_copied; b->in_frame_2->valid_samples -= samples_copied; if(b->out_frame->valid_samples == b->out_format.samples_per_frame) { b->frame_done = 1; return b->out_frame; } return NULL; } typedef struct { bg_plugin_handle_t * vis_handle; bg_plugin_handle_t * ov_handle; bg_plugin_api_t vis_api; audio_buffer_t * audio_buffer; gavl_video_converter_t * video_cnv; int do_convert_video; bg_ov_plugin_t * ov_plugin; bg_ov_callbacks_t ov_callbacks; bg_visualization_plugin_t * vis_plugin; gavl_video_format_t video_format_in; gavl_video_format_t video_format_in_real; gavl_video_format_t video_format_out; pthread_t video_thread; pthread_mutex_t running_mutex; pthread_mutex_t stop_mutex; pthread_mutex_t vis_mutex; pthread_mutex_t ov_mutex; int do_stop; gavl_video_frame_t * video_frame_in; // gavl_video_frame_t * video_frame_out; gavl_timer_t * timer; gavl_time_t last_frame_time; gavl_audio_format_t audio_format_in; gavl_audio_format_t audio_format_out; int do_ov; char * window_id; gavl_audio_frame_t * read_frame; pthread_mutex_t fps_mutex; float fps; bg_msg_queue_t * cb_queue; /* Pass events */ bg_ov_callbacks_t cb; } bg_visualizer_slave_t; static int init_plugin(bg_visualizer_slave_t * v); static bg_plugin_handle_t * load_plugin_gmerlin(const char * filename) { int (*get_plugin_api_version)(); bg_plugin_handle_t * ret; ret = calloc(1, sizeof(*ret)); ret->dll_handle = dlopen(filename, RTLD_NOW | RTLD_GLOBAL); if(!(ret->dll_handle)) { bg_log(BG_LOG_ERROR, LOG_DOMAIN, "Cannot dlopen plugin module %s: %s", filename, dlerror()); goto fail; } get_plugin_api_version = dlsym(ret->dll_handle, "get_plugin_api_version"); if(!get_plugin_api_version) { bg_log(BG_LOG_ERROR, LOG_DOMAIN, "cannot get API version: %s", dlerror()); goto fail; } if(get_plugin_api_version() != BG_PLUGIN_API_VERSION) { bg_log(BG_LOG_ERROR, LOG_DOMAIN, "Wrong API version: Got %d expected %d", get_plugin_api_version(), BG_PLUGIN_API_VERSION); goto fail; } ret->plugin = dlsym(ret->dll_handle, "the_plugin"); if(!ret) { bg_log(BG_LOG_ERROR, LOG_DOMAIN, "No symbol the_plugin: %s", dlerror()); goto fail; } ret->priv = ret->plugin->create(); return ret; fail: return NULL; } #ifdef HAVE_LV static bg_plugin_handle_t * load_plugin_lv(const char * name, int plugin_flags, const char * window_id) { bg_plugin_handle_t * ret; ret = calloc(1, sizeof(*ret)); if(!bg_lv_load(ret, name, plugin_flags, window_id)) { free(ret); return NULL; } return ret; } #endif // #define BG_VIS_MSG_CB_MOTION // x, y, mask // #define // x, y, button, mask // #define BG_VIS_MSG_CB_BUTTON_REL // x, y, button, mask static int ov_button_callback(void * data, int x, int y, int button, int mask) { bg_msg_t * msg; bg_visualizer_slave_t * s = data; msg = bg_msg_queue_lock_write(s->cb_queue); bg_msg_set_id(msg, BG_VIS_MSG_CB_BUTTON); bg_msg_set_arg_int(msg, 0, x); bg_msg_set_arg_int(msg, 1, y); bg_msg_set_arg_int(msg, 2, button); bg_msg_set_arg_int(msg, 3, mask); bg_msg_queue_unlock_write(s->cb_queue); return 1; } static int ov_button_release_callback(void * data, int x, int y, int button, int mask) { bg_msg_t * msg; bg_visualizer_slave_t * s = data; msg = bg_msg_queue_lock_write(s->cb_queue); bg_msg_set_id(msg, BG_VIS_MSG_CB_BUTTON_REL); bg_msg_set_arg_int(msg, 0, x); bg_msg_set_arg_int(msg, 1, y); bg_msg_set_arg_int(msg, 2, button); bg_msg_set_arg_int(msg, 3, mask); bg_msg_queue_unlock_write(s->cb_queue); return 1; } static int ov_motion_callback(void * data, int x, int y, int mask) { bg_msg_t * msg; bg_visualizer_slave_t * s = data; msg = bg_msg_queue_lock_write(s->cb_queue); bg_msg_set_id(msg, BG_VIS_MSG_CB_MOTION); bg_msg_set_arg_int(msg, 0, x); bg_msg_set_arg_int(msg, 1, y); bg_msg_set_arg_int(msg, 2, mask); bg_msg_queue_unlock_write(s->cb_queue); return 1; } static bg_visualizer_slave_t * bg_visualizer_slave_create(int argc, char ** argv) { int i; bg_visualizer_slave_t * ret; char * window_id = NULL; char * plugin_module = NULL; char * ov_module = NULL; /* Handle arguments and load plugins */ i = 1; while(i < argc) { if(!strcmp(argv[i], "-w")) { window_id = argv[i+1]; i += 2; } else if(!strcmp(argv[i], "-p")) { plugin_module = argv[i+1]; i += 2; } else if(!strcmp(argv[i], "-o")) { ov_module = argv[i+1]; i += 2; } } /* Sanity checks */ if(!window_id) { bg_log(BG_LOG_ERROR, LOG_DOMAIN, "No window ID given"); return NULL; } if(!plugin_module) { bg_log(BG_LOG_ERROR, LOG_DOMAIN, "No plugin given"); return NULL; } ret = calloc(1, sizeof(*ret)); ret->audio_buffer = audio_buffer_create(); ret->window_id = window_id; /* Create callbacks */ ret->cb.button_release_callback = ov_button_release_callback; ret->cb.button_callback = ov_button_callback; ret->cb.motion_callback = ov_motion_callback; ret->cb.data = ret; ret->cb_queue = bg_msg_queue_create(); pthread_mutex_init(&ret->stop_mutex, NULL); pthread_mutex_init(&ret->running_mutex, NULL); pthread_mutex_init(&ret->vis_mutex, NULL); pthread_mutex_init(&ret->ov_mutex, NULL); pthread_mutex_init(&ret->fps_mutex, NULL); ret->timer = gavl_timer_create(); /* Load ov module */ if(ov_module) { ret->do_ov = 1; ret->video_cnv = gavl_video_converter_create(); ret->ov_handle = load_plugin_gmerlin(ov_module); if(!ret->ov_handle) return NULL; ret->ov_plugin = (bg_ov_plugin_t*)ret->ov_handle->plugin; if(ret->ov_plugin->set_callbacks) ret->ov_plugin->set_callbacks(ret->ov_handle->priv, &ret->cb); ret->ov_plugin->set_window(ret->ov_handle->priv, ret->window_id); } ret->vis_api = BG_PLUGIN_API_GMERLIN; #ifdef HAVE_LV if(!strncmp(plugin_module, "vis_lv_", 7)) { if(ret->ov_handle) ret->vis_handle = load_plugin_lv(plugin_module, BG_PLUGIN_VISUALIZE_FRAME, ret->window_id); else ret->vis_handle = load_plugin_lv(plugin_module, BG_PLUGIN_VISUALIZE_GL, ret->window_id); ret->vis_api = BG_PLUGIN_API_LV; } else #endif ret->vis_handle = load_plugin_gmerlin(plugin_module); if(!ret->vis_handle) return NULL; ret->vis_plugin = (bg_visualization_plugin_t*)(ret->vis_handle->plugin); if(ret->vis_plugin->set_callbacks) ret->vis_plugin->set_callbacks(ret->vis_handle->priv, &ret->cb); return ret; } static void uload_plugin(bg_plugin_handle_t * h, bg_plugin_api_t api) { #ifdef HAVE_LV if(api == BG_PLUGIN_API_LV) { bg_lv_unload(h); free(h); return; } #endif h->plugin->destroy(h->priv); dlclose(h->dll_handle); free(h); } static void bg_visualizer_slave_destroy(bg_visualizer_slave_t * v) { pthread_mutex_destroy(&v->stop_mutex); if(v->video_cnv) gavl_video_converter_destroy(v->video_cnv); audio_buffer_destroy(v->audio_buffer); gavl_timer_destroy(v->timer); bg_msg_queue_destroy(v->cb_queue); pthread_mutex_destroy(&v->running_mutex); pthread_mutex_destroy(&v->fps_mutex); pthread_mutex_destroy(&v->stop_mutex); pthread_mutex_destroy(&v->ov_mutex); pthread_mutex_destroy(&v->vis_mutex); /* Close vis plugin */ v->vis_plugin->close(v->vis_handle->priv); uload_plugin(v->vis_handle, v->vis_api); /* Close OV Plugin */ if(v->do_ov) { if(v->video_frame_in) { gavl_video_frame_destroy(v->video_frame_in); v->video_frame_in = NULL; } v->ov_plugin->close(v->ov_handle->priv); uload_plugin(v->ov_handle, BG_PLUGIN_API_GMERLIN); } free(v); } static void * video_thread_func(void * data) { int do_stop; bg_visualizer_slave_t * v; gavl_audio_frame_t * audio_frame; gavl_time_t diff_time, current_time; float last_fps = -1.0; int64_t frame_time; gavl_video_frame_t * out_frame = NULL; v = (bg_visualizer_slave_t*)data; pthread_mutex_lock(&v->running_mutex); while(1) { /* Check if we should stop */ pthread_mutex_lock(&v->stop_mutex); do_stop = v->do_stop; pthread_mutex_unlock(&v->stop_mutex); if(do_stop) break; /* Draw frame */ pthread_mutex_lock(&v->vis_mutex); /* Check if we should update audio */ audio_frame = audio_buffer_get(v->audio_buffer); if(audio_frame) v->vis_plugin->update(v->vis_handle->priv, audio_frame); /* Draw frame */ if(!(v->do_ov)) v->vis_plugin->draw_frame(v->vis_handle->priv, NULL); else if(v->do_convert_video) { out_frame = v->ov_plugin->get_frame(v->ov_handle->priv); v->vis_plugin->draw_frame(v->vis_handle->priv, v->video_frame_in); gavl_video_convert(v->video_cnv, v->video_frame_in, out_frame); } else { out_frame = v->ov_plugin->get_frame(v->ov_handle->priv); v->vis_plugin->draw_frame(v->vis_handle->priv, out_frame); } pthread_mutex_unlock(&v->vis_mutex); /* Wait until we can show the frame */ current_time = gavl_timer_get(v->timer); diff_time = v->last_frame_time + v->video_format_in.frame_duration - current_time; if(diff_time > GAVL_TIME_SCALE / 1000) gavl_time_delay(&diff_time); /* Show frame */ if(v->do_ov) { pthread_mutex_lock(&v->ov_mutex); v->ov_plugin->put_video(v->ov_handle->priv, out_frame); frame_time = gavl_timer_get(v->timer); v->ov_plugin->handle_events(v->ov_handle->priv); pthread_mutex_unlock(&v->ov_mutex); } else { pthread_mutex_lock(&v->vis_mutex); v->vis_plugin->show_frame(v->vis_handle->priv); frame_time = gavl_timer_get(v->timer); pthread_mutex_unlock(&v->vis_mutex); } if(v->last_frame_time < frame_time) { if(last_fps < 0.0) { pthread_mutex_lock(&v->fps_mutex); v->fps = (double)(GAVL_TIME_SCALE) / (double)(frame_time - v->last_frame_time); last_fps = v->fps; pthread_mutex_unlock(&v->fps_mutex); } else { pthread_mutex_lock(&v->fps_mutex); v->fps = 0.95 * last_fps + 0.05 * (double)(GAVL_TIME_SCALE) / (double)(frame_time - v->last_frame_time); last_fps = v->fps; pthread_mutex_unlock(&v->fps_mutex); } } v->last_frame_time = frame_time; } pthread_mutex_unlock(&v->running_mutex); return NULL; } static int bg_visualizer_slave_stop(bg_visualizer_slave_t * v) { if(!pthread_mutex_trylock(&v->running_mutex)) { pthread_mutex_unlock(&v->running_mutex); return 0; } /* Join threads */ pthread_mutex_lock(&v->stop_mutex); v->do_stop = 1; pthread_mutex_unlock(&v->stop_mutex); pthread_join(v->video_thread, NULL); bg_log(BG_LOG_INFO, LOG_DOMAIN, "Joined thread"); gavl_timer_stop(v->timer); return 1; } static int bg_visualizer_slave_start(bg_visualizer_slave_t * v) { if(pthread_mutex_trylock(&v->running_mutex)) return 0; pthread_mutex_unlock(&v->running_mutex); v->fps = -1.0; v->do_stop = 0; v->last_frame_time = 0; gavl_timer_set(v->timer, 0); gavl_timer_start(v->timer); pthread_create(&v->video_thread, NULL, video_thread_func, v); bg_log(BG_LOG_INFO, LOG_DOMAIN, "Started thread"); return 1; } static void bg_visualizer_slave_set_audio_format(bg_visualizer_slave_t * v, const gavl_audio_format_t * format) { int was_running; was_running = bg_visualizer_slave_stop(v); pthread_mutex_lock(&v->audio_buffer->in_mutex); gavl_audio_format_copy(&v->audio_format_in, format); if(was_running) audio_buffer_init(v->audio_buffer, &v->audio_format_in, &v->audio_format_out); pthread_mutex_unlock(&v->audio_buffer->in_mutex); if(was_running) bg_visualizer_slave_start(v); } static void cleanup_plugin(bg_visualizer_slave_t * v) { } static int init_plugin(bg_visualizer_slave_t * v) { gavl_audio_format_copy(&v->audio_format_out, &v->audio_format_in); /* Set members, which might be missing */ v->video_format_in.pixel_width = 1; v->video_format_in.pixel_height = 1; /* Set video format */ gavl_video_format_copy(&v->video_format_in_real, &v->video_format_in); /* Open visualizer plugin */ if(v->do_ov) { v->vis_plugin->open_ov(v->vis_handle->priv, &v->audio_format_out, &v->video_format_in_real); gavl_video_format_copy(&v->video_format_out, &v->video_format_in_real); /* Open OV Plugin */ if(!v->ov_plugin->open(v->ov_handle->priv, &v->video_format_out, 0)) return 0; /* Initialize video converter */ v->do_convert_video = gavl_video_converter_init(v->video_cnv, &v->video_format_in_real, &v->video_format_out); if(v->do_convert_video) v->video_frame_in = gavl_video_frame_create(&v->video_format_in_real); } else { if(!v->vis_plugin->open_win(v->vis_handle->priv, &v->audio_format_out, v->window_id)) return 0; gavl_video_format_copy(&v->video_format_out, &v->video_format_in); } audio_buffer_init(v->audio_buffer, &v->audio_format_in, &v->audio_format_out); return 1; } static int msg_read_callback(void * priv, uint8_t * data, int len) { return read(STDIN_FILENO, data, len); } static int msg_write_callback(void * priv, const uint8_t * data, int len) { return write(STDOUT_FILENO, data, len); } static int write_message(bg_msg_t * msg) { int result; // fprintf(stderr, "Write message slave...\n"); result = bg_msg_write(msg, msg_write_callback, NULL); // fprintf(stderr, "Write message slave done %d\n", result); return result; } static void flush_queue(bg_msg_queue_t * queue) { bg_msg_t * msg; while((msg = bg_msg_queue_try_lock_read(queue))) { write_message(msg); bg_msg_queue_unlock_read(queue); } } int main(int argc, char ** argv) { gavl_audio_format_t audio_format; gavl_audio_frame_t * audio_frame = NULL; float arg_f; int keep_going; bg_visualizer_slave_t * s; bg_msg_t * msg; char * parameter_name = NULL; bg_parameter_value_t parameter_value; bg_msg_queue_t * log_queue; int counter = 0.0; bg_parameter_type_t parameter_type; gavl_dsp_context_t * ctx; int big_endian; int result; ctx = gavl_dsp_context_create(); memset(¶meter_value, 0, sizeof(parameter_value)); if(isatty(fileno(stdin))) { printf("This program is not meant to be started from the commandline.\nThe official frontend API for visualizatons is in " PREFIX "/include/gmerlin/visualize.h\n"); return -1; } log_queue = bg_msg_queue_create(); bg_log_set_dest(log_queue); s = bg_visualizer_slave_create(argc, argv); msg = bg_msg_create(); keep_going = 1; while(keep_going) { // fprintf(stderr, "Read message slave...\n"); result = bg_msg_read(msg, msg_read_callback, NULL); // fprintf(stderr, "Read message slave done %d\n", result); if(!result) break; switch(bg_msg_get_id(msg)) { case BG_VIS_MSG_AUDIO_FORMAT: bg_msg_get_arg_audio_format(msg, 0, &audio_format, &big_endian); bg_visualizer_slave_set_audio_format(s, &audio_format); if(audio_frame) gavl_audio_frame_destroy(audio_frame); audio_frame = gavl_audio_frame_create(&audio_format); break; case BG_VIS_MSG_AUDIO_DATA: bg_msg_read_audio_frame(ctx, msg, &audio_format, audio_frame, msg_read_callback, NULL, big_endian); if(!pthread_mutex_trylock(&s->running_mutex)) { pthread_mutex_unlock(&s->running_mutex); break; } else audio_buffer_put(s->audio_buffer, audio_frame); break; case BG_VIS_MSG_VIS_PARAM: bg_msg_get_parameter(msg, ¶meter_name, ¶meter_type, ¶meter_value); pthread_mutex_lock(&s->vis_mutex); s->vis_plugin->common.set_parameter(s->vis_handle->priv, parameter_name, ¶meter_value); pthread_mutex_unlock(&s->vis_mutex); if(parameter_name) { free(parameter_name); parameter_name = NULL; bg_parameter_value_free(¶meter_value, parameter_type); } break; case BG_VIS_MSG_OV_PARAM: bg_msg_get_parameter(msg, ¶meter_name, ¶meter_type, ¶meter_value); pthread_mutex_lock(&s->ov_mutex); s->ov_plugin->common.set_parameter(s->ov_handle->priv, parameter_name, ¶meter_value); pthread_mutex_unlock(&s->ov_mutex); if(parameter_name) { free(parameter_name); parameter_name = NULL; bg_parameter_value_free(¶meter_value, parameter_type); } break; case BG_VIS_MSG_GAIN: arg_f = bg_msg_get_arg_float(msg, 0); audio_buffer_set_gain(s->audio_buffer, arg_f); break; case BG_VIS_MSG_FPS: s->video_format_in.timescale = GAVL_TIME_SCALE; s->video_format_in.frame_duration = (int)(GAVL_TIME_SCALE / bg_msg_get_arg_float(msg, 0)); break; case BG_VIS_MSG_IMAGE_SIZE: s->video_format_in.image_width = bg_msg_get_arg_int(msg, 0); s->video_format_in.image_height = bg_msg_get_arg_int(msg, 1); s->video_format_in.frame_width = s->video_format_in.image_width; s->video_format_in.frame_height = s->video_format_in.image_height; break; case BG_VIS_MSG_START: if(!init_plugin(s)) bg_log(BG_LOG_ERROR, LOG_DOMAIN, "Starting visualization failed"); else bg_visualizer_slave_start(s); break; case BG_VIS_MSG_QUIT: keep_going = 0; break; case BG_VIS_MSG_TELL: flush_queue(log_queue); flush_queue(s->cb_queue); if(counter > 10) { counter = 0; bg_msg_set_id(msg, BG_VIS_SLAVE_MSG_FPS); pthread_mutex_lock(&s->fps_mutex); bg_msg_set_arg_float(msg, 0, s->fps); pthread_mutex_unlock(&s->fps_mutex); write_message(msg); bg_msg_free(msg); } counter++; bg_msg_set_id(msg, BG_VIS_SLAVE_MSG_END); write_message(msg); bg_msg_free(msg); break; } } bg_visualizer_slave_stop(s); cleanup_plugin(s); bg_visualizer_slave_destroy(s); bg_msg_free(msg); gavl_dsp_context_destroy(ctx); return 0; } gmerlin-1.2.0~dfsg/lib/threadpool.c0000644000175000017500000000656511764363410017165 0ustar alessioalessio/***************************************************************** * gmerlin - a general purpose multimedia framework and applications * * Copyright (c) 2001 - 2011 Members of the Gmerlin project * gmerlin-general@lists.sourceforge.net * http://gmerlin.sourceforge.net * * 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 of the License, 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 this program. If not, see . * *****************************************************************/ #include #include #include #include #include #include typedef struct { pthread_t t; sem_t run_sem; sem_t done_sem; pthread_mutex_t stop_mutex; int do_stop; void (*func)(void*, int, int); void * data; int start; int len; } thread_t; struct bg_thread_pool_s { int num_threads; thread_t * threads; }; static void * thread_func(void * data) { thread_t * t = data; int do_stop; while(1) { sem_wait(&t->run_sem); pthread_mutex_lock(&t->stop_mutex); do_stop = t->do_stop; pthread_mutex_unlock(&t->stop_mutex); if(do_stop) break; t->func(t->data, t->start, t->len); sem_post(&t->done_sem); } return NULL; } bg_thread_pool_t * bg_thread_pool_create(int num_threads) { int i; bg_thread_pool_t * ret = calloc(1, sizeof(*ret)); ret->num_threads = num_threads; ret->threads = calloc(num_threads, sizeof(*ret->threads)); for(i = 0; i < ret->num_threads; i++) { pthread_mutex_init(&ret->threads[i].stop_mutex, NULL); sem_init(&ret->threads[i].run_sem, 0, 0); sem_init(&ret->threads[i].done_sem, 0, 0); pthread_create(&ret->threads[i].t, NULL, thread_func, &ret->threads[i]); } return ret; } void bg_thread_pool_destroy(bg_thread_pool_t * p) { int i; for(i = 0; i < p->num_threads; i++) { pthread_mutex_lock(&p->threads[i].stop_mutex); p->threads[i].do_stop = 1; pthread_mutex_unlock(&p->threads[i].stop_mutex); sem_post(&p->threads[i].run_sem); pthread_join(p->threads[i].t, NULL); pthread_mutex_destroy(&p->threads[i].stop_mutex); sem_destroy(&p->threads[i].run_sem); sem_destroy(&p->threads[i].done_sem); } free(p->threads); free(p); } void bg_thread_pool_run(void (*func)(void*,int start, int len), void * gavl_data, int start, int len, void * client_data, int thread) { bg_thread_pool_t * p = client_data; p->threads[thread].func = func; p->threads[thread].data = gavl_data; p->threads[thread].start = start; p->threads[thread].len = len; sem_post(&p->threads[thread].run_sem); } void bg_thread_pool_stop(void * client_data, int thread) { bg_thread_pool_t * p = client_data; sem_wait(&p->threads[thread].done_sem); } gmerlin-1.2.0~dfsg/lib/language_table.c0000644000175000017500000002525111764363410017747 0ustar alessioalessio/***************************************************************** * gmerlin - a general purpose multimedia framework and applications * * Copyright (c) 2001 - 2011 Members of the Gmerlin project * gmerlin-general@lists.sourceforge.net * http://gmerlin.sourceforge.net * * 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 of the License, 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 this program. If not, see . * *****************************************************************/ #include #include char const * const bg_language_codes[] = { "aar", "abk", "ace", "ach", "ada", "afa", "afh", "afr", "aka", "akk", "ale", "alg", "amh", "ang", "apa", "ara", "arc", "arn", "arp", "art", "arw", "asm", "ath", "aus", "ava", "ave", "awa", "aym", "aze", "bad", "bai", "bak", "bal", "bam", "ban", "bas", "bat", "bej", "bel", "bem", "ben", "ber", "bho", "bih", "bik", "bin", "bis", "bla", "bnt", "tib", "bos", "bra", "bre", "btk", "bua", "bug", "bul", "cad", "cai", "car", "cat", "cau", "ceb", "cel", "cze", "cha", "chb", "che", "chg", "chk", "chm", "chn", "cho", "chp", "chr", "chu", "chv", "chy", "cmc", "cop", "cor", "cos", "cpe", "cpf", "cpp", "cre", "crp", "cus", "wel", "dak", "dan", "day", "del", "den", "ger", "dgr", "din", "div", "doi", "dra", "dua", "dum", "dyu", "dzo", "efi", "egy", "eka", "gre", "elx", "eng", "enm", "epo", "est", "baq", "ewe", "ewo", "fan", "fao", "per", "fat", "fij", "fin", "fiu", "fon", "fre", "frm", "fro", "fry", "ful", "fur", "gaa", "gay", "gba", "gem", "gez", "gil", "gla", "gle", "glg", "glv", "gmh", "goh", "gon", "gor", "got", "grb", "grc", "grn", "guj", "gwi", "hai", "hau", "haw", "heb", "her", "hil", "him", "hin", "hit", "hmn", "hmo", "scr", "hun", "hup", "arm", "iba", "ibo", "ijo", "iku", "ile", "ilo", "ina", "inc", "ind", "ine", "ipk", "ira", "iro", "ice", "ita", "jav", "jpn", "jpr", "kaa", "kab", "kac", "kal", "kam", "kan", "kar", "kas", "geo", "kau", "kaw", "kaz", "kha", "khi", "khm", "kho", "kik", "kin", "kir", "kmb", "kok", "kom", "kon", "kor", "kos", "kpe", "kro", "kru", "kum", "kur", "kut", "lad", "lah", "lam", "lao", "lat", "lav", "lez", "lin", "lit", "lol", "loz", "ltz", "lua", "lub", "lug", "lui", "lun", "luo", "lus", "mad", "mag", "mah", "mai", "mak", "mal", "man", "map", "mar", "mas", "mdr", "men", "mga", "mic", "min", "mis", "mac", "mkh", "mlg", "mlt", "mnc", "mni", "mno", "moh", "mol", "mon", "mos", "mao", "may", "mul", "mun", "mus", "mwr", "bur", "myn", "nah", "nai", "nau", "nav", "nbl", "nde", "ndo", "nds", "nep", "new", "nia", "nic", "niu", "dut", "nno", "nob", "non", "nor", "nso", "nub", "nya", "nym", "nyn", "nyo", "nzi", "oci", "oji", "ori", "orm", "osa", "oss", "ota", "oto", "paa", "pag", "pal", "pam", "pan", "pap", "pau", "peo", "phi", "pli", "pol", "pon", "por", "pra", "pro", "pus", "que", "raj", "rap", "rar", "roa", "rom", "rum", "run", "rus", "sad", "sag", "sah", "sai", "sal", "sam", "san", "sas", "sat", "sco", "sel", "sem", "sga", "sgn", "shn", "sid", "sin", "sio", "sit", "sla", "slo", "slv", "sme", "smi", "smo", "sna", "snd", "snk", "sog", "som", "son", "sot", "spa", "alb", "srd", "scc", "srr", "ssa", "ssw", "suk", "sun", "sus", "sux", "swa", "swe", "syr", "tah", "tai", "tam", "tat", "tel", "tem", "ter", "tet", "tgk", "tgl", "tha", "tig", "tir", "tiv", "tkl", "tli", "tmh", "tog", "ton", "tpi", "tsi", "tsn", "tso", "tuk", "tum", "tur", "tut", "tvl", "twi", "tyv", "uga", "uig", "ukr", "umb", "und", "urd", "uzb", "vai", "ven", "vie", "vol", "vot", "wak", "wal", "war", "was", "wen", "wol", "xho", "yao", "yap", "yid", "yor", "ypk", "zap", "zen", "zha", "chi", "znd", "zul", "zun", NULL, }; char const * const bg_language_labels[] = { "Afar", "Abkhazian", "Achinese", "Acoli", "Adangme", "Afro-Asiatic (Other)", "Afrihili", "Afrikaans", "Akan", "Akkadian", "Aleut", "Algonquian languages", "Amharic", "English, Old (ca. 450-1100)", "Apache languages", "Arabic", "Aramaic", "Araucanian", "Arapaho", "Artificial (Other)", "Arawak", "Assamese", "Athapascan languages", "Australian languages", "Avaric", "Avestan", "Awadhi", "Aymara", "Azerbaijani", "Banda", "Bamileke languages", "Bashkir", "Baluchi", "Bambara", "Balinese", "Basa", "Baltic (Other)", "Beja", "Belarusian", "Bemba", "Bengali", "Berber (Other)", "Bhojpuri", "Bihari", "Bikol", "Bini", "Bislama", "Siksika", "Bantu (Other)", "Tibetan", "Bosnian", "Braj", "Breton", "Batak (Indonesia)", "Buriat", "Buginese", "Bulgarian", "Caddo", "Central American Indian (Other)", "Carib", "Catalan", "Caucasian (Other)", "Cebuano", "Celtic (Other)", "Czech", "Chamorro", "Chibcha", "Chechen", "Chagatai", "Chuukese", "Mari", "Chinook jargon", "Choctaw", "Chipewyan", "Cherokee", "Church Slavic", "Chuvash", "Cheyenne", "Chamic languages", "Coptic", "Cornish", "Corsican", "Creoles and pidgins, English based (Other)", "Creoles and pidgins, French-based (Other)", "Creoles and pidgins, Portuguese-based (Other)", "Cree", "Creoles and pidgins (Other)", "Cushitic (Other)", "Welsh", "Dakota", "Danish", "Dayak", "Delaware", "Slave (Athapascan)", "German", "Dogrib", "Dinka", "Divehi", "Dogri", "Dravidian (Other)", "Duala", "Dutch, Middle (ca. 1050-1350)", "Dyula", "Dzongkha", "Efik", "Egyptian (Ancient)", "Ekajuk", "Greek, Modern (1453-)", "Elamite", "English", "English, Middle (1100-1500)", "Esperanto", "Estonian", "Basque", "Ewe", "Ewondo", "Fang", "Faroese", "Persian", "Fanti", "Fijian", "Finnish", "Finno-Ugrian (Other)", "Fon", "French", "French, Middle (ca. 1400-1600)", "French, Old (842-ca. 1400)", "Frisian", "Fulah", "Friulian", "Ga", "Gayo", "Gbaya", "Germanic (Other)", "Geez", "Gilbertese", "Gaelic (Scots)", "Irish", "Gallegan", "Manx", "German, Middle High (ca. 1050-1500)", "German, Old High (ca. 750-1050)", "Gondi", "Gorontalo", "Gothic", "Grebo", "Greek, Ancient (to 1453)", "Guarani", "Gujarati", "Gwich´in", "Haida", "Hausa", "Hawaiian", "Hebrew", "Herero", "Hiligaynon", "Himachali", "Hindi", "Hittite", "Hmong", "Hiri Motu", "Croatian", "Hungarian", "Hupa", "Armenian", "Iban", "Igbo", "Ijo", "Inuktitut", "Interlingue", "Iloko", "Interlingua (International Auxiliary Language Association)", "Indic (Other)", "Indonesian", "Indo-European (Other)", "Inupiaq", "Iranian (Other)", "Iroquoian languages", "Icelandic", "Italian", "Javanese", "Japanese", "Judeo-Persian", "Kara-Kalpak", "Kabyle", "Kachin", "Kalaallisut", "Kamba", "Kannada", "Karen", "Kashmiri", "Georgian", "Kanuri", "Kawi", "Kazakh", "Khasi", "Khoisan (Other)", "Khmer", "Khotanese", "Kikuyu", "Kinyarwanda", "Kirghiz", "Kimbundu", "Konkani", "Komi", "Kongo", "Korean", "Kosraean", "Kpelle", "Kru", "Kurukh", "Kumyk", "Kurdish", "Kutenai", "Ladino", "Lahnda", "Lamba", "Lao", "Latin", "Latvian", "Lezghian", "Lingala", "Lithuanian", "Mongo", "Lozi", "Letzeburgesch", "Luba-Lulua", "Luba-Katanga", "Ganda", "Luiseno", "Lunda", "Luo (Kenya and Tanzania)", "lushai", "Madurese", "Magahi", "Marshall", "Maithili", "Makasar", "Malayalam", "Mandingo", "Austronesian (Other)", "Marathi", "Masai", "Mandar", "Mende", "Irish, Middle (900-1200)", "Micmac", "Minangkabau", "Miscellaneous languages", "Macedonian", "Mon-Khmer (Other)", "Malagasy", "Maltese", "Manchu", "Manipuri", "Manobo languages", "Mohawk", "Moldavian", "Mongolian", "Mossi", "Maori", "Malay", "Multiple languages", "Munda languages", "Creek", "Marwari", "Burmese", "Mayan languages", "Nahuatl", "North American Indian", "Nauru", "Navajo", "Ndebele, South", "Ndebele, North", "Ndonga", "Low German; Low Saxon; German, Low; Saxon, Low", "Nepali", "Newari", "Nias", "Niger-Kordofanian (Other)", "Niuean", "Dutch", "Norwegian Nynorsk", "Norwegian Bokmål", "Norse, Old", "Norwegian", "Sotho, Northern", "Nubian languages", "Chichewa; Nyanja", "Nyamwezi", "Nyankole", "Nyoro", "Nzima", "Occitan (post 1500); Provençal", "Ojibwa", "Oriya", "Oromo", "Osage", "Ossetian; Ossetic", "Turkish, Ottoman (1500-1928)", "Otomian languages", "Papuan (Other)", "Pangasinan", "Pahlavi", "Pampanga", "Panjabi", "Papiamento", "Palauan", "Persian, Old (ca. 600-400 b.c.)", "Philippine (Other)", "Pali", "Polish", "Pohnpeian", "Portuguese", "Prakrit languages", "Provençal, Old (to 1500)", "Pushto", "Quechua", "Rajasthani", "Rapanui", "Rarotongan", "Romance (Other)", "Romany", "Romanian", "Rundi", "Russian", "Sandawe", "Sango", "Yakut", "South American Indian (Other)", "Salishan languages", "Samaritan Aramaic", "Sanskrit", "Sasak", "Santali", "Scots", "Selkup", "Semitic (Other)", "Irish, Old (to 900)", "Sign Languages", "Shan", "Sidamo", "Sinhalese", "Siouan languages", "Sino-Tibetan (Other)", "Slavic (Other)", "Slovak", "Slovenian", "Northern Sami", "Sami languages (Other)", "Samoan", "Shona", "Sindhi", "Soninke", "Sogdian", "Somali", "Songhai", "Sotho, Southern", "Spanish", "Albanian", "Sardinian", "Serbian", "Serer", "Nilo-Saharan (Other)", "Swati", "Sukuma", "Sundanese", "Susu", "Sumerian", "Swahili", "Swedish", "Syriac", "Tahitian", "Tai (Other)", "Tamil", "Tatar", "Telugu", "Timne", "Tereno", "Tetum", "Tajik", "Tagalog", "Thai", "Tigre", "Tigrinya", "Tiv", "Tokelau", "Tlingit", "Tamashek", "Tonga (Nyasa)", "Tonga (Tonga Islands)", "Tok Pisin", "Tsimshian", "Tswana", "Tsonga", "Turkmen", "Tumbuka", "Turkish", "Altaic (Other)", "Tuvalu", "Twi", "Tuvinian", "Ugaritic", "Uighur", "Ukrainian", "Umbundu", "Undetermined", "Urdu", "Uzbek", "Vai", "Venda", "Vietnamese", "Volapük", "Votic", "Wakashan languages", "Walamo", "Waray", "Washo", "Sorbian languages", "Wolof", "Xhosa", "Yao", "Yapese", "Yiddish", "Yoruba", "Yupik languages", "Zapotec", "Zenaga", "Zhuang", "Chinese", "Zande", "Zulu", "Zuni", NULL, }; gmerlin-1.2.0~dfsg/lib/preset_xml.c0000644000175000017500000000355611764363410017203 0ustar alessioalessio/***************************************************************** * gmerlin - a general purpose multimedia framework and applications * * Copyright (c) 2001 - 2011 Members of the Gmerlin project * gmerlin-general@lists.sourceforge.net * http://gmerlin.sourceforge.net * * 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 of the License, 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 this program. If not, see . * *****************************************************************/ #include #include #include #include bg_cfg_section_t * bg_preset_load(bg_preset_t * p) { xmlNodePtr node; xmlDocPtr xml_doc; bg_cfg_section_t * ret; xml_doc = bg_xml_parse_file(p->file); if(!xml_doc) return NULL; node = xml_doc->children; if(BG_XML_STRCMP(node->name, "PRESET")) { xmlFreeDoc(xml_doc); } ret = bg_cfg_section_create(NULL); bg_cfg_xml_2_section(xml_doc, node, ret); xmlFreeDoc(xml_doc); return ret; } void bg_preset_save(bg_preset_t * p, const bg_cfg_section_t * s) { xmlDocPtr xml_doc; xmlNodePtr node; xml_doc = xmlNewDoc((xmlChar*)"1.0"); node = xmlNewDocRawNode(xml_doc, NULL, (xmlChar*)"PRESET", NULL); xmlDocSetRootElement(xml_doc, node); bg_cfg_section_2_xml(s, node); xmlSaveFile(p->file, xml_doc); xmlFreeDoc(xml_doc); } gmerlin-1.2.0~dfsg/lib/translation.c0000644000175000017500000000302511764363410017346 0ustar alessioalessio/***************************************************************** * gmerlin - a general purpose multimedia framework and applications * * Copyright (c) 2001 - 2011 Members of the Gmerlin project * gmerlin-general@lists.sourceforge.net * http://gmerlin.sourceforge.net * * 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 of the License, 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 this program. If not, see . * *****************************************************************/ #include #include #include #include static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; static int translation_initialized = 0; void bg_translation_init() { pthread_mutex_lock(&mutex); if(!translation_initialized) { bg_bindtextdomain (PACKAGE, LOCALE_DIR); translation_initialized = 1; } pthread_mutex_unlock(&mutex); } void bg_bindtextdomain(const char * domainname, const char * dirname) { bindtextdomain(domainname, dirname); setlocale(LC_NUMERIC, "C"); } gmerlin-1.2.0~dfsg/lib/bggavl.c0000644000175000017500000005717711764363410016273 0ustar alessioalessio/***************************************************************** * gmerlin - a general purpose multimedia framework and applications * * Copyright (c) 2001 - 2011 Members of the Gmerlin project * gmerlin-general@lists.sourceforge.net * http://gmerlin.sourceforge.net * * 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 of the License, 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 this program. If not, see . * *****************************************************************/ #include #include #include #include #include #include #include #define LOG_DOMAIN "bggavl" #define SP_INT(s) if(!strcmp(name, # s)) \ { \ opt->s = val->val_i; \ return 1; \ } #define SP_FLOAT(s) if(!strcmp(name, # s)) \ { \ opt->s = val->val_f; \ return 1; \ } /* Audio stuff */ int bg_gavl_audio_set_parameter(void * data, const char * name, const bg_parameter_value_t * val) { bg_gavl_audio_options_t * opt = (bg_gavl_audio_options_t *)data; if(!name) return 1; if(!strcmp(name, "conversion_quality")) { if(val->val_i != gavl_audio_options_get_quality(opt->opt)) opt->options_changed = 1; gavl_audio_options_set_quality(opt->opt, val->val_i); return 1; } SP_INT(fixed_samplerate); if(!strcmp(name, "sampleformat")) { gavl_sample_format_t force_format = GAVL_SAMPLE_NONE; if(!strcmp(val->val_str, "8")) force_format = GAVL_SAMPLE_S8; else if(!strcmp(val->val_str, "16")) force_format = GAVL_SAMPLE_S16; else if(!strcmp(val->val_str, "32")) force_format = GAVL_SAMPLE_S32; else if(!strcmp(val->val_str, "f")) force_format = GAVL_SAMPLE_FLOAT; else if(!strcmp(val->val_str, "d")) force_format = GAVL_SAMPLE_DOUBLE; if(force_format != opt->force_format) { opt->force_format = force_format; opt->options_changed = 1; } return 1; } SP_INT(samplerate); SP_INT(fixed_channel_setup); SP_INT(num_front_channels); SP_INT(num_rear_channels); SP_INT(num_lfe_channels); if(!strcmp(name, "front_to_rear")) { int old_flags, new_flags; if(!val->val_str) return 1; old_flags = gavl_audio_options_get_conversion_flags(opt->opt); new_flags = old_flags & ~GAVL_AUDIO_FRONT_TO_REAR_MASK; if(!strcmp(val->val_str, "copy")) new_flags |= GAVL_AUDIO_FRONT_TO_REAR_COPY; else if(!strcmp(val->val_str, "mute")) new_flags |= GAVL_AUDIO_FRONT_TO_REAR_MUTE; else if(!strcmp(val->val_str, "diff")) new_flags |= GAVL_AUDIO_FRONT_TO_REAR_DIFF; if(old_flags != new_flags) opt->options_changed = 1; gavl_audio_options_set_conversion_flags(opt->opt, new_flags); return 1; } else if(!strcmp(name, "stereo_to_mono")) { int old_flags, new_flags = GAVL_AUDIO_STEREO_TO_MONO_MIX; if(!val->val_str) return 1; old_flags = gavl_audio_options_get_conversion_flags(opt->opt); new_flags = (old_flags & ~GAVL_AUDIO_STEREO_TO_MONO_MASK); if(!strcmp(val->val_str, "left")) new_flags |= GAVL_AUDIO_STEREO_TO_MONO_LEFT; else if(!strcmp(val->val_str, "right")) new_flags |= GAVL_AUDIO_STEREO_TO_MONO_RIGHT; else if(!strcmp(val->val_str, "mix")) new_flags |= GAVL_AUDIO_STEREO_TO_MONO_MIX; if(old_flags |= new_flags) opt->options_changed = 1; gavl_audio_options_set_conversion_flags(opt->opt, new_flags); return 1; } else if(!strcmp(name, "dither_mode")) { gavl_audio_dither_mode_t dither_mode = GAVL_AUDIO_DITHER_AUTO; if(!strcmp(val->val_str, "auto")) { dither_mode = GAVL_AUDIO_DITHER_AUTO; } else if(!strcmp(val->val_str, "none")) { dither_mode = GAVL_AUDIO_DITHER_NONE; } else if(!strcmp(val->val_str, "rect")) { dither_mode = GAVL_AUDIO_DITHER_RECT; } else if(!strcmp(val->val_str, "shaped")) { dither_mode = GAVL_AUDIO_DITHER_SHAPED; } if(dither_mode != gavl_audio_options_get_dither_mode(opt->opt)) opt->options_changed = 1; gavl_audio_options_set_dither_mode(opt->opt, dither_mode); return 1; } else if(!strcmp(name, "resample_mode")) { gavl_resample_mode_t resample_mode = GAVL_RESAMPLE_AUTO; if(!strcmp(val->val_str, "auto")) gavl_audio_options_set_resample_mode(opt->opt, GAVL_RESAMPLE_AUTO); else if(!strcmp(val->val_str, "linear")) resample_mode = GAVL_RESAMPLE_LINEAR; else if(!strcmp(val->val_str, "zoh")) resample_mode = GAVL_RESAMPLE_ZOH; else if(!strcmp(val->val_str, "sinc_fast")) resample_mode = GAVL_RESAMPLE_SINC_FAST; else if(!strcmp(val->val_str, "sinc_medium")) resample_mode = GAVL_RESAMPLE_SINC_MEDIUM; else if(!strcmp(val->val_str, "sinc_best")) resample_mode = GAVL_RESAMPLE_SINC_BEST; if(resample_mode != gavl_audio_options_get_resample_mode(opt->opt)) opt->options_changed = 1; gavl_audio_options_set_resample_mode(opt->opt, resample_mode); return 1; } return 0; } void bg_gavl_audio_options_init(bg_gavl_audio_options_t *opt) { opt->opt = gavl_audio_options_create(); } void bg_gavl_audio_options_free(bg_gavl_audio_options_t * opt) { if(opt->opt) gavl_audio_options_destroy(opt->opt); } void bg_gavl_audio_options_set_format(const bg_gavl_audio_options_t * opt, const gavl_audio_format_t * in_format, gavl_audio_format_t * out_format) { int channel_index; if(in_format) gavl_audio_format_copy(out_format, in_format); if(opt->fixed_samplerate || !in_format) { out_format->samplerate = opt->samplerate; } if(opt->fixed_channel_setup || !in_format) { out_format->num_channels = opt->num_front_channels + opt->num_rear_channels + opt->num_lfe_channels; channel_index = 0; switch(opt->num_front_channels) { case 1: out_format->channel_locations[channel_index] = GAVL_CHID_FRONT_CENTER; break; case 2: out_format->channel_locations[channel_index] = GAVL_CHID_FRONT_LEFT; out_format->channel_locations[channel_index+1] = GAVL_CHID_FRONT_RIGHT; break; case 3: out_format->channel_locations[channel_index] = GAVL_CHID_FRONT_LEFT; out_format->channel_locations[channel_index+1] = GAVL_CHID_FRONT_RIGHT; out_format->channel_locations[channel_index+2] = GAVL_CHID_FRONT_CENTER; break; case 4: out_format->channel_locations[channel_index] = GAVL_CHID_FRONT_LEFT; out_format->channel_locations[channel_index+1] = GAVL_CHID_FRONT_RIGHT; out_format->channel_locations[channel_index+2] = GAVL_CHID_FRONT_CENTER_LEFT; out_format->channel_locations[channel_index+3] = GAVL_CHID_FRONT_CENTER_LEFT; break; case 5: out_format->channel_locations[channel_index] = GAVL_CHID_FRONT_LEFT; out_format->channel_locations[channel_index+1] = GAVL_CHID_FRONT_RIGHT; out_format->channel_locations[channel_index+2] = GAVL_CHID_FRONT_CENTER_LEFT; out_format->channel_locations[channel_index+3] = GAVL_CHID_FRONT_CENTER_LEFT; out_format->channel_locations[channel_index+4] = GAVL_CHID_FRONT_CENTER; break; } channel_index += opt->num_front_channels; switch(opt->num_rear_channels) { case 1: out_format->channel_locations[channel_index] = GAVL_CHID_REAR_CENTER; break; case 2: out_format->channel_locations[channel_index] = GAVL_CHID_REAR_LEFT; out_format->channel_locations[channel_index+1] = GAVL_CHID_REAR_RIGHT; break; case 3: out_format->channel_locations[channel_index] = GAVL_CHID_REAR_LEFT; out_format->channel_locations[channel_index+1] = GAVL_CHID_REAR_RIGHT; out_format->channel_locations[channel_index+2] = GAVL_CHID_REAR_CENTER; break; } channel_index += opt->num_rear_channels; switch(opt->num_lfe_channels) { case 1: out_format->channel_locations[channel_index] = GAVL_CHID_LFE; break; } channel_index += opt->num_lfe_channels; } if(opt->force_format != GAVL_SAMPLE_NONE) out_format->sample_format = opt->force_format; } /* Video */ /* Definitions for standard resolutions */ /* Frame rates */ #define FRAME_RATE_FROM_INPUT 0 #define FRAME_RATE_USER 1 #define FRAME_RATE_23_976 2 #define FRAME_RATE_24 3 #define FRAME_RATE_25 4 #define FRAME_RATE_29_970 5 #define FRAME_RATE_30 6 #define FRAME_RATE_50 7 #define FRAME_RATE_59_940 8 #define FRAME_RATE_60 9 #define NUM_FRAME_RATES 10 static const struct { int rate; char * name; } framerate_strings[NUM_FRAME_RATES] = { { FRAME_RATE_FROM_INPUT, "from_source" }, { FRAME_RATE_USER, "user_defined" }, { FRAME_RATE_23_976, "23_976" }, { FRAME_RATE_24, "24" }, { FRAME_RATE_25, "25" }, { FRAME_RATE_29_970, "29_970" }, { FRAME_RATE_30, "30" }, { FRAME_RATE_50, "50" }, { FRAME_RATE_59_940, "59_940" }, { FRAME_RATE_60, "60" }, }; static const struct { int rate; int timescale; int frame_duration; } framerate_rates[NUM_FRAME_RATES] = { { FRAME_RATE_FROM_INPUT, 0, 0 }, { FRAME_RATE_USER, 0, 0 }, { FRAME_RATE_23_976, 24000, 1001 }, { FRAME_RATE_24, 24, 1 }, { FRAME_RATE_25, 25, 1 }, { FRAME_RATE_29_970, 30000, 1001 }, { FRAME_RATE_30, 30, 1 }, { FRAME_RATE_50, 50, 1 }, { FRAME_RATE_59_940, 60000, 1001 }, { FRAME_RATE_60, 60, 1 }, }; static int get_frame_rate_mode(const char * str) { int i; for(i = 0; i < NUM_FRAME_RATES; i++) { if(!strcmp(str, framerate_strings[i].name)) { return framerate_strings[i].rate; } } return FRAME_RATE_USER; } #define SP_FLAG(s, flag) if(!strcmp(name, s)) { \ flags = gavl_video_options_get_conversion_flags(opt->opt); \ if((val->val_i) && !(flags & flag)) \ { \ opt->options_changed = 1; \ flags |= flag; \ } \ else if(!(val->val_i) && (flags & flag)) \ { \ opt->options_changed = 1; \ flags &= ~flag; \ } \ gavl_video_options_set_conversion_flags(opt->opt, flags); \ return 1; \ } gavl_scale_mode_t bg_gavl_string_to_scale_mode(const char * str) { if(!strcmp(str, "auto")) return GAVL_SCALE_AUTO; else if(!strcmp(str, "nearest")) return GAVL_SCALE_NEAREST; else if(!strcmp(str, "bilinear")) return GAVL_SCALE_BILINEAR; else if(!strcmp(str, "quadratic")) return GAVL_SCALE_QUADRATIC; else if(!strcmp(str, "cubic_bspline")) return GAVL_SCALE_CUBIC_BSPLINE; else if(!strcmp(str, "cubic_mitchell")) return GAVL_SCALE_CUBIC_MITCHELL; else if(!strcmp(str, "cubic_catmull")) return GAVL_SCALE_CUBIC_CATMULL; else if(!strcmp(str, "sinc_lanczos")) return GAVL_SCALE_SINC_LANCZOS; else { bg_log(BG_LOG_ERROR, LOG_DOMAIN, "Unknown scale mode %s\n", str); return GAVL_SCALE_AUTO; } } gavl_downscale_filter_t bg_gavl_string_to_downscale_filter(const char * str) { if(!strcmp(str, "auto")) return GAVL_DOWNSCALE_FILTER_AUTO; else if(!strcmp(str, "none")) return GAVL_DOWNSCALE_FILTER_NONE; else if(!strcmp(str, "wide")) return GAVL_DOWNSCALE_FILTER_WIDE; else if(!strcmp(str, "gauss")) return GAVL_DOWNSCALE_FILTER_GAUSS; else { bg_log(BG_LOG_ERROR, LOG_DOMAIN, "Unknown scale mode %s\n", str); return GAVL_DOWNSCALE_FILTER_GAUSS; } } #define FRAME_SIZE_FROM_INPUT 0 #define FRAME_SIZE_USER 1 #define FRAME_SIZE_PAL_D1 2 #define FRAME_SIZE_PAL_D1_WIDE 3 #define FRAME_SIZE_PAL_DV 4 #define FRAME_SIZE_PAL_DV_WIDE 5 #define FRAME_SIZE_PAL_CVD 6 #define FRAME_SIZE_PAL_VCD 7 #define FRAME_SIZE_PAL_SVCD 8 #define FRAME_SIZE_PAL_SVCD_WIDE 9 #define FRAME_SIZE_NTSC_D1 10 #define FRAME_SIZE_NTSC_D1_WIDE 11 #define FRAME_SIZE_NTSC_DV 12 #define FRAME_SIZE_NTSC_DV_WIDE 13 #define FRAME_SIZE_NTSC_CVD 14 #define FRAME_SIZE_NTSC_VCD 15 #define FRAME_SIZE_NTSC_SVCD 16 #define FRAME_SIZE_NTSC_SVCD_WIDE 17 #define FRAME_SIZE_VGA 18 #define FRAME_SIZE_QVGA 19 #define FRAME_SIZE_720 20 #define FRAME_SIZE_1080 21 #define FRAME_SIZE_SQCIF 22 #define FRAME_SIZE_QCIF 23 #define FRAME_SIZE_CIF 24 #define FRAME_SIZE_4CIF 25 #define FRAME_SIZE_16CIF 26 #define NUM_FRAME_SIZES 27 static const struct { const char * name; int size; int image_width; int image_height; int pixel_width; int pixel_height; } framesizes[] = { { "from_input", FRAME_SIZE_FROM_INPUT, 0, 0, 0, 0}, { "user_defined", FRAME_SIZE_USER, 0, 0, 0, 0}, { "pal_d1", FRAME_SIZE_PAL_D1, 720, 576, 59, 54}, { "pal_d1_wide", FRAME_SIZE_PAL_D1_WIDE, 720, 576, 118, 81}, { "pal_dv", FRAME_SIZE_PAL_DV, 720, 576, 59, 54}, { "pal_dv_wide", FRAME_SIZE_PAL_DV_WIDE, 720, 576, 118, 81}, { "pal_cvd", FRAME_SIZE_PAL_CVD, 352, 576, 59, 27}, { "pal_vcd", FRAME_SIZE_PAL_VCD, 352, 288, 59, 54}, { "pal_svcd", FRAME_SIZE_PAL_SVCD, 480, 576, 59, 36}, { "pal_svcd_wide", FRAME_SIZE_PAL_SVCD_WIDE, 480, 576, 59, 27}, { "ntsc_d1", FRAME_SIZE_NTSC_D1, 720, 480, 10, 11}, { "ntsc_d1_wide", FRAME_SIZE_NTSC_D1_WIDE, 720, 480, 40, 33}, { "ntsc_dv", FRAME_SIZE_NTSC_DV, 720, 480, 10, 11}, { "ntsc_dv_wide", FRAME_SIZE_NTSC_DV_WIDE, 720, 480, 40, 33}, { "ntsc_cvd", FRAME_SIZE_NTSC_CVD, 352, 480, 20, 11}, { "ntsc_vcd", FRAME_SIZE_NTSC_VCD, 352, 240, 10, 11}, { "ntsc_svcd", FRAME_SIZE_NTSC_SVCD, 480, 480, 15, 11}, { "ntsc_svcd_wide", FRAME_SIZE_NTSC_SVCD_WIDE, 480, 480, 20, 11}, { "720", FRAME_SIZE_720, 1280, 720, 1, 1}, { "1080", FRAME_SIZE_1080, 1920, 1080, 1, 1}, { "vga", FRAME_SIZE_VGA, 640, 480, 1, 1}, { "qvga", FRAME_SIZE_QVGA, 320, 240, 1, 1}, { "sqcif", FRAME_SIZE_SQCIF, 128, 96, 12, 11}, { "qcif", FRAME_SIZE_QCIF, 176, 144, 12, 11}, { "cif", FRAME_SIZE_CIF, 352, 288, 12, 11}, { "4cif", FRAME_SIZE_4CIF, 704, 576, 12, 11}, { "16cif", FRAME_SIZE_16CIF, 1408, 1152, 12, 11}, }; static void set_frame_size_mode(bg_gavl_video_options_t * opt, const bg_parameter_value_t * val) { int i; for(i = 0; i < NUM_FRAME_SIZES; i++) { if(!strcmp(val->val_str, framesizes[i].name)) opt->size = framesizes[i].size; } } void bg_gavl_video_options_set_frame_size(const bg_gavl_video_options_t * opt, const gavl_video_format_t * in_format, gavl_video_format_t * out_format) { int i; if(opt->size == FRAME_SIZE_FROM_INPUT) { out_format->image_width = in_format->image_width; out_format->image_height = in_format->image_height; out_format->frame_width = in_format->frame_width; out_format->frame_height = in_format->frame_height; out_format->pixel_width = in_format->pixel_width; out_format->pixel_height = in_format->pixel_height; return; } else if(opt->size == FRAME_SIZE_USER) { out_format->image_width = opt->user_image_width; out_format->image_height = opt->user_image_height; out_format->frame_width = opt->user_image_width; out_format->frame_height = opt->user_image_height; out_format->pixel_width = opt->user_pixel_width; out_format->pixel_height = opt->user_pixel_height; return; } for(i = 0; i < NUM_FRAME_SIZES; i++) { if(opt->size == framesizes[i].size) { out_format->image_width = framesizes[i].image_width; out_format->image_height = framesizes[i].image_height; out_format->frame_width = framesizes[i].image_width; out_format->frame_height = framesizes[i].image_height; out_format->pixel_width = framesizes[i].pixel_width; out_format->pixel_height = framesizes[i].pixel_height; } } } int bg_gavl_video_set_parameter(void * data, const char * name, const bg_parameter_value_t * val) { int flags; bg_gavl_video_options_t * opt = (bg_gavl_video_options_t *)data; if(!name) return 1; if(!strcmp(name, "conversion_quality")) { if(val->val_i != gavl_video_options_get_quality(opt->opt)) opt->options_changed = 1; gavl_video_options_set_quality(opt->opt, val->val_i); return 1; } else if(!strcmp(name, "framerate")) { opt->framerate_mode = get_frame_rate_mode(val->val_str); return 1; } else if(!strcmp(name, "frame_size")) { set_frame_size_mode(opt, val); return 1; } else if(!strcmp(name, "pixelformat")) { opt->pixelformat = gavl_string_to_pixelformat(val->val_str); return 1; } // SP_INT(fixed_framerate); SP_INT(frame_duration); SP_INT(timescale); SP_INT(user_image_width); SP_INT(user_image_height); SP_INT(user_pixel_width); SP_INT(user_pixel_height); // SP_INT(maintain_aspect); SP_FLAG("force_deinterlacing", GAVL_FORCE_DEINTERLACE); SP_FLAG("resample_chroma", GAVL_RESAMPLE_CHROMA); if(!strcmp(name, "alpha_mode")) { if(!strcmp(val->val_str, "ignore")) { gavl_video_options_set_alpha_mode(opt->opt, GAVL_ALPHA_IGNORE); } else if(!strcmp(val->val_str, "blend_color")) { gavl_video_options_set_alpha_mode(opt->opt, GAVL_ALPHA_BLEND_COLOR); } return 1; } else if(!strcmp(name, "background_color")) { gavl_video_options_set_background_color(opt->opt, val->val_color); return 1; } else if(!strcmp(name, "scale_mode")) { gavl_video_options_set_scale_mode(opt->opt, bg_gavl_string_to_scale_mode(val->val_str)); return 1; } else if(!strcmp(name, "scale_order")) { gavl_video_options_set_scale_order(opt->opt, val->val_i); } else if(!strcmp(name, "deinterlace_mode")) { if(!strcmp(val->val_str, "none")) gavl_video_options_set_deinterlace_mode(opt->opt, GAVL_DEINTERLACE_NONE); else if(!strcmp(val->val_str, "copy")) gavl_video_options_set_deinterlace_mode(opt->opt, GAVL_DEINTERLACE_COPY); else if(!strcmp(val->val_str, "scale")) gavl_video_options_set_deinterlace_mode(opt->opt, GAVL_DEINTERLACE_SCALE); } else if(!strcmp(name, "deinterlace_drop_mode")) { if(!strcmp(val->val_str, "top")) gavl_video_options_set_deinterlace_drop_mode(opt->opt, GAVL_DEINTERLACE_DROP_TOP); else if(!strcmp(val->val_str, "bottom")) gavl_video_options_set_deinterlace_drop_mode(opt->opt, GAVL_DEINTERLACE_DROP_BOTTOM); } else if(!strcmp(name, "threads")) { opt->num_threads = val->val_i; if(!opt->thread_pool) { opt->thread_pool = bg_thread_pool_create(opt->num_threads); gavl_video_options_set_num_threads(opt->opt, opt->num_threads); gavl_video_options_set_run_func(opt->opt, bg_thread_pool_run, opt->thread_pool); gavl_video_options_set_stop_func(opt->opt, bg_thread_pool_stop, opt->thread_pool); } return 1; } return 0; } #undef SP_INT void bg_gavl_video_options_init(bg_gavl_video_options_t * opt) { opt->opt = gavl_video_options_create(); } void bg_gavl_video_options_free(bg_gavl_video_options_t * opt) { if(opt->opt) gavl_video_options_destroy(opt->opt); if(opt->thread_pool) bg_thread_pool_destroy(opt->thread_pool); } void bg_gavl_video_options_set_framerate(const bg_gavl_video_options_t * opt, const gavl_video_format_t * in_format, gavl_video_format_t * out_format) { int i; if(opt->framerate_mode == FRAME_RATE_FROM_INPUT) { out_format->frame_duration = in_format->frame_duration; out_format->timescale = in_format->timescale; out_format->framerate_mode = in_format->framerate_mode; return; } else if(opt->framerate_mode == FRAME_RATE_USER) { out_format->frame_duration = opt->frame_duration; out_format->timescale = opt->timescale; out_format->framerate_mode = GAVL_FRAMERATE_CONSTANT; return; } else { for(i = 0; i < NUM_FRAME_RATES; i++) { if(opt->framerate_mode == framerate_rates[i].rate) { out_format->timescale = framerate_rates[i].timescale; out_format->frame_duration = framerate_rates[i].frame_duration; out_format->framerate_mode = GAVL_FRAMERATE_CONSTANT; return; } } } } static void set_interlace(const bg_gavl_video_options_t * opt, const gavl_video_format_t * in_format, gavl_video_format_t * out_format) { int flags = gavl_video_options_get_conversion_flags(opt->opt); if(flags & GAVL_FORCE_DEINTERLACE) out_format->interlace_mode = GAVL_INTERLACE_NONE; else out_format->interlace_mode = in_format->interlace_mode; } void bg_gavl_video_options_set_pixelformat(const bg_gavl_video_options_t * opt, const gavl_video_format_t * in_format, gavl_video_format_t * out_format) { if(opt->pixelformat == GAVL_PIXELFORMAT_NONE) out_format->pixelformat = in_format->pixelformat; else out_format->pixelformat = opt->pixelformat; } void bg_gavl_video_options_set_format(const bg_gavl_video_options_t * opt, const gavl_video_format_t * in_format, gavl_video_format_t * out_format) { bg_gavl_video_options_set_framerate(opt, in_format, out_format); set_interlace(opt, in_format, out_format); bg_gavl_video_options_set_frame_size(opt, in_format, out_format); } int bg_overlay_too_old(gavl_time_t time, gavl_time_t ovl_time, gavl_time_t ovl_duration) { if((ovl_duration >= 0) && (time > ovl_time + ovl_duration)) return 1; return 0; } int bg_overlay_too_new(gavl_time_t time, gavl_time_t ovl_time) { if(time < ovl_time) return 1; return 0; } gmerlin-1.2.0~dfsg/lib/textrenderer.c0000644000175000017500000014070411764363410017531 0ustar alessioalessio/***************************************************************** * gmerlin - a general purpose multimedia framework and applications * * Copyright (c) 2001 - 2011 Members of the Gmerlin project * gmerlin-general@lists.sourceforge.net * http://gmerlin.sourceforge.net * * 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 of the License, 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 this program. If not, see . * *****************************************************************/ /* System includes */ #include #include /* Fontconfig */ #include /* Gmerlin */ #include #include #include #include #include #include #include // #undef FT_STROKER_H /* Text alignment */ #define JUSTIFY_CENTER 0 #define JUSTIFY_LEFT 1 #define JUSTIFY_RIGHT 2 #define JUSTIFY_TOP 1 #define JUSTIFY_BOTTOM 2 static const bg_parameter_info_t parameters[] = { { .name = "render_options", .long_name = TRS("Render options"), .type = BG_PARAMETER_SECTION, }, { .name = "color", .long_name = TRS("Text color"), .type = BG_PARAMETER_COLOR_RGBA, .val_default = { .val_color = { 1.0, 1.0, 1.0, 1.0 } }, }, #ifdef FT_STROKER_H { .name = "border_color", .long_name = TRS("Border color"), .type = BG_PARAMETER_COLOR_RGB, .val_default = { .val_color = { 0.0, 0.0, 0.0, 1.0 } }, }, { .name = "border_width", .long_name = TRS("Border width"), .type = BG_PARAMETER_FLOAT, .val_min = { .val_f = 0.0 }, .val_max = { .val_f = 10.0 }, .val_default = { .val_f = 2.0 }, .num_digits = 2, }, #endif { .name = "font", .long_name = TRS("Font"), .type = BG_PARAMETER_FONT, .val_default = { .val_str = "Sans-20" } }, { .name = "justify_h", .long_name = TRS("Horizontal justify"), .type = BG_PARAMETER_STRINGLIST, .val_default = { .val_str = "center" }, .multi_names = (char const *[]){ "center", "left", "right", NULL }, .multi_labels = (char const *[]){ TRS("Center"), TRS("Left"), TRS("Right"), NULL }, }, { .name = "justify_v", .long_name = TRS("Vertical justify"), .type = BG_PARAMETER_STRINGLIST, .val_default = { .val_str = "bottom" }, .multi_names = (char const *[]){ "center", "top", "bottom",NULL }, .multi_labels = (char const *[]){ TRS("Center"), TRS("Top"), TRS("Bottom"), NULL }, }, { .name = "cache_size", .long_name = TRS("Cache size"), .type = BG_PARAMETER_INT, .val_min = { .val_i = 1 }, .val_max = { .val_i = 65535 }, .val_default = { .val_i = 255 }, .help_string = TRS("Specify, how many different characters are cached for faster rendering. For European languages, this never needs to be larger than 255."), }, { .name = "border_left", .long_name = TRS("Left border"), .type = BG_PARAMETER_INT, .val_min = { .val_i = 0 }, .val_max = { .val_i = 65535 }, .val_default = { .val_i = 10 }, .help_string = TRS("Distance from the left text border to the image border"), }, { .name = "border_right", .long_name = TRS("Right border"), .type = BG_PARAMETER_INT, .val_min = { .val_i = 0 }, .val_max = { .val_i = 65535 }, .val_default = { .val_i = 10 }, .help_string = TRS("Distance from the right text border to the image border"), }, { .name = "border_top", .long_name = TRS("Top border"), .type = BG_PARAMETER_INT, .val_min = { .val_i = 0 }, .val_max = { .val_i = 65535 }, .val_default = { .val_i = 10 }, .help_string = TRS("Distance from the top text border to the image border"), }, { .name = "border_bottom", .long_name = "Bottom border", .type = BG_PARAMETER_INT, .val_min = { .val_i = 0 }, .val_max = { .val_i = 65535 }, .val_default = { .val_i = 10 }, .help_string = TRS("Distance from the bottom text border to the image border"), }, { .name = "ignore_linebreaks", .long_name = TRS("Ignore linebreaks"), .type = BG_PARAMETER_CHECKBUTTON, .help_string = TRS("Ignore linebreaks") }, { .name = "default_format", .long_name = TRS("Default format"), .type = BG_PARAMETER_SECTION, }, { .name = "default_width", .long_name = TRS("Default width"), .type = BG_PARAMETER_INT, .val_min = { .val_i = 0 }, .val_max = { .val_i = 65535 }, .val_default = { .val_i = 640 }, }, { .name = "default_height", .long_name = TRS("Default height"), .type = BG_PARAMETER_INT, .val_min = { .val_i = 0 }, .val_max = { .val_i = 65535 }, .val_default = { .val_i = 480 }, }, { .name = "default_csp", .long_name = TRS("Default Colorspace"), .type = BG_PARAMETER_STRINGLIST, .val_default = { .val_str = "yuv" }, .multi_names = (char const *[]){ "yuv", "rgb", NULL }, .multi_labels = (char const *[]){ TRS("YCrCb"), TRS("RGB"), NULL }, }, { .name = "default_framerate", .long_name = TRS("Default Framerate"), .type = BG_PARAMETER_FLOAT, .val_default = { .val_f = 10.0 }, .num_digits = 3, }, { /* End of parameters */ }, }; typedef struct { int xmin, xmax, ymin, ymax; } bbox_t; typedef struct { uint32_t unicode; FT_Glyph glyph; #ifdef FT_STROKER_H FT_Glyph glyph_stroke; #endif int advance_x, advance_y; /* Advance in integer pixels */ bbox_t bbox; } cache_entry_t; struct bg_text_renderer_s { gavl_rectangle_i_t max_bbox; /* Maximum bounding box the text may have */ FT_Library library; FT_Face face; int font_loaded; int font_changed; /* Configuration stuff */ char * font; char * font_file; double font_size; float color[4]; float color_config[4]; float alpha_f; int alpha_i; #ifdef FT_STROKER_H float color_stroke[4]; int color_i[4]; FT_Stroker stroker; float border_width; #endif /* Charset converter */ bg_charset_converter_t * cnv; /* Glyph cache */ cache_entry_t * cache; int cache_size; int cache_alloc; gavl_video_format_t overlay_format; gavl_video_format_t frame_format; gavl_video_format_t last_frame_format; int justify_h; int justify_v; int border_left, border_right, border_top, border_bottom; bbox_t bbox; /* Actual bounding box of the text */ int ignore_linebreaks; int sub_h, sub_v; /* Chroma subsampling of the final destination frame */ void (*render_func)(bg_text_renderer_t * r, cache_entry_t * glyph, gavl_video_frame_t * frame, int * dst_x, int * dst_y); pthread_mutex_t config_mutex; int config_changed; int fixed_width; int default_width, default_height; gavl_pixelformat_t default_csp; float default_framerate; }; static void adjust_bbox(cache_entry_t * glyph, int dst_x, int dst_y, bbox_t * ret) { if(ret->xmin > dst_x + glyph->bbox.xmin) ret->xmin = dst_x + glyph->bbox.xmin; if(ret->ymin > dst_y + glyph->bbox.ymin) ret->ymin = dst_y + glyph->bbox.ymin; if(ret->xmax < dst_x + glyph->bbox.xmax) ret->xmax = dst_x + glyph->bbox.xmax; if(ret->ymax < dst_y + glyph->bbox.ymax) ret->ymax = dst_y + glyph->bbox.ymax; } #define MY_MIN(x, y) (x < y ? x : y) static void render_rgba_32(bg_text_renderer_t * r, cache_entry_t * glyph, gavl_video_frame_t * frame, int * dst_x, int * dst_y) { FT_BitmapGlyph bitmap_glyph; uint8_t * src_ptr, * dst_ptr, * src_ptr_start, * dst_ptr_start; int i, j, i_tmp, jmax; #ifdef FT_STROKER_H int alpha_i; #endif #ifdef FT_STROKER_H bitmap_glyph = (FT_BitmapGlyph)(glyph->glyph_stroke); #else bitmap_glyph = (FT_BitmapGlyph)(glyph->glyph); #endif if(!bitmap_glyph->bitmap.buffer) { *dst_x += glyph->advance_x; *dst_y += glyph->advance_y; return; } src_ptr_start = bitmap_glyph->bitmap.buffer; dst_ptr_start = frame->planes[0] + (*dst_y - bitmap_glyph->top) * frame->strides[0] + (*dst_x + bitmap_glyph->left) * 4; jmax = MY_MIN(bitmap_glyph->bitmap.width, bitmap_glyph->bitmap.pitch); for(i = 0; i < bitmap_glyph->bitmap.rows; i++) { src_ptr = src_ptr_start; dst_ptr = dst_ptr_start; for(j = 0; j < jmax; j++) { i_tmp = ((int)*src_ptr * (int)r->alpha_i) >> 8; if(i_tmp > dst_ptr[3]) dst_ptr[3] = i_tmp; src_ptr++; dst_ptr += 4; } src_ptr_start += bitmap_glyph->bitmap.pitch; dst_ptr_start += frame->strides[0]; } // #if 0 #ifdef FT_STROKER_H bitmap_glyph = (FT_BitmapGlyph)(glyph->glyph); src_ptr_start = bitmap_glyph->bitmap.buffer; dst_ptr_start = frame->planes[0] + (*dst_y - bitmap_glyph->top) * frame->strides[0] + (*dst_x + bitmap_glyph->left) * 4; jmax = MY_MIN(bitmap_glyph->bitmap.width, bitmap_glyph->bitmap.pitch); for(i = 0; i < bitmap_glyph->bitmap.rows; i++) { src_ptr = src_ptr_start; dst_ptr = dst_ptr_start; for(j = 0; j < jmax; j++) { if(*src_ptr) { alpha_i = *src_ptr; dst_ptr[0] = (int)dst_ptr[0] + ((alpha_i * ((int)(r->color_i[0]) - (int)dst_ptr[0])) >> 8); dst_ptr[1] = (int)dst_ptr[1] + ((alpha_i * ((int)(r->color_i[1]) - (int)dst_ptr[1])) >> 8); dst_ptr[2] = (int)dst_ptr[2] + ((alpha_i * ((int)(r->color_i[2]) - (int)dst_ptr[2])) >> 8); } src_ptr++; dst_ptr += 4; } src_ptr_start += bitmap_glyph->bitmap.pitch; dst_ptr_start += frame->strides[0]; } #endif *dst_x += glyph->advance_x; *dst_y += glyph->advance_y; } static void render_graya_16(bg_text_renderer_t * r, cache_entry_t * glyph, gavl_video_frame_t * frame, int * dst_x, int * dst_y) { FT_BitmapGlyph bitmap_glyph; uint8_t * src_ptr, * dst_ptr, * src_ptr_start, * dst_ptr_start; int i, j, i_tmp, jmax; #ifdef FT_STROKER_H int alpha_i; #endif #ifdef FT_STROKER_H bitmap_glyph = (FT_BitmapGlyph)(glyph->glyph_stroke); #else bitmap_glyph = (FT_BitmapGlyph)(glyph->glyph); #endif if(!bitmap_glyph->bitmap.buffer) { *dst_x += glyph->advance_x; *dst_y += glyph->advance_y; return; } src_ptr_start = bitmap_glyph->bitmap.buffer; dst_ptr_start = frame->planes[0] + (*dst_y - bitmap_glyph->top) * frame->strides[0] + (*dst_x + bitmap_glyph->left) * 2; jmax = MY_MIN(bitmap_glyph->bitmap.width, bitmap_glyph->bitmap.pitch); for(i = 0; i < bitmap_glyph->bitmap.rows; i++) { src_ptr = src_ptr_start; dst_ptr = dst_ptr_start; for(j = 0; j < jmax; j++) { i_tmp = ((int)*src_ptr * (int)r->alpha_i) >> 8; if(i_tmp > dst_ptr[1]) dst_ptr[1] = i_tmp; src_ptr++; dst_ptr += 2; } src_ptr_start += bitmap_glyph->bitmap.pitch; dst_ptr_start += frame->strides[0]; } // #if 0 #ifdef FT_STROKER_H bitmap_glyph = (FT_BitmapGlyph)(glyph->glyph); src_ptr_start = bitmap_glyph->bitmap.buffer; dst_ptr_start = frame->planes[0] + (*dst_y - bitmap_glyph->top) * frame->strides[0] + (*dst_x + bitmap_glyph->left) * 2; jmax = MY_MIN(bitmap_glyph->bitmap.width, bitmap_glyph->bitmap.pitch); for(i = 0; i < bitmap_glyph->bitmap.rows; i++) { src_ptr = src_ptr_start; dst_ptr = dst_ptr_start; for(j = 0; j < jmax; j++) { if(*src_ptr) { alpha_i = *src_ptr; dst_ptr[0] = (int)dst_ptr[0] + ((alpha_i * ((int)(r->color_i[0]) - (int)dst_ptr[0])) >> 8); } src_ptr++; dst_ptr += 2; } src_ptr_start += bitmap_glyph->bitmap.pitch; dst_ptr_start += frame->strides[0]; } #endif *dst_x += glyph->advance_x; *dst_y += glyph->advance_y; } static void render_rgba_64(bg_text_renderer_t * r, cache_entry_t * glyph, gavl_video_frame_t * frame, int * dst_x, int * dst_y) { FT_BitmapGlyph bitmap_glyph; uint8_t * src_ptr, * src_ptr_start, * dst_ptr_start; uint16_t * dst_ptr; int i, j, i_tmp, jmax; #ifdef FT_STROKER_H int alpha_i; #endif #ifdef FT_STROKER_H bitmap_glyph = (FT_BitmapGlyph)(glyph->glyph_stroke); #else bitmap_glyph = (FT_BitmapGlyph)(glyph->glyph); #endif if(!bitmap_glyph->bitmap.buffer) { *dst_x += glyph->advance_x; *dst_y += glyph->advance_y; return; } src_ptr_start = bitmap_glyph->bitmap.buffer; dst_ptr_start = frame->planes[0] + (*dst_y - bitmap_glyph->top) * frame->strides[0] + (*dst_x + bitmap_glyph->left) * 8; jmax = MY_MIN(bitmap_glyph->bitmap.width, bitmap_glyph->bitmap.pitch); for(i = 0; i < bitmap_glyph->bitmap.rows; i++) { src_ptr = src_ptr_start; dst_ptr = (uint16_t*)dst_ptr_start; for(j = 0; j < jmax; j++) { i_tmp = ((int)*src_ptr * (int)r->alpha_i) >> 8; if(i_tmp > dst_ptr[3]) dst_ptr[3] = i_tmp; src_ptr++; dst_ptr += 4; } src_ptr_start += bitmap_glyph->bitmap.pitch; dst_ptr_start += frame->strides[0]; } // #if 0 #ifdef FT_STROKER_H /* Render border */ bitmap_glyph = (FT_BitmapGlyph)(glyph->glyph); src_ptr_start = bitmap_glyph->bitmap.buffer; dst_ptr_start = frame->planes[0] + (*dst_y - bitmap_glyph->top) * frame->strides[0] + (*dst_x + bitmap_glyph->left) * 8; jmax = MY_MIN(bitmap_glyph->bitmap.width, bitmap_glyph->bitmap.pitch); for(i = 0; i < bitmap_glyph->bitmap.rows; i++) { src_ptr = src_ptr_start; dst_ptr = (uint16_t*)dst_ptr_start; for(j = 0; j < jmax; j++) { if(*src_ptr) { // alpha_i = ((int)*src_ptr * (int)r->color_i[3]) >> 8; alpha_i = *src_ptr; dst_ptr[0] = (int)dst_ptr[0] + ((alpha_i * ((int64_t)(r->color_i[0]) - (int64_t)dst_ptr[0])) >> 8); dst_ptr[1] = (int)dst_ptr[1] + ((alpha_i * ((int64_t)(r->color_i[1]) - (int64_t)dst_ptr[1])) >> 8); dst_ptr[2] = (int)dst_ptr[2] + ((alpha_i * ((int64_t)(r->color_i[2]) - (int64_t)dst_ptr[2])) >> 8); } src_ptr++; dst_ptr += 4; } src_ptr_start += bitmap_glyph->bitmap.pitch; dst_ptr_start += frame->strides[0]; } #endif *dst_x += glyph->advance_x; *dst_y += glyph->advance_y; } static void render_graya_32(bg_text_renderer_t * r, cache_entry_t * glyph, gavl_video_frame_t * frame, int * dst_x, int * dst_y) { FT_BitmapGlyph bitmap_glyph; uint8_t * src_ptr, * src_ptr_start, * dst_ptr_start; uint16_t * dst_ptr; int i, j, i_tmp, jmax; #ifdef FT_STROKER_H int alpha_i; #endif #ifdef FT_STROKER_H bitmap_glyph = (FT_BitmapGlyph)(glyph->glyph_stroke); #else bitmap_glyph = (FT_BitmapGlyph)(glyph->glyph); #endif if(!bitmap_glyph->bitmap.buffer) { *dst_x += glyph->advance_x; *dst_y += glyph->advance_y; return; } src_ptr_start = bitmap_glyph->bitmap.buffer; dst_ptr_start = frame->planes[0] + (*dst_y - bitmap_glyph->top) * frame->strides[0] + (*dst_x + bitmap_glyph->left) * 4; jmax = MY_MIN(bitmap_glyph->bitmap.width, bitmap_glyph->bitmap.pitch); for(i = 0; i < bitmap_glyph->bitmap.rows; i++) { src_ptr = src_ptr_start; dst_ptr = (uint16_t*)dst_ptr_start; for(j = 0; j < jmax; j++) { i_tmp = ((int)*src_ptr * (int)r->alpha_i) >> 8; if(i_tmp > dst_ptr[1]) dst_ptr[1] = i_tmp; src_ptr++; dst_ptr += 2; } src_ptr_start += bitmap_glyph->bitmap.pitch; dst_ptr_start += frame->strides[0]; } // #if 0 #ifdef FT_STROKER_H /* Render border */ bitmap_glyph = (FT_BitmapGlyph)(glyph->glyph); src_ptr_start = bitmap_glyph->bitmap.buffer; dst_ptr_start = frame->planes[0] + (*dst_y - bitmap_glyph->top) * frame->strides[0] + (*dst_x + bitmap_glyph->left) * 4; jmax = MY_MIN(bitmap_glyph->bitmap.width, bitmap_glyph->bitmap.pitch); for(i = 0; i < bitmap_glyph->bitmap.rows; i++) { src_ptr = src_ptr_start; dst_ptr = (uint16_t*)dst_ptr_start; for(j = 0; j < jmax; j++) { if(*src_ptr) { // alpha_i = ((int)*src_ptr * (int)r->color_i[3]) >> 8; alpha_i = *src_ptr; dst_ptr[0] = (int)dst_ptr[0] + ((alpha_i * ((int64_t)(r->color_i[0]) - (int64_t)dst_ptr[0])) >> 8); } src_ptr++; dst_ptr += 2; } src_ptr_start += bitmap_glyph->bitmap.pitch; dst_ptr_start += frame->strides[0]; } #endif *dst_x += glyph->advance_x; *dst_y += glyph->advance_y; } static void render_rgba_float(bg_text_renderer_t * r, cache_entry_t * glyph, gavl_video_frame_t * frame, int * dst_x, int * dst_y) { FT_BitmapGlyph bitmap_glyph; uint8_t * src_ptr, * src_ptr_start, * dst_ptr_start; float * dst_ptr; int i, j, jmax; float f_tmp; #ifdef FT_STROKER_H float alpha_f; #endif #ifdef FT_STROKER_H bitmap_glyph = (FT_BitmapGlyph)(glyph->glyph_stroke); #else bitmap_glyph = (FT_BitmapGlyph)(glyph->glyph); #endif if(!bitmap_glyph->bitmap.buffer) { *dst_x += glyph->advance_x; *dst_y += glyph->advance_y; return; } src_ptr_start = bitmap_glyph->bitmap.buffer; dst_ptr_start = frame->planes[0] + (*dst_y - bitmap_glyph->top) * frame->strides[0] + (*dst_x + bitmap_glyph->left) * 4 * sizeof(float); jmax = MY_MIN(bitmap_glyph->bitmap.width, bitmap_glyph->bitmap.pitch); for(i = 0; i < bitmap_glyph->bitmap.rows; i++) { src_ptr = src_ptr_start; dst_ptr = (float*)dst_ptr_start; for(j = 0; j < jmax; j++) { f_tmp = ((float)*src_ptr * r->alpha_f) / 255.0; if(f_tmp > dst_ptr[3]) dst_ptr[3] = f_tmp; src_ptr++; dst_ptr += 4; } src_ptr_start += bitmap_glyph->bitmap.pitch; dst_ptr_start += frame->strides[0]; } // #if 0 #ifdef FT_STROKER_H /* Render border */ bitmap_glyph = (FT_BitmapGlyph)(glyph->glyph); src_ptr_start = bitmap_glyph->bitmap.buffer; dst_ptr_start = frame->planes[0] + (*dst_y - bitmap_glyph->top) * frame->strides[0] + (*dst_x + bitmap_glyph->left) * 4 * sizeof(float); jmax = MY_MIN(bitmap_glyph->bitmap.width, bitmap_glyph->bitmap.pitch); for(i = 0; i < bitmap_glyph->bitmap.rows; i++) { src_ptr = src_ptr_start; dst_ptr = (float*)dst_ptr_start; for(j = 0; j < jmax; j++) { if(*src_ptr) { alpha_f = (float)(*src_ptr) / 255.0; dst_ptr[0] = dst_ptr[0] + alpha_f * (r->color[0] - dst_ptr[0]); dst_ptr[1] = dst_ptr[1] + alpha_f * (r->color[1] - dst_ptr[1]); dst_ptr[2] = dst_ptr[2] + alpha_f * (r->color[2] - dst_ptr[2]); } src_ptr++; dst_ptr += 4; } src_ptr_start += bitmap_glyph->bitmap.pitch; dst_ptr_start += frame->strides[0]; } #endif *dst_x += glyph->advance_x; *dst_y += glyph->advance_y; } static void render_graya_float(bg_text_renderer_t * r, cache_entry_t * glyph, gavl_video_frame_t * frame, int * dst_x, int * dst_y) { FT_BitmapGlyph bitmap_glyph; uint8_t * src_ptr, * src_ptr_start, * dst_ptr_start; float * dst_ptr; int i, j, jmax; float f_tmp; #ifdef FT_STROKER_H float alpha_f; #endif #ifdef FT_STROKER_H bitmap_glyph = (FT_BitmapGlyph)(glyph->glyph_stroke); #else bitmap_glyph = (FT_BitmapGlyph)(glyph->glyph); #endif if(!bitmap_glyph->bitmap.buffer) { *dst_x += glyph->advance_x; *dst_y += glyph->advance_y; return; } src_ptr_start = bitmap_glyph->bitmap.buffer; dst_ptr_start = frame->planes[0] + (*dst_y - bitmap_glyph->top) * frame->strides[0] + (*dst_x + bitmap_glyph->left) * 2 * sizeof(float); jmax = MY_MIN(bitmap_glyph->bitmap.width, bitmap_glyph->bitmap.pitch); for(i = 0; i < bitmap_glyph->bitmap.rows; i++) { src_ptr = src_ptr_start; dst_ptr = (float*)dst_ptr_start; for(j = 0; j < jmax; j++) { f_tmp = ((float)*src_ptr * r->alpha_f) / 255.0; if(f_tmp > dst_ptr[1]) dst_ptr[1] = f_tmp; src_ptr++; dst_ptr += 2; } src_ptr_start += bitmap_glyph->bitmap.pitch; dst_ptr_start += frame->strides[0]; } // #if 0 #ifdef FT_STROKER_H /* Render border */ bitmap_glyph = (FT_BitmapGlyph)(glyph->glyph); src_ptr_start = bitmap_glyph->bitmap.buffer; dst_ptr_start = frame->planes[0] + (*dst_y - bitmap_glyph->top) * frame->strides[0] + (*dst_x + bitmap_glyph->left) * 2 * sizeof(float); jmax = MY_MIN(bitmap_glyph->bitmap.width, bitmap_glyph->bitmap.pitch); for(i = 0; i < bitmap_glyph->bitmap.rows; i++) { src_ptr = src_ptr_start; dst_ptr = (float*)dst_ptr_start; for(j = 0; j < jmax; j++) { if(*src_ptr) { alpha_f = (float)(*src_ptr) / 255.0; dst_ptr[0] = dst_ptr[0] + alpha_f * (r->color[0] - dst_ptr[0]); } src_ptr++; dst_ptr += 2; } src_ptr_start += bitmap_glyph->bitmap.pitch; dst_ptr_start += frame->strides[0]; } #endif *dst_x += glyph->advance_x; *dst_y += glyph->advance_y; } static void alloc_glyph_cache(bg_text_renderer_t * r, int size) { int i; if(size > r->cache_alloc) { /* Enlarge */ r->cache_alloc = size; r->cache = realloc(r->cache, r->cache_alloc * sizeof(*(r->cache))); } else if(size < r->cache_alloc) { /* Shrink */ if(size < r->cache_size) { for(i = size; i < r->cache_size; i++) FT_Done_Glyph(r->cache[i].glyph); r->cache_size = size; } r->cache_alloc = size; r->cache = realloc(r->cache, r->cache_alloc * sizeof(*(r->cache))); } else return; } static void clear_glyph_cache(bg_text_renderer_t * r) { int i; for(i = 0; i < r->cache_size; i++) { FT_Done_Glyph(r->cache[i].glyph); #ifdef FT_STROKER_H FT_Done_Glyph(r->cache[i].glyph_stroke); #endif } r->cache_size = 0; } static cache_entry_t * get_glyph(bg_text_renderer_t * r, uint32_t unicode) { int i, index; cache_entry_t * entry; FT_BitmapGlyph bitmap_glyph; for(i = 0; i < r->cache_size; i++) { if(r->cache[i].unicode == unicode) return &r->cache[i]; } /* No glyph found, try to load a new one into the cache */ if(r->cache_size >= r->cache_alloc) { FT_Done_Glyph(r->cache[0].glyph); index = 0; } else { index = r->cache_size; r->cache_size++; } entry = &r->cache[index]; /* Load the glyph */ if(FT_Load_Char(r->face, unicode, FT_LOAD_DEFAULT)) { return NULL; } /* extract glyph image */ if(FT_Get_Glyph(r->face->glyph, &entry->glyph)) { return NULL; } #ifdef FT_STROKER_H /* Stroke glyph */ entry->glyph_stroke = entry->glyph; FT_Glyph_StrokeBorder(&entry->glyph_stroke, r->stroker, 0, 0); // FT_Glyph_StrokeBorder(&entry->glyph_stroke, r->stroker, 1, 0); #endif /* Render glyph */ if(FT_Glyph_To_Bitmap( &entry->glyph, FT_RENDER_MODE_NORMAL, NULL, 1 )) return NULL; entry->advance_x = r->face->glyph->advance.x >> 6; // entry->advance_y = r->face->glyph->metrics.vertAdvance >> 6; entry->advance_y = 0; #ifdef FT_STROKER_H if(FT_Glyph_To_Bitmap( &entry->glyph_stroke, FT_RENDER_MODE_NORMAL, NULL, 1 )) return NULL; #endif /* Get bounding box and advances */ #ifdef FT_STROKER_H bitmap_glyph = (FT_BitmapGlyph)(entry->glyph_stroke); #else bitmap_glyph = (FT_BitmapGlyph)(entry->glyph); #endif // entry->advance_x = entry->glyph->advance.x>>16; // entry->advance_y = entry->glyph->advance.y>>16; if(r->fixed_width) { entry->bbox.xmin = 0; entry->bbox.xmax = entry->advance_x; entry->bbox.ymin = -r->face->size->metrics.ascender >> 6; entry->bbox.ymax = -r->face->size->metrics.descender >> 6; } else { entry->bbox.xmin = bitmap_glyph->left; entry->bbox.xmax = entry->bbox.xmin + bitmap_glyph->bitmap.width; entry->bbox.ymin = -bitmap_glyph->top; entry->bbox.ymax = entry->bbox.ymin + bitmap_glyph->bitmap.rows; } entry->unicode = unicode; return entry; } static void unload_font(bg_text_renderer_t * r) { if(!r->font_loaded) return; #ifdef FT_STROKER_H FT_Stroker_Done(r->stroker); #endif clear_glyph_cache(r); FT_Done_Face(r->face); r->face = NULL; r->font_loaded = 0; } /* fontconfig stuff inspired from MPlayer code */ static int load_font(bg_text_renderer_t * r) { int err; FT_Matrix matrix; FcPattern *fc_pattern = NULL; FcPattern *fc_pattern_1 = NULL; FcChar8 *filename; FcBool scalable; float sar, font_size_scaled; unload_font(r); if(r->font) { /* Get font file */ FcInit(); fc_pattern = FcNameParse((const FcChar8*)r->font); // FcPatternPrint(fc_pattern); FcConfigSubstitute(0, fc_pattern, FcMatchPattern); // FcPatternPrint(fc_pattern); FcDefaultSubstitute(fc_pattern); // FcPatternPrint(fc_pattern); fc_pattern_1 = FcFontMatch(NULL, fc_pattern, 0); // FcPatternPrint(fc_pattern); FcPatternGetBool(fc_pattern_1, FC_SCALABLE, 0, &scalable); if(scalable != FcTrue) { FcPatternDestroy(fc_pattern); FcPatternDestroy(fc_pattern_1); fc_pattern = FcNameParse((const FcChar8*)"Sans-20"); FcConfigSubstitute(0, fc_pattern, FcMatchPattern); FcDefaultSubstitute(fc_pattern); fc_pattern_1 = FcFontMatch(0, fc_pattern, 0); } // s doesn't need to be freed according to fontconfig docs FcPatternGetString(fc_pattern_1, FC_FILE, 0, &filename); FcPatternGetDouble(fc_pattern_1, FC_SIZE, 0, &r->font_size); } else { filename = (FcChar8 *)r->font_file; } /* Load face */ err = FT_New_Face(r->library, (char*)filename, 0, &r->face); if(err) { if(r->font) { FcPatternDestroy(fc_pattern); FcPatternDestroy(fc_pattern_1); } return 0; } r->fixed_width = FT_IS_FIXED_WIDTH(r->face); if(r->font) { FcPatternDestroy(fc_pattern); FcPatternDestroy(fc_pattern_1); } /* Select Unicode */ FT_Select_Charmap(r->face, FT_ENCODING_UNICODE ); #ifdef FT_STROKER_H /* Create stroker */ #if (FREETYPE_MAJOR > 2) || ((FREETYPE_MAJOR == 2) && (FREETYPE_MINOR > 1)) FT_Stroker_New(r->library, &r->stroker); #else FT_Stroker_New(r->face->memory, &r->stroker); #endif FT_Stroker_Set(r->stroker, (int)(r->border_width * 32.0 + 0.5), FT_STROKER_LINECAP_ROUND, FT_STROKER_LINEJOIN_ROUND, 0); #endif sar = (float)(r->frame_format.pixel_width) / (float)(r->frame_format.pixel_height); // sar = 1.0; font_size_scaled = r->font_size * sar * (float)(r->frame_format.image_width) / 640.0; err = FT_Set_Char_Size(r->face, /* handle to face object */ 0, /* char_width in 1/64th of points */ (int)(font_size_scaled*64.0+0.5),/* char_height in 1/64th of points */ 72, /* horizontal device resolution */ 72 ); /* vertical device resolution */ matrix.xx = (FT_Fixed)( (1.0/sar) * 0x10000L ); matrix.yx = 0; matrix.xy = 0; matrix.yy = 0x10000L; // 1.0 FT_Set_Transform(r->face, &matrix, NULL); clear_glyph_cache(r); r->font_loaded = 1; return 1; } bg_text_renderer_t * bg_text_renderer_create() { bg_text_renderer_t * ret = calloc(1, sizeof(*ret)); #ifndef WORDS_BIGENDIAN ret->cnv = bg_charset_converter_create("UTF-8", "UCS-4LE"); #else ret->cnv = bg_charset_converter_create("UTF-8", "UCS-4BE"); #endif pthread_mutex_init(&ret->config_mutex,NULL); /* Initialize freetype */ FT_Init_FreeType(&ret->library); return ret; } void bg_text_renderer_destroy(bg_text_renderer_t * r) { bg_charset_converter_destroy(r->cnv); unload_font(r); if(r->cache) free(r->cache); if(r->font) free(r->font); if(r->font_file) free(r->font_file); FT_Done_FreeType(r->library); pthread_mutex_destroy(&r->config_mutex); free(r); } const bg_parameter_info_t * bg_text_renderer_get_parameters() { return parameters; } void bg_text_renderer_set_parameter(void * data, const char * name, const bg_parameter_value_t * val) { bg_text_renderer_t * r; r = (bg_text_renderer_t *)data; if(!name) return; pthread_mutex_lock(&r->config_mutex); /* General text renderer */ if(!strcmp(name, "font")) { if(!r->font || strcmp(val->val_str, r->font)) { r->font = bg_strdup(r->font, val->val_str); r->font_changed = 1; } } /* OSD */ else if(!strcmp(name, "font_file")) { if(!r->font_file || strcmp(val->val_str, r->font_file)) { r->font_file = bg_strdup(r->font_file, val->val_str); r->font_changed = 1; } } else if(!strcmp(name, "font_size")) { if(r->font_size != val->val_f) { r->font_size = val->val_f; r->font_changed = 1; } } /* */ else if(!strcmp(name, "color")) { r->color_config[0] = val->val_color[0]; r->color_config[1] = val->val_color[1]; r->color_config[2] = val->val_color[2]; r->color_config[3] = 0.0; r->alpha_f = val->val_color[3]; } #ifdef FT_STROKER_H else if(!strcmp(name, "border_color")) { r->color_stroke[0] = val->val_color[0]; r->color_stroke[1] = val->val_color[1]; r->color_stroke[2] = val->val_color[2]; r->color_stroke[3] = 0.0; } else if(!strcmp(name, "border_width")) { r->border_width = val->val_f; } #endif else if(!strcmp(name, "cache_size")) { alloc_glyph_cache(r, val->val_i); } else if(!strcmp(name, "justify_h")) { if(!strcmp(val->val_str, "left")) r->justify_h = JUSTIFY_LEFT; else if(!strcmp(val->val_str, "right")) r->justify_h = JUSTIFY_RIGHT; else if(!strcmp(val->val_str, "center")) r->justify_h = JUSTIFY_CENTER; } else if(!strcmp(name, "justify_v")) { if(!strcmp(val->val_str, "top")) r->justify_v = JUSTIFY_TOP; else if(!strcmp(val->val_str, "bottom")) r->justify_v = JUSTIFY_BOTTOM; else if(!strcmp(val->val_str, "center")) r->justify_v = JUSTIFY_CENTER; } else if(!strcmp(name, "border_left")) { r->border_left = val->val_i; } else if(!strcmp(name, "border_right")) { r->border_right = val->val_i; } else if(!strcmp(name, "border_top")) { r->border_top = val->val_i; } else if(!strcmp(name, "border_bottom")) { r->border_bottom = val->val_i; } else if(!strcmp(name, "ignore_linebreaks")) { r->ignore_linebreaks = val->val_i; } else if(!strcmp(name, "default_width")) { r->default_width = val->val_i; } else if(!strcmp(name, "default_height")) { r->default_height = val->val_i; } else if(!strcmp(name, "default_framerate")) { r->default_framerate = val->val_f; } else if(!strcmp(name, "default_csp")) { if(!strcmp(val->val_str, "rgb")) r->default_csp = GAVL_RGB_24; else r->default_csp = GAVL_YUV_444_P; } r->config_changed = 1; pthread_mutex_unlock(&r->config_mutex); } /* Copied from gavl */ #define r_float_to_y 0.29900 #define g_float_to_y 0.58700 #define b_float_to_y 0.11400 #define r_float_to_u (-0.16874) #define g_float_to_u (-0.33126) #define b_float_to_u 0.50000 #define r_float_to_v 0.50000 #define g_float_to_v (-0.41869) #define b_float_to_v (-0.08131) #define Y_FLOAT_TO_8(val) (int)(val * 219.0+0.5) + 16; #define UV_FLOAT_TO_8(val) (int)(val * 224.0+0.5) + 128; #define GRAY_FLOAT_TO_8(val) (int)(val * 255.0+0.5); #define GRAY_FLOAT_TO_16(val) (int)(val * 65535.0+0.5); #define Y_FLOAT_TO_16(val,dst) dst=(int)(val * 219.0 * (float)0x100+0.5) + 0x1000; #define UV_FLOAT_TO_16(val,dst) dst=(int)(val * 224.0 * (float)0x100+0.5) + 0x8000; #define RGB_FLOAT_TO_Y_8(r, g, b, y) \ y_tmp = r_float_to_y * r + g_float_to_y * g + b_float_to_y * b; \ y = Y_FLOAT_TO_8(y_tmp); #define RGB_FLOAT_TO_YUV_8(r, g, b, y, u, v) \ RGB_FLOAT_TO_Y_8(r, g, b, y) \ u_tmp = r_float_to_u * r + g_float_to_u * g + b_float_to_u * b; \ v_tmp = r_float_to_v * r + g_float_to_v * g + b_float_to_v * b; \ u = UV_FLOAT_TO_8(u_tmp); \ v = UV_FLOAT_TO_8(v_tmp); #define RGB_FLOAT_TO_Y_16(r, g, b, y) \ y_tmp = r_float_to_y * r + g_float_to_y * g + b_float_to_y * b; \ Y_FLOAT_TO_16(y_tmp, y); #define RGB_FLOAT_TO_YUV_16(r, g, b, y, u, v) \ RGB_FLOAT_TO_Y_16(r, g, b, y) \ u_tmp = r_float_to_u * r + g_float_to_u * g + b_float_to_u * b; \ v_tmp = r_float_to_v * r + g_float_to_v * g + b_float_to_v * b; \ UV_FLOAT_TO_16(u_tmp, u); \ UV_FLOAT_TO_16(v_tmp, v); #define RGB_FLOAT_TO_YUV_FLOAT(r, g, b, y, u, v) \ y = r_float_to_y * r + g_float_to_y * g + b_float_to_y * b; \ u = r_float_to_u * r + g_float_to_u * g + b_float_to_u * b; \ v = r_float_to_v * r + g_float_to_v * g + b_float_to_v * b; #define RGB_FLOAT_TO_Y_FLOAT(r, g, b, y, u, v) \ y = r_float_to_y * r + g_float_to_y * g + b_float_to_y * b; #define RGB_FLOAT_TO_GRAY_16(r, g, b, y) \ y_tmp = r_float_to_y * r + g_float_to_y * g + b_float_to_y * b; \ y = GRAY_FLOAT_TO_16(y_tmp); #define RGB_FLOAT_TO_GRAY_8(r, g, b, y) \ y_tmp = r_float_to_y * r + g_float_to_y * g + b_float_to_y * b; \ y = GRAY_FLOAT_TO_8(y_tmp); #define RGB_FLOAT_TO_GRAY_FLOAT(r, g, b, y) \ y = r_float_to_y * r + g_float_to_y * g + b_float_to_y * b; static void init_nolock(bg_text_renderer_t * r) { int bits; #ifdef FT_STROKER_H float y_tmp, u_tmp, v_tmp; #endif if((r->frame_format.image_width != r->last_frame_format.image_width) || (r->frame_format.image_height != r->last_frame_format.image_height) || !r->last_frame_format.pixel_width || !r->frame_format.pixel_height || (r->frame_format.pixel_width * r->last_frame_format.pixel_height != r->frame_format.pixel_height * r->last_frame_format.pixel_width)) r->font_changed = 1; gavl_video_format_copy(&r->last_frame_format, &r->frame_format); /* Load font if necessary */ if(r->font_changed || !r->face) load_font(r); /* Copy formats */ gavl_video_format_copy(&r->overlay_format, &r->frame_format); /* Decide about overlay format */ gavl_pixelformat_chroma_sub(r->frame_format.pixelformat, &r->sub_h, &r->sub_v); if(gavl_pixelformat_is_rgb(r->frame_format.pixelformat)) { bits = 8*gavl_pixelformat_bytes_per_pixel(r->frame_format.pixelformat); if(bits <= 32) { r->overlay_format.pixelformat = GAVL_RGBA_32; r->alpha_i = (int)(r->alpha_f*255.0+0.5); #ifdef FT_STROKER_H r->color_i[0] = (int)(r->color_config[0]*255.0+0.5); r->color_i[1] = (int)(r->color_config[1]*255.0+0.5); r->color_i[2] = (int)(r->color_config[2]*255.0+0.5); r->color_i[3] = (int)(r->color_config[3]*255.0+0.5); #endif r->render_func = render_rgba_32; } else if(bits <= 64) { r->overlay_format.pixelformat = GAVL_RGBA_64; r->alpha_i = (int)(r->alpha_f*65535.0+0.5); #ifdef FT_STROKER_H r->color_i[0] = (int)(r->color_config[0]*65535.0+0.5); r->color_i[1] = (int)(r->color_config[1]*65535.0+0.5); r->color_i[2] = (int)(r->color_config[2]*65535.0+0.5); r->color_i[3] = (int)(r->color_config[3]*65535.0+0.5); #endif r->render_func = render_rgba_64; } else { r->overlay_format.pixelformat = GAVL_RGBA_FLOAT; r->render_func = render_rgba_float; r->color[0] = r->color_config[0]; r->color[1] = r->color_config[1]; r->color[2] = r->color_config[2]; } } else if(gavl_pixelformat_is_yuv(r->frame_format.pixelformat)) { if(gavl_pixelformat_is_planar(r->frame_format.pixelformat)) { switch(gavl_pixelformat_bytes_per_component(r->frame_format.pixelformat)) { case 1: r->overlay_format.pixelformat = GAVL_YUVA_32; r->alpha_i = (int)(r->alpha_f*255.0+0.5); #ifdef FT_STROKER_H RGB_FLOAT_TO_YUV_8(r->color_config[0], r->color_config[1], r->color_config[2], r->color_i[0], r->color_i[1], r->color_i[2]); r->color_i[3] = (int)(r->color[3]*255.0+0.5); #endif r->render_func = render_rgba_32; break; case 2: r->overlay_format.pixelformat = GAVL_YUVA_64; r->alpha_i = (int)(r->alpha_f*65535.0+0.5); #ifdef FT_STROKER_H RGB_FLOAT_TO_YUV_16(r->color_config[0], r->color_config[1], r->color_config[2], r->color_i[0], r->color_i[1], r->color_i[2]); r->color_i[3] = (int)(r->color[3]*65535.0+0.5); #endif r->render_func = render_rgba_64; break; } } else /* Packed */ { switch(gavl_pixelformat_bytes_per_pixel(r->frame_format.pixelformat)) { case 2: /* YUY2, UYVY */ case 4: /* YUVA32 */ r->overlay_format.pixelformat = GAVL_YUVA_32; r->alpha_i = (int)(r->alpha_f*255.0+0.5); #ifdef FT_STROKER_H RGB_FLOAT_TO_YUV_8(r->color_config[0], r->color_config[1], r->color_config[2], r->color_i[0], r->color_i[1], r->color_i[2]); r->color_i[3] = (int)(r->color[3]*255.0+0.5); #endif r->render_func = render_rgba_32; break; case 8: /* YUVA 64 */ r->overlay_format.pixelformat = GAVL_YUVA_64; r->alpha_i = (int)(r->alpha_f*65535.0+0.5); #ifdef FT_STROKER_H RGB_FLOAT_TO_YUV_16(r->color_config[0], r->color_config[1], r->color_config[2], r->color_i[0], r->color_i[1], r->color_i[2]); r->color_i[3] = (int)(r->color[3]*65535.0+0.5); #endif r->render_func = render_rgba_64; break; case 3*sizeof(float): /* YUV float */ case 4*sizeof(float): /* YUVA float */ r->overlay_format.pixelformat = GAVL_YUVA_FLOAT; #ifdef FT_STROKER_H RGB_FLOAT_TO_YUV_FLOAT(r->color_config[0], r->color_config[1], r->color_config[2], r->color[0], r->color[1], r->color[2]); #endif r->render_func = render_rgba_float; break; } } } else // Gray { switch(r->frame_format.pixelformat) { case GAVL_GRAY_8: case GAVL_GRAYA_16: r->overlay_format.pixelformat = GAVL_GRAYA_16; r->alpha_i = (int)(r->alpha_f*255.0+0.5); #ifdef FT_STROKER_H RGB_FLOAT_TO_GRAY_8(r->color_config[0], r->color_config[1], r->color_config[2], r->color_i[0]); #endif r->render_func = render_graya_16; break; case GAVL_GRAY_16: case GAVL_GRAYA_32: r->overlay_format.pixelformat = GAVL_GRAYA_32; r->alpha_i = (int)(r->alpha_f*65535.0+0.5); #ifdef FT_STROKER_H RGB_FLOAT_TO_GRAY_16(r->color_config[0], r->color_config[1], r->color_config[2], r->color_i[0]); #endif r->render_func = render_graya_32; break; case GAVL_GRAY_FLOAT: case GAVL_GRAYA_FLOAT: r->overlay_format.pixelformat = GAVL_GRAYA_FLOAT; r->render_func = render_graya_float; RGB_FLOAT_TO_GRAY_FLOAT(r->color_config[0], r->color_config[1], r->color_config[2], r->color[0]); break; default: break; } } /* */ gavl_rectangle_i_set_all(&r->max_bbox, &r->overlay_format); gavl_rectangle_i_crop_left(&r->max_bbox, r->border_left); gavl_rectangle_i_crop_right(&r->max_bbox, r->border_right); gavl_rectangle_i_crop_top(&r->max_bbox, r->border_top); gavl_rectangle_i_crop_bottom(&r->max_bbox, r->border_bottom); } void bg_text_renderer_init(bg_text_renderer_t * r, const gavl_video_format_t * frame_format, gavl_video_format_t * overlay_format) { int timescale, frame_duration; pthread_mutex_lock(&r->config_mutex); timescale = overlay_format->timescale; frame_duration = overlay_format->frame_duration; if(frame_format) { gavl_video_format_copy(&r->frame_format, frame_format); } else { memset(&r->frame_format, 0, sizeof(r->frame_format)); r->frame_format.image_width = r->default_width; r->frame_format.image_height = r->default_height; r->frame_format.frame_width = r->default_width; r->frame_format.frame_height = r->default_height; r->frame_format.pixel_width = 1; r->frame_format.pixel_height = 1; r->frame_format.pixelformat = r->default_csp; r->frame_format.timescale = (int)(r->default_framerate * 1000 + 0.5); r->frame_format.frame_duration = 1000; } init_nolock(r); r->overlay_format.timescale = timescale; r->overlay_format.frame_duration = frame_duration; gavl_video_format_copy(overlay_format, &r->overlay_format); r->config_changed = 0; pthread_mutex_unlock(&r->config_mutex); } void bg_text_renderer_get_frame_format(bg_text_renderer_t * r, gavl_video_format_t * frame_format) { gavl_video_format_copy(frame_format, &r->frame_format); } static void flush_line(bg_text_renderer_t * r, gavl_video_frame_t * f, cache_entry_t ** glyphs, int len, int * line_y) { int line_x, j; int line_width; if(!len) return; line_width = 0; line_width = -glyphs[0]->bbox.xmin; /* Compute the length of the line */ for(j = 0; j < len-1; j++) { line_width += glyphs[j]->advance_x; /* Adjust the y-position, if the glyph extends beyond the top border of the frame. This should happen only for the first line */ if(*line_y < -glyphs[j]->bbox.ymin) *line_y = -glyphs[j]->bbox.ymin; } line_width += glyphs[len - 1]->bbox.xmax; if(*line_y < -glyphs[len - 1]->bbox.ymin) *line_y = -glyphs[len - 1]->bbox.ymin; switch(r->justify_h) { case JUSTIFY_CENTER: line_x = (r->max_bbox.w - line_width) >> 1; break; case JUSTIFY_LEFT: line_x = 0; break; case JUSTIFY_RIGHT: line_x = r->max_bbox.w - line_width; break; } line_x -= glyphs[0]->bbox.xmin; for(j = 0; j < len; j++) { adjust_bbox(glyphs[j], line_x, *line_y, &r->bbox); r->render_func(r, glyphs[j], f, &line_x, line_y); } } void bg_text_renderer_render(bg_text_renderer_t * r, const char * string, gavl_overlay_t * ovl) { cache_entry_t ** glyphs = NULL; uint32_t * string_unicode = NULL; int len, i; int pos_x, pos_y; int line_start, line_end; int line_width, line_end_y; int line_offset; int break_word; /* Linebreak within a (long) word */ pthread_mutex_lock(&r->config_mutex); if(r->config_changed) init_nolock(r); r->bbox.xmin = r->overlay_format.image_width; r->bbox.ymin = r->overlay_format.image_height; r->bbox.xmax = 0; r->bbox.ymax = 0; #ifdef FT_STROKER_H gavl_video_frame_fill(ovl->frame, &r->overlay_format, r->color_stroke); #else gavl_video_frame_fill(ovl->frame, &r->overlay_format, r->color); #endif /* Convert string */ string_unicode = (uint32_t*)bg_convert_string(r->cnv, string, -1, &len); len /= 4; line_offset = r->face->size->metrics.height >> 6; glyphs = malloc(len * sizeof(*glyphs)); if(r->ignore_linebreaks) { for(i = 0; i < len; i++) { if(string_unicode[i] == '\n') string_unicode[i] = ' '; } } for(i = 0; i < len; i++) { glyphs[i] = get_glyph(r, string_unicode[i]); if(!glyphs[i]) glyphs[i] = get_glyph(r, '?'); } line_start = 0; line_end = -1; break_word = 0; pos_x = 0; pos_y = r->face->size->metrics.ascender >> 6; line_width = 0; for(i = 0; i < len; i++) { if((string_unicode[i] == ' ') || (string_unicode[i] == '\n') || (i == len)) { line_end = i; line_width = pos_x; line_end_y = pos_y; break_word = 0; } /* Linebreak */ if((pos_x + (glyphs[i]->advance_x) > r->max_bbox.w) || (string_unicode[i] == '\n')) { if(line_end < 0) { line_width = pos_x; line_end_y = pos_y; line_end = i; break_word = 1; } /* Render the line */ flush_line(r, ovl->frame, &glyphs[line_start], line_end - line_start, &pos_y); pos_x -= line_width; pos_y += line_offset; if((pos_y + (r->face->size->metrics.descender >> 6)) > r->max_bbox.h) break; line_start = line_end; if(!break_word) line_start++; line_end = -1; } pos_x += glyphs[i]->advance_x; } if(len - line_start) { flush_line(r, ovl->frame, &glyphs[line_start], len - line_start, &pos_y); } ovl->ovl_rect.x = r->bbox.xmin; ovl->ovl_rect.y = r->bbox.ymin; ovl->ovl_rect.w = r->bbox.xmax - r->bbox.xmin; ovl->ovl_rect.h = r->bbox.ymax - r->bbox.ymin; /* Align to subsampling */ ovl->ovl_rect.w += r->sub_h - (ovl->ovl_rect.w % r->sub_h); ovl->ovl_rect.h += r->sub_v - (ovl->ovl_rect.h % r->sub_v); switch(r->justify_h) { case JUSTIFY_LEFT: case JUSTIFY_CENTER: ovl->dst_x = ovl->ovl_rect.x + r->border_left; if(ovl->dst_x % r->sub_h) ovl->dst_x += r->sub_h - (ovl->dst_x % r->sub_h); break; case JUSTIFY_RIGHT: ovl->dst_x = r->overlay_format.image_width - r->border_right - ovl->ovl_rect.w; ovl->dst_x -= (ovl->dst_x % r->sub_h); break; } switch(r->justify_v) { case JUSTIFY_TOP: ovl->dst_y = r->border_top; ovl->dst_y += r->sub_v - (ovl->dst_y % r->sub_v); break; case JUSTIFY_CENTER: ovl->dst_y = r->border_top + ((r->overlay_format.image_height - ovl->ovl_rect.h)>>1); if(ovl->dst_y % r->sub_v) ovl->dst_y += r->sub_v - (ovl->dst_y % r->sub_v); break; case JUSTIFY_BOTTOM: ovl->dst_y = r->overlay_format.image_height - r->border_bottom - ovl->ovl_rect.h; ovl->dst_y -= (ovl->dst_y % r->sub_v); break; } if(glyphs) free(glyphs); if(string_unicode) free(string_unicode); pthread_mutex_unlock(&r->config_mutex); } gmerlin-1.2.0~dfsg/lib/accelerator.c0000644000175000017500000000761311764363410017303 0ustar alessioalessio/***************************************************************** * gmerlin - a general purpose multimedia framework and applications * * Copyright (c) 2001 - 2011 Members of the Gmerlin project * gmerlin-general@lists.sourceforge.net * http://gmerlin.sourceforge.net * * 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 of the License, 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 this program. If not, see . * *****************************************************************/ #include #include #include #include #include struct bg_accelerator_map_s { int num; int num_alloc; bg_accelerator_t * accels; }; void bg_accelerator_map_append(bg_accelerator_map_t * m, int key, int mask, int id) { if(m->num_alloc <= m->num + 2) { m->num_alloc = m->num + 100; m->accels = realloc(m->accels, m->num_alloc * sizeof(*m->accels)); } m->accels[m->num].key = key; m->accels[m->num].mask = mask; m->accels[m->num].id = id; m->num++; m->accels[m->num].key = BG_KEY_NONE; } /* Array is terminated with BG_KEY_NONE */ void bg_accelerator_map_append_array(bg_accelerator_map_t * m, const bg_accelerator_t * tail) { int num_append = 0; while(tail[num_append].key != BG_KEY_NONE) num_append++; if(m->num_alloc <= m->num + num_append + 1) { m->num_alloc = m->num + num_append + 100; m->accels = realloc(m->accels, m->num_alloc * sizeof(*m->accels)); } memcpy(m->accels + m->num, tail, num_append * sizeof(*m->accels)); m->num += num_append; m->accels[m->num].key = BG_KEY_NONE; } const bg_accelerator_t * bg_accelerator_map_get_accels(const bg_accelerator_map_t * m) { return m->accels; } void bg_accelerator_map_destroy(bg_accelerator_map_t * m) { if(m->accels) free(m->accels); free(m); } bg_accelerator_map_t * bg_accelerator_map_create() { bg_accelerator_map_t * ret; ret = calloc(1, sizeof(*ret)); ret->num_alloc = 1; ret->accels = calloc(ret->num_alloc, sizeof(*ret->accels)); ret->accels[0].key = BG_KEY_NONE; return ret; } static int find_by_id(const bg_accelerator_map_t * m, int id) { int i; for(i = 0; i < m->num; i++) { if(m->accels[i].id == id) return i; } return -1; } static int find_by_key(const bg_accelerator_map_t * m, int key, int mask) { int i; for(i = 0; i < m->num; i++) { if((m->accels[i].key == key) && (m->accels[i].mask == mask)) return i; } return -1; } void bg_accelerator_map_remove(bg_accelerator_map_t * m, int id) { int index; index = find_by_id(m, id); if(index < 0) return; if(index < m->num - 1) { memmove(m->accels + index, m->accels + index + 1, sizeof(*m->accels) * (m->num - 1 - index)); } m->num--; } int bg_accelerator_map_has_accel(const bg_accelerator_map_t * m, int key, int mask, int * id) { int result; result = find_by_key(m, key, mask); if(result >= 0) { if( id) *id = m->accels[result].id; return 1; } return 0; } int bg_accelerator_map_has_accel_with_id(const bg_accelerator_map_t * m, int id) { if(find_by_id(m, id) < 0) return 0; return 1; } void bg_accelerator_map_clear(bg_accelerator_map_t * m) { m->num = 0; } gmerlin-1.2.0~dfsg/lib/bgfrei0r.c0000644000175000017500000003376411764363410016525 0ustar alessioalessio/***************************************************************** * gmerlin - a general purpose multimedia framework and applications * * Copyright (c) 2001 - 2011 Members of the Gmerlin project * gmerlin-general@lists.sourceforge.net * http://gmerlin.sourceforge.net * * 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 of the License, 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 this program. If not, see . * *****************************************************************/ /* Make gmerlin video filters from frei0r plugins. * See http://www.piksel.org/frei0r */ #include #include #include #include #include #include #include #include #include #define LOG_DOMAIN "frei0r" static bg_parameter_info_t * create_parameters(void * dll_handle, f0r_plugin_info_t * plugin_info) { int i; f0r_instance_t (*construct) (unsigned int width, unsigned int height); f0r_instance_t (*destruct) (f0r_instance_t); f0r_instance_t instance; int (*init)(); void (*deinit)(); void (*get_param_info) (f0r_param_info_t *info, int param_index); void (*get_param_value) (f0r_instance_t instance, f0r_param_t param, int param_index); bg_parameter_info_t * ret = NULL; f0r_param_info_t param_info; if(!plugin_info->num_params) return ret; get_param_info = dlsym(dll_handle, "f0r_get_param_info"); if(!get_param_info) { bg_log(BG_LOG_ERROR, LOG_DOMAIN, "Cannot load frei0r plugin: %s", dlerror()); return NULL; } construct = dlsym(dll_handle, "f0r_construct"); if(!construct) { bg_log(BG_LOG_ERROR, LOG_DOMAIN, "Cannot load frei0r plugin: %s", dlerror()); return NULL; } destruct = dlsym(dll_handle, "f0r_destruct"); if(!destruct) { bg_log(BG_LOG_ERROR, LOG_DOMAIN, "Cannot load frei0r plugin: %s", dlerror()); return NULL; } get_param_value = dlsym(dll_handle, "f0r_get_param_value"); if(!get_param_value) { bg_log(BG_LOG_ERROR, LOG_DOMAIN, "Cannot load frei0r plugin: %s", dlerror()); return NULL; } init = dlsym(dll_handle, "f0r_init"); deinit = dlsym(dll_handle, "f0r_deinit"); if(init) init(); /* Need to create an instance so we get the default values */ instance = construct(32, 32); ret = calloc(plugin_info->num_params+1, sizeof(*ret)); for(i = 0; i < plugin_info->num_params; i++) { memset(¶m_info, 0, sizeof(param_info)); get_param_info(¶m_info, i); ret[i].name = bg_strdup(NULL, param_info.name); ret[i].long_name = bg_strdup(NULL, param_info.name); ret[i].flags = BG_PARAMETER_SYNC; ret[i].help_string = bg_strdup(NULL, param_info.explanation); switch(param_info.type) { case F0R_PARAM_BOOL: { double val; get_param_value(instance, &val, i); if(val > 0.5) ret[i].val_default.val_i = 1; ret[i].type = BG_PARAMETER_CHECKBUTTON; break; } case F0R_PARAM_DOUBLE: { double val; get_param_value(instance, &val, i); ret[i].val_default.val_f = val; ret[i].type = BG_PARAMETER_SLIDER_FLOAT; ret[i].num_digits = 4; ret[i].val_min.val_f = 0.0; ret[i].val_max.val_f = 1.0; break; } case F0R_PARAM_COLOR: { f0r_param_color_t val; get_param_value(instance, &val, i); ret[i].val_default.val_color[0] = val.r; ret[i].val_default.val_color[1] = val.g; ret[i].val_default.val_color[2] = val.b; ret[i].type = BG_PARAMETER_COLOR_RGB; break; } case F0R_PARAM_POSITION: { f0r_param_position_t val; get_param_value(instance, &val, i); ret[i].val_default.val_pos[0] = val.x; ret[i].val_default.val_pos[1] = val.y; ret[i].type = BG_PARAMETER_POSITION; ret[i].num_digits = 4; break; } case F0R_PARAM_STRING: ret[i].type = BG_PARAMETER_STRING; break; } } destruct(instance); if(deinit) deinit(); return ret; } bg_plugin_info_t * bg_frei0r_get_info(void * dll_handle, const char * filename) { bg_plugin_info_t * ret = NULL; f0r_plugin_info_t plugin_info; void (*get_plugin_info)(f0r_plugin_info_t *info); get_plugin_info = dlsym(dll_handle, "f0r_get_plugin_info"); if(!get_plugin_info) { bg_log(BG_LOG_ERROR, LOG_DOMAIN, "Cannot load frei0r plugin: %s", dlerror()); return ret; } memset(&plugin_info, 0, sizeof(plugin_info)); get_plugin_info(&plugin_info); ret = calloc(1, sizeof(*ret)); ret->name = bg_sprintf("bg_f0r_%s", plugin_info.name); ret->long_name = bg_sprintf("frei0r %s", plugin_info.name); ret->type = BG_PLUGIN_FILTER_VIDEO; ret->api = BG_PLUGIN_API_FREI0R; ret->flags = BG_PLUGIN_FILTER_1; ret->module_filename = bg_strdup(NULL, filename); // fprintf(stderr, "Loading %s\n", ret->name); /* Check if we can use this at all */ if(plugin_info.plugin_type != F0R_PLUGIN_TYPE_FILTER) { ret->flags |= BG_PLUGIN_UNSUPPORTED; return ret; } ret->description = bg_sprintf(TRS("Author: %s\n%s"), plugin_info.author, plugin_info.explanation); ret->parameters = create_parameters(dll_handle, &plugin_info); return ret; } /* Plugin function wrappers */ typedef struct { /* Function pointers */ f0r_instance_t (*construct) (unsigned int width, unsigned int height); void (*destruct) (f0r_instance_t instance); void (*set_param_value) (f0r_instance_t instance, f0r_param_t param, int param_index); void (*update) (f0r_instance_t instance, double time, const uint32_t *inframe, uint32_t *outframe); f0r_instance_t instance; f0r_plugin_info_t plugin_info; /* Parameter values are cached here */ bg_cfg_section_t * section; bg_read_video_func_t read_func; void * read_data; int read_stream; gavl_video_frame_t * in_frame; gavl_video_frame_t * out_frame; gavl_video_format_t format; const bg_parameter_info_t * parameters; int do_swap; } frei0r_t; static void set_parameter_instance(void * data, const char * name, const bg_parameter_value_t * v) { int index; frei0r_t * vp; const bg_parameter_info_t * info; if(!name) return; vp = (frei0r_t *)data; info = bg_parameter_find(vp->parameters, name); if(info) { index = info - vp->parameters; switch(info->type) { case BG_PARAMETER_CHECKBUTTON: { double val = v->val_i ? 1.0 : 0.0; vp->set_param_value(vp->instance, &val, index); break; } case BG_PARAMETER_SLIDER_FLOAT: { double val = v->val_f; vp->set_param_value(vp->instance, &val, index); break; } case BG_PARAMETER_COLOR_RGB: { f0r_param_color_t val; val.r = v->val_color[0]; val.g = v->val_color[1]; val.b = v->val_color[2]; vp->set_param_value(vp->instance, &val, index); break; } case BG_PARAMETER_POSITION: { f0r_param_position_t val; val.x = v->val_pos[0]; val.y = v->val_pos[1]; vp->set_param_value(vp->instance, &val, index); break; } default: break; } } } static void set_parameter_frei0r(void * data, const char * name, const bg_parameter_value_t * val) { frei0r_t * vp; const bg_parameter_info_t * info; vp = (frei0r_t *)data; if(!name) return; if(vp->instance) set_parameter_instance(data, name, val); /* * Save the value into the section, so we can pass this to the next * instance (gmerlin filters survive format changes, f0r filters don't) */ if(!vp->section) vp->section = bg_cfg_section_create_from_parameters("bla", vp->parameters); info = bg_parameter_find(vp->parameters, name); if(info) bg_cfg_section_set_parameter(vp->section, info, val); } static void connect_input_port_frei0r(void *priv, bg_read_video_func_t func, void *data, int stream, int port) { frei0r_t * vp; vp = (frei0r_t *)priv; if(!port) { vp->read_func = func; vp->read_data = data; vp->read_stream = stream; } } static void get_output_format_frei0r(void * priv, gavl_video_format_t * format) { frei0r_t * vp; vp = (frei0r_t *)priv; gavl_video_format_copy(format, &vp->format); } static const gavl_pixelformat_t packed32_formats[] = { GAVL_RGB_32, GAVL_BGR_32, GAVL_RGBA_32, GAVL_YUVA_32, GAVL_PIXELFORMAT_NONE, }; static void set_input_format_frei0r(void *priv, gavl_video_format_t *format, int port) { /* Set input format */ frei0r_t * vp; vp = (frei0r_t *)priv; switch(vp->plugin_info.color_model) { case F0R_COLOR_MODEL_BGRA8888: vp->do_swap = 1; /* Fall through */ case F0R_COLOR_MODEL_RGBA8888: format->pixelformat = GAVL_RGBA_32; break; case F0R_COLOR_MODEL_PACKED32: format->pixelformat = gavl_pixelformat_get_best(format->pixelformat, packed32_formats, NULL); break; } /* Frei0r demands image sizes to be a multiple of 8. We fake this by making a larger frame */ format->frame_width = ((format->image_width+7)/8)*8; format->frame_height = ((format->image_height+7)/8)*8; gavl_video_format_copy(&vp->format, format); /* Fire up the plugin */ vp->instance = vp->construct(vp->format.frame_width, vp->format.frame_height); /* Now, we can set parameters */ if(vp->section) { bg_cfg_section_apply(vp->section, vp->parameters, set_parameter_instance, vp); } vp->in_frame = gavl_video_frame_create_nopad(&vp->format); if(vp->out_frame) { gavl_video_frame_destroy(vp->out_frame); vp->out_frame = NULL; } } static int read_video_frei0r(void *priv, gavl_video_frame_t *frame, int stream) { frei0r_t * vp; double time; vp = (frei0r_t *)priv; if(!vp->read_func(vp->read_data, vp->in_frame, vp->read_stream)) return 0; time = gavl_time_to_seconds(gavl_time_unscale(vp->format.timescale, vp->in_frame->timestamp)); if(frame->strides[0] == vp->format.frame_width * 4) vp->update(vp->instance, time, (const uint32_t*)vp->in_frame->planes[0], (uint32_t*)frame->planes[0]); else { if(!vp->out_frame) vp->out_frame = gavl_video_frame_create_nopad(&vp->format); vp->update(vp->instance, time, (const uint32_t*)vp->in_frame->planes[0], (uint32_t*)vp->out_frame->planes[0]); gavl_video_frame_copy(&vp->format, frame, vp->out_frame); } frame->timestamp = vp->in_frame->timestamp; frame->duration = vp->in_frame->duration; return 1; } static const bg_parameter_info_t * get_parameters_frei0r(void * priv) { frei0r_t * vp; vp = (frei0r_t *)priv; return vp->parameters; } int bg_frei0r_load(bg_plugin_handle_t * ret, const bg_plugin_info_t * info) { bg_fv_plugin_t * vf; frei0r_t * priv; void (*get_plugin_info)(f0r_plugin_info_t *info); vf = calloc(1, sizeof(*vf)); ret->plugin_nc = (bg_plugin_common_t*)vf; ret->plugin = ret->plugin_nc; vf->set_input_format = set_input_format_frei0r; vf->connect_input_port = connect_input_port_frei0r; vf->get_output_format = get_output_format_frei0r; vf->read_video = read_video_frei0r; if(info->parameters) { ret->plugin_nc->get_parameters = get_parameters_frei0r; ret->plugin_nc->set_parameter = set_parameter_frei0r; } get_plugin_info = dlsym(ret->dll_handle, "f0r_get_plugin_info"); if(!get_plugin_info) { bg_log(BG_LOG_ERROR, LOG_DOMAIN, "Cannot load frei0r plugin: %s", dlerror()); return 0; } priv = calloc(1, sizeof(*priv)); ret->priv = priv; get_plugin_info(&priv->plugin_info); priv->parameters = info->parameters; /* Get function pointers */ priv->construct = dlsym(ret->dll_handle, "f0r_construct"); if(!priv->construct) { bg_log(BG_LOG_ERROR, LOG_DOMAIN, "Cannot load frei0r plugin: %s", dlerror()); return 0; } priv->destruct = dlsym(ret->dll_handle, "f0r_destruct"); if(!priv->destruct) { bg_log(BG_LOG_ERROR, LOG_DOMAIN, "Cannot load frei0r plugin: %s", dlerror()); return 0; } priv->set_param_value = dlsym(ret->dll_handle, "f0r_set_param_value"); if(!priv->set_param_value) { bg_log(BG_LOG_ERROR, LOG_DOMAIN, "Cannot load frei0r plugin: %s", dlerror()); return 0; } priv->update = dlsym(ret->dll_handle, "f0r_update"); if(!priv->update) { bg_log(BG_LOG_ERROR, LOG_DOMAIN, "Cannot load frei0r plugin: %s", dlerror()); return 0; } return 1; } void bg_frei0r_unload(bg_plugin_handle_t * h) { frei0r_t * vp; vp = (frei0r_t *)h->priv; if(vp->instance) vp->destruct(vp->instance); if(vp->in_frame) gavl_video_frame_destroy(vp->in_frame); if(vp->out_frame) gavl_video_frame_destroy(vp->out_frame); free(vp); } gmerlin-1.2.0~dfsg/lib/encoder.c0000644000175000017500000007736011764363410016444 0ustar alessioalessio/***************************************************************** * gmerlin - a general purpose multimedia framework and applications * * Copyright (c) 2001 - 2011 Members of the Gmerlin project * gmerlin-general@lists.sourceforge.net * http://gmerlin.sourceforge.net * * 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 of the License, 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 this program. If not, see . * *****************************************************************/ #include #include #include #include #include #include #define LOG_DOMAIN "encoder" /* Encoder flags */ typedef struct { int in_index; int out_index; bg_encoder_plugin_t * plugin; void * priv; bg_plugin_handle_t * h; gavl_audio_format_t format; bg_cfg_section_t * section; const bg_parameter_info_t * parameters; const gavl_metadata_t * m; const gavl_compression_info_t * ci; } audio_stream_t; typedef struct { int in_index; int out_index; bg_encoder_plugin_t * plugin; void * priv; bg_plugin_handle_t * h; gavl_video_format_t format; bg_cfg_section_t * section; const bg_parameter_info_t * parameters; int pass; int total_passes; char * stats_file; const gavl_metadata_t * m; // int64_t last_timestamp; const gavl_compression_info_t * ci; } video_stream_t; typedef struct { int in_index; int out_index; bg_encoder_plugin_t * plugin; void * priv; bg_plugin_handle_t * h; int timescale; bg_cfg_section_t * section; const bg_parameter_info_t * parameters; const gavl_metadata_t * m; } subtitle_text_stream_t; typedef struct { int in_index; int out_index; bg_encoder_plugin_t * plugin; void * priv; bg_plugin_handle_t * h; gavl_video_format_t format; bg_cfg_section_t * section; const bg_parameter_info_t * parameters; const gavl_metadata_t * m; } subtitle_overlay_stream_t; typedef struct { const bg_plugin_info_t * info; bg_cfg_section_t * section; } plugin_config_t; typedef struct { bg_cfg_section_t * section; } stream_config_t; struct bg_encoder_s { plugin_config_t audio_plugin; plugin_config_t video_plugin; plugin_config_t subtitle_text_plugin; plugin_config_t subtitle_overlay_plugin; stream_config_t audio_stream; stream_config_t video_stream; stream_config_t subtitle_text_stream; stream_config_t subtitle_overlay_stream; int num_audio_streams; int num_video_streams; int num_subtitle_text_streams; int num_subtitle_overlay_streams; int total_streams; audio_stream_t * audio_streams; video_stream_t * video_streams; subtitle_text_stream_t * subtitle_text_streams; subtitle_overlay_stream_t * subtitle_overlay_streams; int num_plugins; bg_plugin_handle_t ** plugins; int separate; bg_plugin_registry_t * plugin_reg; /* Config stuff */ bg_cfg_section_t * es; bg_transcoder_track_t * tt; int stream_mask; bg_encoder_callbacks_t * cb_ext; bg_encoder_callbacks_t cb_int; char * filename_base; const gavl_metadata_t * metadata; const bg_chapter_list_t * chapter_list; }; static int cb_create_output_file(void * data, const char * filename) { int ret; bg_encoder_t * e = data; if(e->cb_ext && e->cb_ext->create_output_file) ret = e->cb_ext->create_output_file(e->cb_ext->data, filename); else ret = 1; if(ret) bg_log(BG_LOG_INFO, LOG_DOMAIN, "Created output file %s", filename); return ret; } static int cb_create_temp_file(void * data, const char * filename) { int ret; bg_encoder_t * e = data; if(e->cb_ext && e->cb_ext->create_temp_file) ret = e->cb_ext->create_temp_file(e->cb_ext->data, filename); else ret = 1; if(ret) bg_log(BG_LOG_INFO, LOG_DOMAIN, "Created temp file %s\n", filename); return ret; } static void init_plugin_from_section(bg_encoder_t * e, plugin_config_t * ret, bg_stream_type_t type) { const char * name; name = bg_encoder_section_get_plugin(e->plugin_reg, e->es, type, e->stream_mask); if(name) { ret->info = bg_plugin_find_by_name(e->plugin_reg, name); bg_encoder_section_get_plugin_config(e->plugin_reg, e->es, type, e->stream_mask, &ret->section, NULL); } } static void init_stream_from_section(bg_encoder_t * e, stream_config_t * ret, bg_stream_type_t type) { bg_encoder_section_get_stream_config(e->plugin_reg, e->es, type, e->stream_mask, &ret->section, NULL); } static void init_from_section(bg_encoder_t * e) { if(e->stream_mask & BG_STREAM_AUDIO) { init_plugin_from_section(e, &e->audio_plugin, BG_STREAM_AUDIO); init_stream_from_section(e, &e->audio_stream, BG_STREAM_AUDIO); } if(e->stream_mask & BG_STREAM_SUBTITLE_TEXT) { init_plugin_from_section(e, &e->subtitle_text_plugin, BG_STREAM_SUBTITLE_TEXT); init_stream_from_section(e, &e->subtitle_text_stream, BG_STREAM_SUBTITLE_TEXT); } if(e->stream_mask & BG_STREAM_SUBTITLE_OVERLAY) { init_plugin_from_section(e, &e->subtitle_overlay_plugin, BG_STREAM_SUBTITLE_OVERLAY); init_stream_from_section(e, &e->subtitle_overlay_stream, BG_STREAM_SUBTITLE_OVERLAY); } if(e->stream_mask & BG_STREAM_VIDEO) { init_plugin_from_section(e, &e->video_plugin, BG_STREAM_VIDEO); init_stream_from_section(e, &e->video_stream, BG_STREAM_VIDEO); } } static void init_from_tt(bg_encoder_t * e) { const char * plugin_name; /* Video plugin (must come first) */ plugin_name = bg_transcoder_track_get_video_encoder(e->tt); if(plugin_name) { e->video_plugin.info = bg_plugin_find_by_name(e->plugin_reg, plugin_name); e->video_plugin.section = e->tt->video_encoder_section; } /* Audio plugin */ plugin_name = bg_transcoder_track_get_audio_encoder(e->tt); if(plugin_name) { e->audio_plugin.info = bg_plugin_find_by_name(e->plugin_reg, plugin_name); e->audio_plugin.section = e->tt->audio_encoder_section; } /* Subtitle text plugin */ plugin_name = bg_transcoder_track_get_subtitle_text_encoder(e->tt); if(plugin_name) { e->subtitle_text_plugin.info = bg_plugin_find_by_name(e->plugin_reg, plugin_name); e->subtitle_text_plugin.section = e->tt->subtitle_text_encoder_section; } /* Subtitle overlay plugin */ plugin_name = bg_transcoder_track_get_subtitle_overlay_encoder(e->tt); if(plugin_name) { e->subtitle_overlay_plugin.info = bg_plugin_find_by_name(e->plugin_reg, plugin_name); e->subtitle_overlay_plugin.section = e->tt->subtitle_overlay_encoder_section; } } bg_encoder_t * bg_encoder_create(bg_plugin_registry_t * plugin_reg, bg_cfg_section_t * es, bg_transcoder_track_t * tt, int stream_mask, int flag_mask) { bg_encoder_t * ret = calloc(1, sizeof(*ret)); ret->plugin_reg = plugin_reg; ret->stream_mask = stream_mask; ret->cb_int.create_output_file = cb_create_output_file; ret->cb_int.create_temp_file = cb_create_temp_file; ret->cb_int.data = ret; /* Set plugin infos */ if(es) { ret->es = es; init_from_section(ret); } else if(tt) { ret->tt = tt; init_from_tt(ret); } return ret; } void bg_encoder_set_callbacks(bg_encoder_t * e, bg_encoder_callbacks_t * cb) { e->cb_ext = cb; } void bg_encoder_destroy(bg_encoder_t * enc, int do_delete) { int i; /* Close all encoder plugins */ for(i = 0; i < enc->num_plugins; i++) { bg_encoder_plugin_t * encoder = (bg_encoder_plugin_t *)enc->plugins[i]->plugin; encoder->close(enc->plugins[i]->priv, do_delete); bg_plugin_unref(enc->plugins[i]); } if(enc->plugins) free(enc->plugins); if(enc->filename_base) free(enc->filename_base); if(enc->audio_streams) free(enc->audio_streams); if(enc->video_streams) free(enc->video_streams); if(enc->subtitle_text_streams) free(enc->subtitle_text_streams); if(enc->subtitle_overlay_streams) free(enc->subtitle_overlay_streams); free(enc); } int bg_encoder_open(bg_encoder_t * enc, const char * filename_base, const gavl_metadata_t * metadata, const bg_chapter_list_t * chapter_list) { enc->filename_base = bg_strdup(enc->filename_base, filename_base); enc->metadata = metadata; enc->chapter_list = chapter_list; return 1; } static bg_plugin_handle_t * load_encoder(bg_encoder_t * enc, const bg_plugin_info_t * info, bg_cfg_section_t * section, const char * filename_base) { bg_plugin_handle_t * ret; bg_encoder_plugin_t * plugin; enc->plugins = realloc(enc->plugins, (enc->num_plugins+1)* sizeof(enc->plugins)); enc->plugins[enc->num_plugins] = bg_plugin_load(enc->plugin_reg, info); ret = enc->plugins[enc->num_plugins]; plugin = (bg_encoder_plugin_t *)ret->plugin; if(plugin->set_callbacks) plugin->set_callbacks(ret->priv, &enc->cb_int); if(plugin->common.set_parameter) bg_cfg_section_apply(section, info->parameters, plugin->common.set_parameter, ret->priv); if(!plugin->open(ret->priv, filename_base, enc->metadata, enc->chapter_list)) { bg_plugin_unref(ret); return NULL; } enc->num_plugins++; return ret; } static void check_separate(bg_encoder_t * enc) { /* Check for separate audio streams */ if(enc->num_audio_streams) { if((enc->audio_plugin.info) || ((enc->video_plugin.info->max_audio_streams > 0) && (enc->num_audio_streams > enc->video_plugin.info->max_audio_streams))) enc->separate |= BG_STREAM_AUDIO; } /* Check for separate subtitle text streams */ if(enc->num_subtitle_text_streams) { if((enc->subtitle_text_plugin.info) || ((enc->video_plugin.info->max_subtitle_text_streams > 0) && (enc->num_subtitle_text_streams > enc->video_plugin.info->max_subtitle_text_streams))) enc->separate |= BG_STREAM_SUBTITLE_TEXT; } /* Check for separate subtitle overlay streams */ if(enc->num_subtitle_overlay_streams) { if((enc->subtitle_overlay_plugin.info) || ((enc->video_plugin.info->max_subtitle_overlay_streams > 0) && (enc->num_subtitle_overlay_streams > enc->video_plugin.info->max_subtitle_overlay_streams))) enc->separate |= BG_STREAM_SUBTITLE_OVERLAY; } /* Check for separate video streams */ if(enc->num_video_streams) { if((enc->video_plugin.info->max_video_streams > 0) && (enc->num_video_streams > enc->video_plugin.info->max_video_streams)) enc->separate |= BG_STREAM_VIDEO; } /* If video is separate, all other streams get separate as well */ if(enc->separate & BG_STREAM_VIDEO) { enc->separate |= BG_STREAM_SUBTITLE_OVERLAY | BG_STREAM_SUBTITLE_TEXT | BG_STREAM_AUDIO; } else { /* Under some conditions, we want the video to be marked as separate as well */ if(((enc->separate & BG_STREAM_SUBTITLE_OVERLAY) || !enc->num_subtitle_overlay_streams) && ((enc->separate & BG_STREAM_SUBTITLE_TEXT) || !enc->num_subtitle_text_streams) && ((enc->separate & BG_STREAM_AUDIO) || !enc->num_audio_streams)) enc->separate |= BG_STREAM_VIDEO; } } typedef struct { void (*func)(void * data, int index, const char * name, const bg_parameter_value_t*val); void * data; int index; } set_stream_param_struct_t; static void set_stream_param(void * priv, const char * name, const bg_parameter_value_t * val) { set_stream_param_struct_t * s; s = (set_stream_param_struct_t *)priv; s->func(s->data, s->index, name, val); } static bg_plugin_handle_t * get_stream_handle(bg_encoder_t * enc, bg_stream_type_t type, int stream, int in_index) { bg_plugin_handle_t * ret; const bg_plugin_info_t * info = NULL; bg_cfg_section_t * section = NULL; char * filename_base; const char * type_string = NULL; if(enc->separate & type) { switch(type) { case BG_STREAM_AUDIO: type_string = "audio"; info = enc->audio_plugin.info; section = enc->audio_plugin.section; break; case BG_STREAM_VIDEO: type_string = "video"; info = enc->video_plugin.info; section = enc->video_plugin.section; break; case BG_STREAM_SUBTITLE_TEXT: type_string = "subtext"; info = enc->subtitle_text_plugin.info; section = enc->subtitle_text_plugin.section; break; case BG_STREAM_SUBTITLE_OVERLAY: type_string = "subovl"; info = enc->subtitle_overlay_plugin.info; section = enc->subtitle_overlay_plugin.section; break; } if(enc->total_streams > 1) { filename_base = bg_sprintf("%s_%s_%02d", enc->filename_base, type_string, in_index+1); ret = load_encoder(enc, info, section, filename_base); free(filename_base); } else ret = load_encoder(enc, info, section, enc->filename_base); } else { if(enc->num_plugins) ret = enc->plugins[0]; else ret = load_encoder(enc, enc->video_plugin.info, enc->video_plugin.section, enc->filename_base); } return ret; } static int start_audio(bg_encoder_t * enc, int stream) { audio_stream_t * s; bg_plugin_handle_t * h; set_stream_param_struct_t st; s = &enc->audio_streams[stream]; /* Get handle */ h = get_stream_handle(enc, BG_STREAM_AUDIO, stream, s->in_index); if(!h) return 0; s->plugin = (bg_encoder_plugin_t*)h->plugin; s->priv = h->priv; s->h = h; /* Add stream */ if(s->ci) { s->out_index = s->plugin->add_audio_stream_compressed(s->priv, s->m, &s->format, s->ci); if(s->out_index < 0) return 0; } else { s->out_index = s->plugin->add_audio_stream(s->priv, s->m, &s->format); if(s->out_index < 0) return 0; /* Apply parameters */ if(s->plugin->set_audio_parameter) { st.func = s->plugin->set_audio_parameter; st.data = s->priv; st.index = s->out_index; bg_cfg_section_apply(s->section, s->parameters, set_stream_param, &st); } } return 1; } static int start_video(bg_encoder_t * enc, int stream) { video_stream_t * s; bg_plugin_handle_t * h; set_stream_param_struct_t st; s = &enc->video_streams[stream]; /* Get handle */ h = get_stream_handle(enc, BG_STREAM_VIDEO, stream, s->in_index); if(!h) return 0; s->plugin = (bg_encoder_plugin_t*)h->plugin; s->priv = h->priv; s->h = h; /* Add stream */ if(s->ci) { s->out_index = s->plugin->add_video_stream_compressed(s->priv, s->m, &s->format, s->ci); if(s->out_index < 0) return 0; } else { s->out_index = s->plugin->add_video_stream(s->priv, s->m, &s->format); if(s->out_index < 0) return 0; /* Apply parameters */ if(s->plugin->set_video_parameter) { st.func = s->plugin->set_video_parameter; st.data = s->priv; st.index = s->out_index; bg_cfg_section_apply(s->section, s->parameters, set_stream_param, &st); } /* Set pass */ if(s->total_passes) { if(!s->plugin->set_video_pass || !s->plugin->set_video_pass(s->priv, s->out_index, s->pass, s->total_passes, s->stats_file)) { bg_log(BG_LOG_ERROR, LOG_DOMAIN, "Multipass encoding not supported by encoder plugin"); return 0; } } } return 1; } static int start_subtitle_text(bg_encoder_t * enc, int stream) { subtitle_text_stream_t * s; bg_plugin_handle_t * h; set_stream_param_struct_t st; s = &enc->subtitle_text_streams[stream]; /* Get handle */ h = get_stream_handle(enc, BG_STREAM_SUBTITLE_TEXT, stream, s->in_index); if(!h) return 0; s->plugin = (bg_encoder_plugin_t*)h->plugin; s->priv = h->priv; s->h = h; /* Add stream */ s->out_index = s->plugin->add_subtitle_text_stream(s->priv, s->m, &s->timescale); if(s->out_index < 0) return 0; /* Apply parameters */ if(s->plugin->set_subtitle_text_parameter) { st.func = s->plugin->set_subtitle_text_parameter; st.data = s->priv; st.index = s->out_index; bg_cfg_section_apply(s->section, s->parameters, set_stream_param, &st); } return 1; } static int start_subtitle_overlay(bg_encoder_t * enc, int stream) { subtitle_overlay_stream_t * s; bg_plugin_handle_t * h; set_stream_param_struct_t st; s = &enc->subtitle_overlay_streams[stream]; /* Get handle */ h = get_stream_handle(enc, BG_STREAM_SUBTITLE_OVERLAY, stream, s->in_index); if(!h) return 0; s->plugin = (bg_encoder_plugin_t*)h->plugin; s->priv = h->priv; s->h = h; /* Add stream */ s->out_index = s->plugin->add_subtitle_overlay_stream(s->priv, s->m, &s->format); if(s->out_index < 0) return 0; /* Apply parameters */ if(s->plugin->set_subtitle_overlay_parameter) { st.func = s->plugin->set_subtitle_overlay_parameter; st.data = s->priv; st.index = s->out_index; bg_cfg_section_apply(s->section, s->parameters, set_stream_param, &st); } return 1; } /* Start encoding */ int bg_encoder_start(bg_encoder_t * enc) { int i; check_separate(enc); enc->total_streams = enc->num_audio_streams + enc->num_video_streams + enc->num_subtitle_text_streams + enc->num_subtitle_overlay_streams; /* We make sure, that for the case of combined streams the video is always the first one */ for(i = 0; i < enc->num_video_streams; i++) { if(!start_video(enc, i)) return 0; } for(i = 0; i < enc->num_audio_streams; i++) { if(!start_audio(enc, i)) return 0; } for(i = 0; i < enc->num_subtitle_text_streams; i++) { if(!start_subtitle_text(enc, i)) return 0; } for(i = 0; i < enc->num_subtitle_overlay_streams; i++) { if(!start_subtitle_overlay(enc, i)) return 0; } /* Start encoders */ for(i = 0; i < enc->num_plugins; i++) { bg_encoder_plugin_t * plugin = (bg_encoder_plugin_t *)enc->plugins[i]->plugin; if(plugin->start && !plugin->start(enc->plugins[i]->priv)) return 0; } return 1; } /* Add streams */ #define REALLOC_STREAM(streams, num) \ streams = realloc(streams, sizeof(*streams)*(num+1));\ s = &streams[num]; \ memset(s, 0, sizeof(*s)); /* Add streams */ int bg_encoder_add_audio_stream(bg_encoder_t * enc, const gavl_metadata_t * m, const gavl_audio_format_t * format, int source_index) { int ret; audio_stream_t * s; REALLOC_STREAM(enc->audio_streams, enc->num_audio_streams); gavl_audio_format_copy(&s->format, format); s->in_index = source_index; if(enc->tt) s->section = enc->tt->audio_streams[source_index].encoder_section; else s->section = enc->audio_stream.section; if(enc->audio_plugin.info) s->parameters = enc->audio_plugin.info->audio_parameters; else if(enc->video_plugin.info) s->parameters = enc->video_plugin.info->audio_parameters; s->m = m; ret = enc->num_audio_streams; enc->num_audio_streams++; return ret; } int bg_encoder_add_video_stream(bg_encoder_t * enc, const gavl_metadata_t * m, const gavl_video_format_t * format, int source_index) { int ret; video_stream_t * s; REALLOC_STREAM(enc->video_streams, enc->num_video_streams); gavl_video_format_copy(&s->format, format); s->in_index = source_index; if(enc->tt) s->section = enc->tt->video_streams[source_index].encoder_section; else s->section = enc->video_stream.section; s->parameters = enc->video_plugin.info->video_parameters; s->m = m; ret = enc->num_video_streams; enc->num_video_streams++; return ret; } int bg_encoder_add_audio_stream_compressed(bg_encoder_t * enc, const gavl_metadata_t * m, const gavl_audio_format_t * format, const gavl_compression_info_t * info, int source_index) { int ret; audio_stream_t * s; REALLOC_STREAM(enc->audio_streams, enc->num_audio_streams); gavl_audio_format_copy(&s->format, format); s->in_index = source_index; s->ci = info; s->m = m; ret = enc->num_audio_streams; enc->num_audio_streams++; return ret; } int bg_encoder_add_video_stream_compressed(bg_encoder_t * enc, const gavl_metadata_t * m, const gavl_video_format_t * format, const gavl_compression_info_t * info, int source_index) { int ret; video_stream_t * s; REALLOC_STREAM(enc->video_streams, enc->num_video_streams); gavl_video_format_copy(&s->format, format); s->in_index = source_index; s->ci = info; s->m = m; ret = enc->num_video_streams; enc->num_video_streams++; return ret; } int bg_encoder_add_subtitle_text_stream(bg_encoder_t * enc, const gavl_metadata_t * m, int timescale, int source_index) { int ret; subtitle_text_stream_t * s; REALLOC_STREAM(enc->subtitle_text_streams, enc->num_subtitle_text_streams); s->timescale = timescale; s->in_index = source_index; s->m = m; if(enc->tt) s->section = enc->tt->subtitle_text_streams[source_index].encoder_section_text; else s->section = enc->subtitle_text_stream.section; if(enc->subtitle_text_plugin.info) s->parameters = enc->subtitle_text_plugin.info->subtitle_text_parameters; else if(enc->video_plugin.info) s->parameters = enc->video_plugin.info->subtitle_text_parameters; ret = enc->num_subtitle_text_streams; enc->num_subtitle_text_streams++; return ret; } int bg_encoder_add_subtitle_overlay_stream(bg_encoder_t * enc, const gavl_metadata_t * m, const gavl_video_format_t * format, int source_index, bg_stream_type_t source_format) { int ret; subtitle_overlay_stream_t * s; REALLOC_STREAM(enc->subtitle_overlay_streams, enc->num_subtitle_overlay_streams); gavl_video_format_copy(&s->format, format); s->in_index = source_index; s->m = m; if(enc->tt) { if(source_format == BG_STREAM_SUBTITLE_TEXT) s->section = enc->tt->subtitle_text_streams[source_index].encoder_section_overlay; else s->section = enc->tt->subtitle_overlay_streams[source_index].encoder_section; } else s->section = enc->subtitle_overlay_stream.section; if(enc->subtitle_overlay_plugin.info) s->parameters = enc->subtitle_overlay_plugin.info->subtitle_overlay_parameters; else if(enc->video_plugin.info) s->parameters = enc->video_plugin.info->subtitle_overlay_parameters; ret = enc->num_subtitle_overlay_streams; enc->num_subtitle_overlay_streams++; return ret; } void bg_encoder_set_video_pass(bg_encoder_t * enc, int stream, int pass, int total_passes, const char * stats_file) { video_stream_t * s = &enc->video_streams[stream]; s->pass = pass; s->total_passes = total_passes; s->stats_file = bg_strdup(s->stats_file, stats_file); } /* Get formats */ void bg_encoder_get_audio_format(bg_encoder_t * enc, int stream, gavl_audio_format_t*ret) { audio_stream_t * s = &enc->audio_streams[stream]; s->plugin->get_audio_format(s->priv, s->out_index, ret); } void bg_encoder_get_video_format(bg_encoder_t * enc, int stream, gavl_video_format_t*ret) { video_stream_t * s = &enc->video_streams[stream]; s->plugin->get_video_format(s->priv, s->out_index, ret); } void bg_encoder_get_subtitle_overlay_format(bg_encoder_t * enc, int stream, gavl_video_format_t*ret) { subtitle_overlay_stream_t * s = &enc->subtitle_overlay_streams[stream]; s->plugin->get_subtitle_overlay_format(s->priv, s->out_index, ret); } void bg_encoder_get_subtitle_text_timescale(bg_encoder_t * enc, int stream, int * ret) { subtitle_text_stream_t * s = &enc->subtitle_text_streams[stream]; *ret = s->timescale; } /* Write frame */ int bg_encoder_write_audio_frame(bg_encoder_t * enc, gavl_audio_frame_t * frame, int stream) { int ret; audio_stream_t * s = &enc->audio_streams[stream]; bg_plugin_lock(s->h); ret = s->plugin->write_audio_frame(s->priv, frame, s->out_index); bg_plugin_unlock(s->h); return ret; } int bg_encoder_write_video_frame(bg_encoder_t * enc, gavl_video_frame_t * frame, int stream) { int ret; video_stream_t * s = &enc->video_streams[stream]; #if 0 fprintf(stderr, "Write video frame %"PRId64"\n", frame->timestamp); if(frame->timestamp < s->last_timestamp) { fprintf(stderr, "Error: %"PRId64" < %"PRId64"\n", frame->timestamp, s->last_timestamp); } s->last_timestamp = frame->timestamp; #endif bg_plugin_lock(s->h); ret = s->plugin->write_video_frame(s->priv, frame, s->out_index); bg_plugin_unlock(s->h); return ret; } int bg_encoder_write_subtitle_text(bg_encoder_t * enc, const char * text, int64_t start, int64_t duration, int stream) { int ret; subtitle_text_stream_t * s = &enc->subtitle_text_streams[stream]; bg_plugin_lock(s->h); ret = s->plugin->write_subtitle_text(s->priv, text, start, duration, s->out_index); bg_plugin_unlock(s->h); return ret; } int bg_encoder_write_subtitle_overlay(bg_encoder_t * enc, gavl_overlay_t * ovl, int stream) { int ret; subtitle_overlay_stream_t * s = &enc->subtitle_overlay_streams[stream]; bg_plugin_lock(s->h); ret = s->plugin->write_subtitle_overlay(s->priv, ovl, s->out_index); bg_plugin_unlock(s->h); return ret; } static bg_plugin_handle_t * open_dummy_encoder(bg_encoder_t * enc, const bg_plugin_info_t * plugin_info, bg_cfg_section_t * plugin_section) { bg_encoder_plugin_t * plugin; bg_plugin_handle_t * ret; ret = bg_plugin_load(enc->plugin_reg, plugin_info); plugin = (bg_encoder_plugin_t *)ret->plugin; if(plugin->common.set_parameter) bg_cfg_section_apply(plugin_section, plugin_info->parameters, plugin->common.set_parameter, ret->priv); return ret; } int bg_encoder_writes_compressed_audio(bg_encoder_t * enc, const gavl_audio_format_t * format, const gavl_compression_info_t * info) { int ret; bg_encoder_plugin_t * plugin; const bg_plugin_info_t * plugin_info; bg_plugin_handle_t * h; bg_cfg_section_t * plugin_section; if(enc->audio_plugin.info) { plugin_info = enc->audio_plugin.info; plugin_section = enc->audio_plugin.section; } else if(enc->video_plugin.info) { plugin_info = enc->video_plugin.info; plugin_section = enc->video_plugin.section; } else return 0; h = open_dummy_encoder(enc, plugin_info, plugin_section); plugin = (bg_encoder_plugin_t *)h->plugin; if(plugin->writes_compressed_audio) ret = plugin->writes_compressed_audio(h->priv, format, info); else ret = 0; bg_plugin_unref(h); return ret; } int bg_encoder_writes_compressed_video(bg_encoder_t * enc, const gavl_video_format_t * format, const gavl_compression_info_t * info) { int ret; bg_encoder_plugin_t * plugin; const bg_plugin_info_t * plugin_info; bg_plugin_handle_t * h; bg_cfg_section_t * plugin_section; if(enc->video_plugin.info) { plugin_info = enc->video_plugin.info; plugin_section = enc->video_plugin.section; } else return 0; h = open_dummy_encoder(enc, plugin_info, plugin_section); plugin = (bg_encoder_plugin_t *)h->plugin; if(plugin->writes_compressed_video) ret = plugin->writes_compressed_video(h->priv, format, info); else ret = 0; bg_plugin_unref(h); return ret; } int bg_encoder_write_audio_packet(bg_encoder_t * enc, gavl_packet_t * p, int stream) { int ret; audio_stream_t * s = &enc->audio_streams[stream]; bg_plugin_lock(s->h); ret = s->plugin->write_audio_packet(s->priv, p, s->out_index); bg_plugin_unlock(s->h); return ret; } int bg_encoder_write_video_packet(bg_encoder_t * enc, gavl_packet_t * p, int stream) { int ret; video_stream_t * s = &enc->video_streams[stream]; bg_plugin_lock(s->h); ret = s->plugin->write_video_packet(s->priv, p, s->out_index); bg_plugin_unlock(s->h); return ret; } void bg_encoder_update_metadata(bg_encoder_t * enc, const char * name, const gavl_metadata_t * m) { int i; for(i = 0; i < enc->num_plugins; i++) { bg_encoder_plugin_t * encoder = (bg_encoder_plugin_t *)enc->plugins[i]->plugin; if(encoder->update_metadata) { bg_plugin_lock(enc->plugins[i]); encoder->update_metadata(enc->plugins[i]->priv, name, m); bg_plugin_unlock(enc->plugins[i]); } } } gmerlin-1.2.0~dfsg/lib/stringutils.c0000644000175000017500000003261111764363410017402 0ustar alessioalessio/***************************************************************** * gmerlin - a general purpose multimedia framework and applications * * Copyright (c) 2001 - 2011 Members of the Gmerlin project * gmerlin-general@lists.sourceforge.net * http://gmerlin.sourceforge.net * * 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 of the License, 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 this program. If not, see . * *****************************************************************/ #define _GNU_SOURCE #include #include #include #include #include #include #include #include #include #include /* stat stuff */ #include #include #include #include #include #include #define LOG_DOMAIN "utils" #include #include #include char * bg_fix_path(char * path) { char * ret; int len; if(!path) return path; len = strlen(path); if(!len) { free(path); return NULL; } if(path[len-1] != '/') { ret = malloc(len+2); strcpy(ret, path); free(path); ret[len] = '/'; ret[len+1] = '\0'; return ret; } else return path; } char * bg_strdup(char * old_string, const char * new_string) { char * ret; int len; if(!new_string || (*new_string == '\0')) { if(old_string) free(old_string); return NULL; } if(old_string) { if(!strcmp(old_string, new_string)) return old_string; else free(old_string); } len = ((strlen(new_string)+1 + 3) / 4) * 4 ; ret = malloc(len); strcpy(ret, new_string); return ret; } char * bg_strndup(char * old_string, const char * new_string_start, const char * new_string_end) { char * ret; if(!new_string_start || (*new_string_start == '\0')) { if(old_string) free(old_string); return NULL; } if(old_string) { if(!strncmp(old_string, new_string_start, new_string_end - new_string_start)) return old_string; else free(old_string); } ret = malloc(new_string_end - new_string_start + 1); strncpy(ret, new_string_start, new_string_end - new_string_start); ret[new_string_end - new_string_start] = '\0'; return ret; } char * bg_sprintf(const char * format,...) { va_list argp; /* arg ptr */ #ifndef HAVE_VASPRINTF int len; #endif char * ret; va_start( argp, format); #ifndef HAVE_VASPRINTF len = vsnprintf(NULL, 0, format, argp); ret = malloc(len+1); vsnprintf(ret, len+1, format, argp); #else vasprintf(&ret, format, argp); #endif va_end(argp); return ret; } char * bg_create_unique_filename(char * template) { char * filename; struct stat stat_buf; FILE * file; int err = 0; uint32_t count; count = 0; filename = bg_sprintf(template, 0); while(1) { if(stat(filename, &stat_buf) == -1) { /* Create empty file */ file = fopen(filename, "w"); if(file) { fclose(file); } else { bg_log(BG_LOG_ERROR, LOG_DOMAIN, "Cannot open file \"%s\" for writing", filename); err = 1; } if(err) { free(filename); return NULL; } else return filename; } count++; sprintf(filename, template, count); } } char * bg_strcat(char * old_string, const char * tail) { if(!old_string) return bg_strdup(NULL, tail); old_string = realloc(old_string, strlen(old_string) + strlen(tail) + 1); strcat(old_string, tail); return old_string; } char * bg_strncat(char * old_string, const char * start, const char * end) { int old_len; if(!old_string) return bg_strndup(NULL, start, end); old_len = strlen(old_string); old_string = realloc(old_string, old_len + end - start + 1); strncpy(&old_string[old_len], start, end - start); old_string[old_len + end - start] = '\0'; return old_string; } char ** bg_strbreak(const char * str, char delim) { int num_entries; char *pos, *end = NULL; const char *pos_c; char ** ret; int i; if(!str || (*str == '\0')) return NULL; pos_c = str; num_entries = 1; while((pos_c = strchr(pos_c, delim))) { num_entries++; pos_c++; } ret = calloc(num_entries+1, sizeof(char*)); ret[0] = bg_strdup(NULL, str); pos = ret[0]; for(i = 0; i < num_entries; i++) { if(i) ret[i] = pos; if(i < num_entries-1) { end = strchr(pos, delim); *end = '\0'; } end++; pos = end; } return ret; } void bg_strbreak_free(char ** retval) { free(retval[0]); free(retval); } int bg_string_is_url(const char * str) { const char * pos, * end_pos; pos = str; end_pos = strstr(str, "://"); if(!end_pos) return 0; while(pos != end_pos) { if(!isalnum(*pos)) return 0; pos++; } return 1; } int bg_url_split(const char * url, char ** protocol, char ** user, char ** password, char ** hostname, int * port, char ** path) { const char * pos1; const char * pos2; /* For detecting user:pass@blabla.com/file */ const char * colon_pos; const char * at_pos; const char * slash_pos; pos1 = url; /* Sanity check */ pos2 = strstr(url, "://"); if(!pos2) return 0; /* Protocol */ if(protocol) *protocol = bg_strndup(NULL, pos1, pos2); pos2 += 3; pos1 = pos2; /* Check for user and password */ colon_pos = strchr(pos1, ':'); at_pos = strchr(pos1, '@'); slash_pos = strchr(pos1, '/'); if(colon_pos && at_pos && at_pos && (colon_pos < at_pos) && (at_pos < slash_pos)) { if(user) *user = bg_strndup(NULL, pos1, colon_pos); pos1 = colon_pos + 1; if(password) *password = bg_strndup(NULL, pos1, at_pos); pos1 = at_pos + 1; pos2 = pos1; } /* Hostname */ while((*pos2 != '\0') && (*pos2 != ':') && (*pos2 != '/')) pos2++; if(hostname) *hostname = bg_strndup(NULL, pos1, pos2); switch(*pos2) { case '\0': if(port) *port = -1; return 1; break; case ':': /* Port */ pos2++; if(port) *port = atoi(pos2); while(isdigit(*pos2)) pos2++; break; default: if(port) *port = -1; break; } if(path) { pos1 = pos2; pos2 = pos1 + strlen(pos1); if(pos1 != pos2) *path = bg_strndup(NULL, pos1, pos2); else *path = NULL; } return 1; } /* Scramble and descramble password (taken from gftp) */ char * bg_scramble_string(const char * str) { char *newstr, *newpos; newstr = malloc (strlen (str) * 2 + 2); newpos = newstr; *newpos++ = '$'; while (*str != 0) { *newpos++ = ((*str >> 2) & 0x3c) | 0x41; *newpos++ = ((*str << 2) & 0x3c) | 0x41; str++; } *newpos = 0; return (newstr); } char * bg_descramble_string(const char *str) { const char *strpos; char *newstr, *newpos; int error; if (*str != '$') return (bg_strdup (NULL, str)); strpos = str + 1; newstr = malloc (strlen (strpos) / 2 + 1); newpos = newstr; error = 0; while (*strpos != '\0' && (*strpos + 1) != '\0') { if ((*strpos & 0xc3) != 0x41 || (*(strpos + 1) & 0xc3) != 0x41) { error = 1; break; } *newpos++ = ((*strpos & 0x3c) << 2) | ((*(strpos + 1) & 0x3c) >> 2); strpos += 2; } if(error) { free (newstr); return (bg_strdup(NULL, str)); } *newpos = '\0'; return (newstr); } const char * bg_get_language_name(const char * iso) { int i = 0; while(bg_language_codes[i]) { if((bg_language_codes[i][0] == iso[0]) && (bg_language_codes[i][1] == iso[1]) && (bg_language_codes[i][2] == iso[2])) return bg_language_labels[i]; i++; } return NULL; } int bg_string_match(const char * key, const char * key_list) { const char * pos; const char * end; pos = key_list; if(!key_list) return 0; while(1) { end = pos; while(!isspace(*end) && (*end != '\0')) end++; if(end == pos) break; if((strlen(key) == (int)(end-pos)) && !strncasecmp(pos, key, (int)(end-pos))) { return 1; } pos = end; if(pos == '\0') break; else { while(isspace(*pos) && (pos != '\0')) pos++; } } return 0; } /* Used mostly for generating manual pages, it's horribly inefficient */ char * bg_toupper(const char * str) { char * tmp_string_1; char * tmp_string_2; char * ret; int len; wchar_t * pos_1, * pos_2; bg_charset_converter_t * cnv1; bg_charset_converter_t * cnv2; cnv1 = bg_charset_converter_create("UTF-8", "WCHAR_T"); cnv2 = bg_charset_converter_create("WCHAR_T", "UTF-8"); tmp_string_1 = bg_convert_string(cnv1, str, -1, &len); tmp_string_2 = malloc(len + 4); pos_1 = (wchar_t*)tmp_string_1; pos_2 = (wchar_t*)tmp_string_2; while(*pos_1) { *pos_2 = towupper(*pos_1); pos_1++; pos_2++; } *pos_2 = 0; ret = bg_convert_string(cnv2, tmp_string_2, len, NULL); free(tmp_string_1); free(tmp_string_2); bg_charset_converter_destroy(cnv1); bg_charset_converter_destroy(cnv2); return ret; } void bg_get_filename_hash(const char * gml, char ret[33]) { char * uri; uint8_t md5sum[16]; uri = bg_string_to_uri(gml, -1); bg_md5_buffer(uri, strlen(uri), md5sum); sprintf(ret, "%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x", md5sum[0], md5sum[1], md5sum[2], md5sum[3], md5sum[4], md5sum[5], md5sum[6], md5sum[7], md5sum[8], md5sum[9], md5sum[10], md5sum[11], md5sum[12], md5sum[13], md5sum[14], md5sum[15]); free(uri); } void bg_dprintf(const char * format, ...) { va_list argp; /* arg ptr */ va_start( argp, format); vfprintf(stderr, format, argp); va_end(argp); } void bg_diprintf(int indent, const char * format, ...) { int i; va_list argp; /* arg ptr */ for(i = 0; i < indent; i++) bg_dprintf( " "); va_start( argp, format); vfprintf(stderr, format, argp); va_end(argp); } char * bg_filename_ensure_extension(const char * filename, const char * ext) { const char * pos; if((pos = strrchr(filename, '.')) && (!strcasecmp(pos+1, ext))) return bg_strdup(NULL, filename); else return bg_sprintf("%s.%s", filename, ext); } char * bg_get_stream_label(int index, const gavl_metadata_t * m) { char * label; const char * info; const char * language; info = gavl_metadata_get(m, GAVL_META_LABEL); language = gavl_metadata_get(m, GAVL_META_LANGUAGE); if(info && language) label = bg_sprintf("%s [%s]", info, bg_get_language_name(language)); else if(info) label = bg_sprintf("%s", info); else if(language) label = bg_sprintf(TR("Stream %d [%s]"), index+1, bg_get_language_name(language)); else label = bg_sprintf(TR("Stream %d"), index+1); return label; } char * bg_canonical_filename(const char * name) { #ifdef HAVE_CANONICALIZE_FILE_NAME return canonicalize_file_name(name); #else char * ret = malloc(PATH_MAX); realpath(name, ret); return ret; #endif } void * bg_read_file(const char * filename, int * len_ret) { uint8_t * ret; FILE * file; size_t len; file = fopen(filename, "r"); if(!file) return NULL; fseek(file, 0, SEEK_END); len = ftell(file); fseek(file, 0, SEEK_SET); ret = malloc(len + 1); if(fread(ret, 1, len, file) < len) { fclose(file); free(ret); return NULL; } ret[len] = '\0'; fclose(file); if(len_ret) *len_ret = len; return ret; } int bg_write_file(const char * filename, void * data, int len) { FILE * file; file = fopen(filename, "w"); if(!file) return 0; if(fwrite(data, 1, len, file) < len) { fclose(file); return 0; } fclose(file); return 1; } static const struct { const char * bcode; const char * tcode; } iso639tab[] = { { "alb", "sqi" }, { "arm", "hye" }, { "baq", "eus" }, { "bur", "mya" }, { "chi", "zho" }, { "cze", "ces" }, { "dut", "nld" }, { "fre", "fra" }, { "geo", "kat" }, { "ger", "deu" }, { "gre", "ell" }, { "ice", "isl" }, { "mac", "mkd" }, { "mao", "mri" }, { "may", "msa" }, { "per", "fas" }, { "rum", "ron" }, { "slo", "slk" }, { "tib", "bod" }, { "wel", "cym" }, { /* End */ } }; const char * bg_iso639_b_to_t(const char * code) { int i = 0; while(iso639tab[i].bcode) { if(!strcmp(code, iso639tab[i].bcode)) return iso639tab[i].tcode; i++; } return code; } gmerlin-1.2.0~dfsg/lib/cmdline.c0000644000175000017500000007333411764363410016435 0ustar alessioalessio/***************************************************************** * gmerlin - a general purpose multimedia framework and applications * * Copyright (c) 2001 - 2011 Members of the Gmerlin project * gmerlin-general@lists.sourceforge.net * http://gmerlin.sourceforge.net * * 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 of the License, 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 this program. If not, see . * *****************************************************************/ #include #include #include #include #include #include #include #include #include #include #include static const bg_cmdline_app_data_t * app_data; /* Terminal related functions */ #define MAX_COLS 79 /* For line-wrapping */ static void opt_help(void * data, int * argc, char *** argv, int arg); static void opt_help_man(void * data, int * argc, char *** argv, int arg); static void opt_help_texi(void * data, int * argc, char *** argv, int arg); static void opt_version(void * data, int * argc, char *** argv, int arg); static void do_indent(FILE * out, int num, bg_help_format_t format) { switch(format) { case BG_HELP_FORMAT_TERM: case BG_HELP_FORMAT_PLAIN: { int i; for(i = 0; i < num; i++) fprintf(out, " "); } break; case BG_HELP_FORMAT_MAN: // fprintf(out, ".RS %d\n", num); break; case BG_HELP_FORMAT_TEXI: break; } } static void dump_string_term(FILE * out, const char * str, int indent, const char * translation_domain, bg_help_format_t format) { const char * start; const char * end; const char * pos; str = TR_DOM(str); if(format == BG_HELP_FORMAT_MAN) do_indent(out, indent + 2, format); start = str; pos = str; end = str; while(1) { if(isspace(*pos)) end = pos; if(pos - start + indent + 2 > MAX_COLS) { if(format != BG_HELP_FORMAT_MAN) do_indent(out, indent + 2, format); fwrite(start, 1, end - start, out); fprintf(out, "\n"); while(isspace(*end)) end++; start = end; } else if(*pos == '\0') { if(format != BG_HELP_FORMAT_MAN) do_indent(out, indent + 2, format); fwrite(start, 1, pos - start, out); fprintf(out, "\n"); break; } else if(*pos == '\n') { if(format != BG_HELP_FORMAT_MAN) do_indent(out, indent + 2, format); fwrite(start, 1, pos - start, out); if(format == BG_HELP_FORMAT_TEXI) fprintf(out, "@*\n"); else fprintf(out, "\n"); pos++; start = pos; end = pos; } else pos++; } } static const char ansi_underline[] = { 27, '[', '4', 'm', '\0' }; static const char ansi_normal[] = { 27, '[', '0', 'm', '\0' }; static const char ansi_bold[] = { 27, '[', '1', 'm', '\0' }; static void print_string(FILE * out, const char * str, bg_help_format_t format) { switch(format) { case BG_HELP_FORMAT_TEXI: { const char * pos; pos = str; while(*pos) { if((*pos == '{') || (*pos == '}') || (*pos == '@')) fprintf(out, "@%c", *pos); else fprintf(out, "%c", *pos); pos++; } } break; default: fprintf(out, "%s", str); break; } } static void print_bold(FILE * out, char * str, bg_help_format_t format) { switch(format) { case BG_HELP_FORMAT_TERM: fprintf(out, "%s%s%s", ansi_bold, str, ansi_normal); break; case BG_HELP_FORMAT_PLAIN: fprintf(out, "%s", str); /* Do nothing */ break; case BG_HELP_FORMAT_MAN: fprintf(out, ".B %s\n", str); break; case BG_HELP_FORMAT_TEXI: fprintf(out, "@b{"); print_string(out, str, format); fprintf(out, "}"); break; } } static void print_italic(FILE * out, char * str, bg_help_format_t format) { switch(format) { case BG_HELP_FORMAT_TERM: fprintf(out, "%s%s%s", ansi_underline, str, ansi_normal); break; case BG_HELP_FORMAT_PLAIN: /* Do nothing */ fprintf(out, "%s", str); break; case BG_HELP_FORMAT_MAN: fprintf(out, ".I %s\n", str); break; case BG_HELP_FORMAT_TEXI: fprintf(out, "@i{"); print_string(out, str, format); fprintf(out, "}"); break; } } static void print_linebreak(FILE * out, bg_help_format_t format) { if(format == BG_HELP_FORMAT_MAN) fprintf(out, "\n.P\n"); else if(format == BG_HELP_FORMAT_TEXI) fprintf(out, "@*@*\n"); else fprintf(out, "\n\n"); } static void print_version(const bg_cmdline_app_data_t * app_data) { printf("%s (%s) %s\n", app_data->name, app_data->package, app_data->version); printf(TR("Copyright (C) 2001-2007 Members of the gmerlin project\n")); printf(TR("This is free software. You may redistribute copies of it under the terms of\n\ the GNU General Public License .\n\ There is NO WARRANTY.\n")); } static void print_help(const bg_cmdline_arg_t* args, bg_help_format_t format) { int i = 0; FILE * out = stdout; if(format == BG_HELP_FORMAT_TEXI) fprintf(out, "@table @i\n"); while(args[i].arg) { switch(format) { case BG_HELP_FORMAT_PLAIN: case BG_HELP_FORMAT_TERM: fprintf(out, " "); print_bold(out, args[i].arg, format); if(args[i].help_arg) { fprintf(out, " "); print_italic(out, args[i].help_arg, format); } fprintf(out, "\n"); dump_string_term(out, args[i].help_string, 0, NULL, format); break; case BG_HELP_FORMAT_TEXI: fprintf(out, "@item %s", args[i].arg); if(args[i].help_arg) { fprintf(out, " "); print_string(out, args[i].help_arg, format); } fprintf(out, "\n"); print_string(out, args[i].help_string, format); fprintf(out, "@*\n"); break; case BG_HELP_FORMAT_MAN: print_bold(out, args[i].arg, format); if(args[i].help_arg) print_italic(out, args[i].help_arg, format); fprintf(out, "\n"); fprintf(out, ".RS 2\n"); dump_string_term(out, args[i].help_string, 0, NULL, format); fprintf(out, ".RE\n"); break; } if(args[i].parameters) { bg_cmdline_print_help_parameters(args[i].parameters, format); } fprintf(out, "\n"); i++; } if(format == BG_HELP_FORMAT_TEXI) fprintf(out, "@end table\n"); } static const bg_cmdline_arg_t auto_options[] = { { .arg = "-help", .help_string = TRS("Print this help message and exit"), .callback = opt_help, }, { .arg = "-help-man", .help_string = TRS("Print this help message as a manual page and exit"), .callback = opt_help_man, }, { .arg = "-help-texi", .help_string = TRS("Print this help message in texinfo format and exit"), .callback = opt_help_texi, }, { .arg = "-version", .help_string = TRS("Print version info and exit"), .callback = opt_version, }, { /* End of options */ } }; void bg_cmdline_print_help(char * argv0, bg_help_format_t format) { int i; char * tmp_string; switch(format) { case BG_HELP_FORMAT_TERM: case BG_HELP_FORMAT_PLAIN: tmp_string = bg_sprintf(TRD(app_data->synopsis, app_data->package), argv0); printf("Usage: %s\n\n", tmp_string); free(tmp_string); printf("%s\n", app_data->help_before); i = 0; while(app_data->args[i].name) { printf("%s\n\n", app_data->args[i].name); print_help(app_data->args[i].args, format); i++; } print_bold(stdout, "Generic options\n", format); printf("\nThe following generic options are available for all gmerlin applications\n"); print_linebreak(stdout, format); print_help(auto_options, format); if(app_data->env) { print_bold(stdout, TR("Environment variables\n\n"), format); i = 0; while(app_data->env[i].name) { print_bold(stdout, app_data->env[i].name, format); printf("\n"); dump_string_term(stdout, app_data->env[i].desc, 0, NULL, format); i++; print_linebreak(stdout, format); } } if(app_data->files) { print_bold(stdout, TR("Files\n\n"), format); i = 0; while(app_data->files[i].name) { print_bold(stdout, app_data->files[i].name, format); printf("\n"); dump_string_term(stdout, app_data->files[i].desc, 0, NULL, format); print_linebreak(stdout, format); i++; } } break; case BG_HELP_FORMAT_MAN: { char date_str[512]; struct tm brokentime; time_t t; char ** args; char * string_uc; time(&t); localtime_r(&t, &brokentime); strftime(date_str, 511, "%B %Y", &brokentime); string_uc = bg_toupper(app_data->name); printf(".TH %s 1 \"%s\" Gmerlin \"User Manuals\"\n", string_uc, date_str); free(string_uc); printf(".SH NAME\n%s\n", app_data->name); printf(".SH SYNOPSIS\n.B %s \n", app_data->name); tmp_string = bg_strdup(NULL, TRD(app_data->synopsis, app_data->package)); args = bg_strbreak(tmp_string, ' '); i = 0; while(args[i]) { printf(".I %s\n", args[i]); i++; } if(app_data->help_before) printf(".SH DESCRIPTION\n%s\n", TRD(app_data->help_before, app_data->package)); i = 0; while(app_data->args[i].name) { string_uc = bg_toupper(app_data->args[i].name); printf(".SH %s\n\n", string_uc); free(string_uc); print_help(app_data->args[i].args, format); i++; } printf(".SH GENERIC OPTIONS\nThe following generic options are available for all gmerlin applications\n\n"); print_help(auto_options, format); if(app_data->env) { printf(TR(".SH ENVIRONMENT VARIABLES\n")); i = 0; while(app_data->env[i].name) { print_bold(stdout, app_data->env[i].name, format); printf("\n"); printf(".RS 2\n"); dump_string_term(stdout, app_data->env[i].desc, 0, NULL, format); printf(".RE\n"); i++; } } if(app_data->files) { printf(TR(".SH FILES\n")); i = 0; while(app_data->files[i].name) { print_bold(stdout, app_data->files[i].name, format); printf("\n"); printf(".RS 2\n"); dump_string_term(stdout, app_data->files[i].desc, 0, NULL, format); printf(".RE\n"); print_linebreak(stdout, format); i++; } } } break; case BG_HELP_FORMAT_TEXI: printf("@table @b\n"); printf("@item Synopsis\n"); printf("@b{%s} @i{%s}@*\n", app_data->name, TRD(app_data->synopsis, app_data->package)); if(app_data->help_before) { printf("@item Description\n"); printf("%s@*\n", TRD(app_data->help_before, app_data->package)); } i = 0; while(app_data->args[i].name) { printf("@item %s\n", app_data->args[i].name); print_help(app_data->args[i].args, format); i++; } printf("@item Generic options\n"); printf("The following generic options are available for all gmerlin applications@*\n"); print_help(auto_options, format); if(app_data->env) { printf(TR("@item Environment variables\n")); printf("@table @env\n"); i = 0; while(app_data->env[i].name) { printf("@item %s\n", app_data->env[i].name); printf("%s@*\n", TRD(app_data->env[i].desc, app_data->package)); i++; } printf("@end table\n"); } if(app_data->files) { printf(TR("@item Files\n")); printf("@table @file\n"); i = 0; while(app_data->files[i].name) { printf("@item %s\n", app_data->files[i].name); printf("%s@*\n", TRD(app_data->files[i].desc, app_data->package)); i++; } printf("@end table\n"); } printf("@end table\n"); break; } } static void opt_help(void * data, int * argc, char *** argv, int arg) { if(isatty(fileno(stdout))) bg_cmdline_print_help((*argv)[0], BG_HELP_FORMAT_TERM); else bg_cmdline_print_help((*argv)[0], BG_HELP_FORMAT_PLAIN); exit(0); } static void opt_help_man(void * data, int * argc, char *** argv, int arg) { bg_cmdline_print_help((*argv)[0], BG_HELP_FORMAT_MAN); exit(0); } static void opt_help_texi(void * data, int * argc, char *** argv, int arg) { bg_cmdline_print_help((*argv)[0], BG_HELP_FORMAT_TEXI); exit(0); } static void opt_version(void * data, int * argc, char *** argv, int arg) { print_version(app_data); exit(0); } /* */ void bg_cmdline_remove_arg(int * argc, char *** _argv, int arg) { char ** argv = *_argv; /* Move the upper args down */ if(arg < *argc - 1) memmove(argv + arg, argv + arg + 1, (*argc - arg - 1) * sizeof(*argv)); (*argc)--; } static void cmdline_parse(const bg_cmdline_arg_t * args, int * argc, char *** _argv, void * callback_data, int parse_auto) { int found; int i, j; char ** argv = *_argv; i = 1; if(parse_auto) { cmdline_parse(auto_options, argc, _argv, NULL, 0); } if(!args) return; while(i < *argc) { j = 0; found = 0; if(!strcmp(argv[i], "--")) break; while(args[j].arg) { if(!strcmp(args[j].arg, argv[i])) { bg_cmdline_remove_arg(argc, _argv, i); if(args[j].callback) args[j].callback(callback_data, argc, _argv, i); else if(args[j].parameters) { } found = 1; break; } else j++; } if(!found) i++; } } void bg_cmdline_parse(bg_cmdline_arg_t * args, int * argc, char *** _argv, void * callback_data) { cmdline_parse(args, argc, _argv, callback_data, 1); } char ** bg_cmdline_get_locations_from_args(int * argc, char *** _argv) { char ** ret; int seen_dashdash; char ** argv; int i, index; int num_locations = 0; argv = *_argv; /* Count the locations */ for(i = 1; i < *argc; i++) { if(!strcmp(argv[i], "--")) { num_locations += *argc - 1 - i; break; } else if(argv[i][0] != '-') num_locations++; } if(!num_locations) return NULL; /* Allocate return value */ ret = calloc(num_locations + 1, sizeof(*ret)); i = 1; index = 0; seen_dashdash = 0; while(i < *argc) { if(seen_dashdash || (argv[i][0] != '-')) { ret[index++] = argv[i]; bg_cmdline_remove_arg(argc, _argv, i); } else if(!strcmp(argv[i], "--")) { seen_dashdash = 1; bg_cmdline_remove_arg(argc, _argv, i); } else { i++; } } return ret; } int bg_cmdline_apply_options(bg_cfg_section_t * section, bg_set_parameter_func_t set_parameter, void * data, const bg_parameter_info_t * parameters, const char * option_string) { if(!bg_cfg_section_set_parameters_from_string(section, parameters, option_string)) return 0; /* Now, apply the section */ if(set_parameter) bg_cfg_section_apply(section, parameters, set_parameter, data); return 1; } static void print_help_parameters(int indent, const bg_parameter_info_t * parameters, bg_help_format_t format) { int i = 0; int j; FILE * out = stdout; int pos; char time_string[GAVL_TIME_STRING_LEN]; char * tmp_string; const char * translation_domain = NULL; indent += 2; if(format == BG_HELP_FORMAT_MAN) fprintf(out, ".RS 2\n"); else if(format == BG_HELP_FORMAT_TEXI) fprintf(out, "@table @r\n"); if(!indent) { do_indent(out, indent+2, format); fprintf(out, TR("Supported options:\n\n")); } while(parameters[i].name) { if(parameters[i].gettext_domain) translation_domain = parameters[i].gettext_domain; if(parameters[i].gettext_directory) bg_bindtextdomain(translation_domain, parameters[i].gettext_directory); if((parameters[i].type == BG_PARAMETER_SECTION) || (parameters[i].flags & BG_PARAMETER_HIDE_DIALOG)) { i++; continue; } pos = 0; if(format == BG_HELP_FORMAT_MAN) { do_indent(out, indent+2, format); fprintf(out, ".BR "); // pos += fprintf(out, spaces); // pos += fprintf(out, " "); if(parameters[i].opt) { fprintf(out, "%s", parameters[i].opt); pos += strlen(parameters[i].opt); } else { fprintf(out, "%s", parameters[i].name); pos += strlen(parameters[i].name); } fprintf(out, " \"="); } else if(format == BG_HELP_FORMAT_TEXI) { fprintf(out, "@item "); pos += indent+2; if(parameters[i].opt) { print_bold(out, parameters[i].opt, format); pos += strlen(parameters[i].opt); } else { print_bold(out, parameters[i].name, format); pos += strlen(parameters[i].name); } fprintf(out, "="); } else { do_indent(out, indent+2, format); pos += indent+2; if(parameters[i].opt) { print_bold(out, parameters[i].opt, format); pos += strlen(parameters[i].opt); } else { print_bold(out, parameters[i].name, format); pos += strlen(parameters[i].name); } fprintf(out, "="); } switch(parameters[i].type) { case BG_PARAMETER_SECTION: case BG_PARAMETER_BUTTON: break; case BG_PARAMETER_CHECKBUTTON: tmp_string = bg_sprintf(TR("[1|0] (default: %d)"), parameters[i].val_default.val_i); print_string(out, tmp_string, format); free(tmp_string); if(format == BG_HELP_FORMAT_MAN) fprintf(out, "\""); print_linebreak(out, format); break; case BG_PARAMETER_INT: case BG_PARAMETER_SLIDER_INT: pos += fprintf(out, TR(" (")); if(parameters[i].val_min.val_i < parameters[i].val_max.val_i) { pos += fprintf(out, "%d..%d, ", parameters[i].val_min.val_i, parameters[i].val_max.val_i); } fprintf(out, TR("default: %d)"), parameters[i].val_default.val_i); if(format == BG_HELP_FORMAT_MAN) fprintf(out, "\""); print_linebreak(out, format); break; case BG_PARAMETER_SLIDER_FLOAT: case BG_PARAMETER_FLOAT: pos += fprintf(out, TR(" (")); if(parameters[i].val_min.val_f < parameters[i].val_max.val_f) { tmp_string = bg_sprintf("%%.%df..%%.%df, ", parameters[i].num_digits, parameters[i].num_digits); pos += fprintf(out, tmp_string, parameters[i].val_min.val_f, parameters[i].val_max.val_f); free(tmp_string); } tmp_string = bg_sprintf(TR("default: %%.%df)"), parameters[i].num_digits); fprintf(out, tmp_string, parameters[i].val_default.val_f); free(tmp_string); if(format == BG_HELP_FORMAT_MAN) fprintf(out, "\""); print_linebreak(out, format); break; case BG_PARAMETER_STRING: case BG_PARAMETER_FONT: case BG_PARAMETER_DEVICE: case BG_PARAMETER_FILE: case BG_PARAMETER_DIRECTORY: pos += fprintf(out, TR("")); if(parameters[i].val_default.val_str) { tmp_string = bg_sprintf(TR(" (Default: %s)"), parameters[i].val_default.val_str); print_string(out, tmp_string, format); free(tmp_string); } if(format == BG_HELP_FORMAT_MAN) fprintf(out, "\""); print_linebreak(out, format); break; case BG_PARAMETER_STRING_HIDDEN: pos += fprintf(out, TR("")); if(format == BG_HELP_FORMAT_MAN) fprintf(out, "\""); print_linebreak(out, format); break; case BG_PARAMETER_STRINGLIST: pos += fprintf(out, TR("")); if(format == BG_HELP_FORMAT_MAN) fprintf(out, "\""); print_linebreak(out, format); j = 0; pos = 0; do_indent(out, indent+2, format); pos += indent+2; pos += fprintf(out, TR("Supported strings: ")); while(parameters[i].multi_names[j]) { if(j) pos += fprintf(out, " "); if(pos + strlen(parameters[i].multi_names[j]+1) > MAX_COLS) { if((format == BG_HELP_FORMAT_TERM) || (format == BG_HELP_FORMAT_PLAIN)) fprintf(out, "\n"); pos = 0; do_indent(out, indent+2, format); pos += indent+2; } pos += fprintf(out, "%s", parameters[i].multi_names[j]); j++; } print_linebreak(out, format); do_indent(out, indent+2, format); pos += indent+2; tmp_string = bg_sprintf(TR("Default: %s"), parameters[i].val_default.val_str); print_string(out, tmp_string, format); free(tmp_string); print_linebreak(out, format); break; case BG_PARAMETER_COLOR_RGB: fprintf(out, TR(",, (default: %.3f,%.3f,%.3f)"), parameters[i].val_default.val_color[0], parameters[i].val_default.val_color[1], parameters[i].val_default.val_color[2]); if(format == BG_HELP_FORMAT_MAN) fprintf(out, "\""); print_linebreak(out, format); do_indent(out, indent+2, format); pos += indent+2; fprintf(out, TR(", and are in the range 0.0..1.0")); if(format != BG_HELP_FORMAT_MAN) fprintf(out, "\n"); else fprintf(out, "\n.P\n"); break; case BG_PARAMETER_COLOR_RGBA: fprintf(out, TR(",,, (default: %.3f,%.3f,%.3f,%.3f)"), parameters[i].val_default.val_color[0], parameters[i].val_default.val_color[1], parameters[i].val_default.val_color[2], parameters[i].val_default.val_color[3]); if(format == BG_HELP_FORMAT_MAN) fprintf(out, "\""); print_linebreak(out, format); do_indent(out, indent+2, format); pos += indent+2; fprintf(out, TR(", , and are in the range 0.0..1.0")); if(format != BG_HELP_FORMAT_MAN) fprintf(out, "\n"); else fprintf(out, "\n.P\n"); break; case BG_PARAMETER_MULTI_MENU: print_string(out, TR("option[{suboptions}]"), format); if(format == BG_HELP_FORMAT_MAN) fprintf(out, "\""); print_linebreak(out, format); pos = 0; do_indent(out, indent+2, format); pos += indent+2; pos += fprintf(out, TR("Supported options: ")); j = 0; if(parameters[i].multi_names) { while(parameters[i].multi_names[j]) { if(j) pos += fprintf(out, " "); if(pos + strlen(parameters[i].multi_names[j]) > MAX_COLS) { if(format != BG_HELP_FORMAT_MAN) fprintf(out, "\n"); pos = 0; do_indent(out, indent+2, format); pos += indent+2; } pos += fprintf(out, "%s", parameters[i].multi_names[j]); j++; } } else pos += fprintf(out, TR("")); print_linebreak(out, format); do_indent(out, indent+2, format); pos += indent+2; fprintf(out, TR("Default: %s"), parameters[i].val_default.val_str); print_linebreak(out, format); break; case BG_PARAMETER_MULTI_LIST: case BG_PARAMETER_MULTI_CHAIN: print_string(out, TR("{option[{suboptions}][:option[{suboptions}]...]}"), format); if(format == BG_HELP_FORMAT_MAN) fprintf(out, "\""); print_linebreak(out, format); pos = 0; do_indent(out, indent+2, format); pos += indent+2; pos += fprintf(out, TR("Supported options: ")); j = 0; while(parameters[i].multi_names[j]) { if(j) pos += fprintf(out, " "); if(pos + strlen(parameters[i].multi_names[j]+1) > MAX_COLS) { fprintf(out, "\n"); pos = 0; do_indent(out, indent+4, format); pos += indent+4; } pos += fprintf(out, "%s", parameters[i].multi_names[j]); j++; } fprintf(out, "\n\n"); break; case BG_PARAMETER_TIME: print_string(out, TR("{[[HH:]MM:]SS} ("), format); if(parameters[i].val_min.val_time < parameters[i].val_max.val_time) { gavl_time_prettyprint(parameters[i].val_min.val_time, time_string); fprintf(out, "%s..", time_string); gavl_time_prettyprint(parameters[i].val_max.val_time, time_string); fprintf(out, "%s, ", time_string); } gavl_time_prettyprint(parameters[i].val_default.val_time, time_string); fprintf(out, TR("default: %s)"), time_string); if(format == BG_HELP_FORMAT_MAN) fprintf(out, "\""); print_linebreak(out, format); do_indent(out, indent+2, format); pos += indent+2; fprintf(out, TR("Seconds can be fractional (i.e. with decimal point)\n")); break; case BG_PARAMETER_POSITION: fprintf(out, TR(", (default: %.3f,%.3f)"), parameters[i].val_default.val_pos[0], parameters[i].val_default.val_pos[1]); if(format == BG_HELP_FORMAT_MAN) fprintf(out, "\""); print_linebreak(out, format); do_indent(out, indent+2, format); pos += indent+2; fprintf(out, TR(", and are in the range 0.0..1.0")); if(format != BG_HELP_FORMAT_MAN) fprintf(out, "\n"); else fprintf(out, "\n.P\n"); break; } do_indent(out, indent+2, format); pos += indent+2; fprintf(out, "%s", TR_DOM(parameters[i].long_name)); print_linebreak(out, format); if(parameters[i].help_string) { dump_string_term(out, parameters[i].help_string, indent, translation_domain, format); print_linebreak(out, format); } /* Print suboptions */ if(parameters[i].multi_parameters) { j = 0; while(parameters[i].multi_names[j]) { if(parameters[i].multi_parameters[j]) { do_indent(out, indent+2, format); pos += indent+2; // print_linebreak(out, format); if(parameters[i].type == BG_PARAMETER_MULTI_MENU) { if(parameters[i].opt) tmp_string = bg_sprintf(TR("Suboptions for %s=%s"), parameters[i].opt,parameters[i].multi_names[j]); else tmp_string = bg_sprintf(TR("Suboptions for %s=%s"), parameters[i].name,parameters[i].multi_names[j]); } else { tmp_string = bg_sprintf(TR("Suboptions for %s"), parameters[i].multi_names[j]); } print_bold(out, tmp_string, format); free(tmp_string); print_linebreak(out, format); // print_linebreak(out, format); // print_linebreak(out, format); print_help_parameters(indent+2, parameters[i].multi_parameters[j], format); } j++; } } i++; } if(format == BG_HELP_FORMAT_MAN) fprintf(out, ".RE\n"); else if(format == BG_HELP_FORMAT_TEXI) fprintf(out, "@end table\n"); } void bg_cmdline_print_help_parameters(const bg_parameter_info_t * parameters, bg_help_format_t format) { print_help_parameters(0, parameters, format); } void bg_cmdline_init(const bg_cmdline_app_data_t * data) { app_data = data; } gmerlin-1.2.0~dfsg/lib/x11/0000755000175000017500000000000011764363441015261 5ustar alessioalessiogmerlin-1.2.0~dfsg/lib/x11/Makefile.am0000644000175000017500000000143511764363410017314 0ustar alessioalessioplugindir=$(pkglibdir)/plugins INCLUDES = -I$(top_srcdir)/include AM_CFLAGS = \ @X_CFLAGS@ \ -DLOCALE_DIR=\"$(localedir)\" \ -DPLUGIN_DIR=\"$(plugindir)\" \ -DDOC_DIR=\"$(docdir)\" \ -DDATA_DIR=\"$(pkgdatadir)\" if HAVE_XV xv_sources = xvideo.c xv_libs = @XV_LIBS@ else xv_sources = xv_libs = endif if HAVE_GLX glx_sources = glvideo.c glx_libs = @GL_LIBS@ else glx_sources = glx_libs = endif if HAVE_XTEST xtest_libs = @XTEST_LIBS@ else xtest_libs = endif noinst_LTLIBRARIES = \ libx11.la libx11_la_SOURCES = \ grab.c \ icon.c \ shm.c \ x11_event.c \ x11_gl.c \ x11_video.c \ x11_window.c \ overlay.c \ screensaver.c \ ximage.c \ $(glx_sources) \ $(xv_sources) libx11_la_LIBADD = @GMERLIN_DEP_LIBS@ @XINERAMA_LIBS@ @XFIXES_LIBS@ @XDPMS_LIBS@ $(xv_libs) $(glx_libs) $(xtest_libs) @X_LIBS@ gmerlin-1.2.0~dfsg/lib/x11/icon.c0000644000175000017500000001613711764363410016361 0ustar alessioalessio/***************************************************************** * gmerlin - a general purpose multimedia framework and applications * * Copyright (c) 2001 - 2011 Members of the Gmerlin project * gmerlin-general@lists.sourceforge.net * http://gmerlin.sourceforge.net * * 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 of the License, 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 this program. If not, see . * *****************************************************************/ #include #include /* Warning: These functions are not optimized and not intended to be used very often */ static Pixmap make_icon(bg_x11_window_t * win, const gavl_video_frame_t * icon, const gavl_video_format_t * format) { XImage * im; gavl_video_format_t out_format; gavl_video_converter_t * cnv; gavl_video_options_t * opt; int do_convert; const gavl_video_frame_t * image_frame; gavl_video_frame_t * out_frame; Pixmap ret; /* Create converter */ cnv = gavl_video_converter_create(); opt = gavl_video_converter_get_options(cnv); gavl_video_options_set_alpha_mode(opt, GAVL_ALPHA_IGNORE); /* Create pixmap */ ret = XCreatePixmap(win->dpy, win->root, format->image_width, format->image_height, win->depth); /* Set up format and converter */ gavl_video_format_copy(&out_format, format); out_format.pixelformat = bg_x11_window_get_pixelformat(win->dpy, win->visual, win->depth); do_convert = gavl_video_converter_init(cnv, format, &out_format); if(do_convert) { out_frame = gavl_video_frame_create(&out_format); image_frame = out_frame; gavl_video_convert(cnv, icon, out_frame); } else { image_frame = icon; out_frame = NULL; } /* Make image */ im = XCreateImage(win->dpy, win->visual, win->depth, ZPixmap, 0, (char*)(image_frame->planes[0]), format->image_width, format->image_height, 32, image_frame->strides[0]); XPutImage(win->dpy, /* dpy */ ret, /* d */ win->gc, /* gc */ im, /* image */ 0, /* src_x */ 0, /* src_y */ 0, /* dst_x */ 0, /* dst_y */ format->image_width, /* src_width */ format->image_height); /* src_height */ /* Cleanup */ gavl_video_converter_destroy(cnv); if(out_frame) gavl_video_frame_destroy(out_frame); im->data = NULL; XDestroyImage(im); /* Return */ return ret; } static void create_mask_8(gavl_video_format_t * format, gavl_video_frame_t * frame, char * im, int bytes_per_line) { int i, j; uint8_t * ptr; uint8_t * im_ptr; int shift; for(i = 0; i < format->image_height; i++) { ptr = frame->planes[0] + i * frame->strides[0]; im_ptr = (uint8_t*)(im + i * bytes_per_line); shift = 0; for(j = 0; j < format->image_width; j++) { if(*ptr >= 0x80) *im_ptr |= 1 << shift; if(shift == 7) { im_ptr++; shift = 0; } else shift++; ptr++; } } } static void create_mask_16(gavl_video_format_t * format, gavl_video_frame_t * frame, char * im, int bytes_per_line) { int i, j; uint16_t * ptr; uint8_t * im_ptr; int shift; for(i = 0; i < format->image_height; i++) { ptr = (uint16_t*)(frame->planes[0] + i * frame->strides[0]); im_ptr = (uint8_t*)(im + i * bytes_per_line); shift = 0; for(j = 0; j < format->image_width; j++) { if(*ptr >= 0x8000) *im_ptr |= 1 << shift; if(shift == 7) { im_ptr++; shift = 0; } else shift++; ptr++; } } } static void create_mask_float(gavl_video_format_t * format, gavl_video_frame_t * frame, char * im, int bytes_per_line) { int i, j; float * ptr; uint8_t * im_ptr; int shift; for(i = 0; i < format->image_height; i++) { ptr = (float*)(frame->planes[0] + i * frame->strides[0]); im_ptr = (uint8_t*)(im + i * bytes_per_line); shift = 0; for(j = 0; j < format->image_width; j++) { if(*ptr >= 0.5) *im_ptr |= 1 << shift; if(shift == 7) { im_ptr++; shift = 0; } else shift++; ptr++; } } } static Pixmap make_mask(bg_x11_window_t * win, const gavl_video_frame_t * icon, const gavl_video_format_t * format) { gavl_video_frame_t * alpha_frame; gavl_video_format_t alpha_format; char * image_data; Pixmap ret; int bytes_per_line; /* Extract alpha */ if(!gavl_get_color_channel_format(format, &alpha_format, GAVL_CCH_ALPHA)) return None; /* No alpha */ alpha_frame = gavl_video_frame_create(&alpha_format); gavl_video_frame_extract_channel(format, GAVL_CCH_ALPHA, icon, alpha_frame); /* Create image */ bytes_per_line = (format->image_width + 7) / 8; image_data = calloc(1, bytes_per_line * format->image_height); switch(alpha_format.pixelformat) { case GAVL_GRAY_8: create_mask_8(&alpha_format, alpha_frame, image_data, bytes_per_line); break; case GAVL_GRAY_16: create_mask_16(&alpha_format, alpha_frame, image_data, bytes_per_line); break; case GAVL_GRAY_FLOAT: create_mask_float(&alpha_format, alpha_frame, image_data, bytes_per_line); break; default: break; } ret = XCreateBitmapFromData(win->dpy, win->root, image_data, format->image_width, format->image_height); gavl_video_frame_destroy(alpha_frame); free(image_data); return ret; } void bg_x11_window_make_icon(bg_x11_window_t * win, const gavl_video_frame_t * icon, const gavl_video_format_t * format, Pixmap * icon_ret, Pixmap * mask_ret) { if(icon_ret) *icon_ret = make_icon(win, icon, format); if(mask_ret) *mask_ret = make_mask(win, icon, format); } gmerlin-1.2.0~dfsg/lib/x11/x11_event.c0000644000175000017500000010033411764363410017234 0ustar alessioalessio/***************************************************************** * gmerlin - a general purpose multimedia framework and applications * * Copyright (c) 2001 - 2011 Members of the Gmerlin project * gmerlin-general@lists.sourceforge.net * http://gmerlin.sourceforge.net * * 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 of the License, 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 this program. If not, see . * *****************************************************************/ #include #include #include #include #include #include #define IDLE_MAX 50 #define STATE_IGNORE ~(Mod2Mask) static const struct { KeySym x11; int bg; } keycodes[] = { { XK_0, BG_KEY_0 }, { XK_1, BG_KEY_1 }, { XK_2, BG_KEY_2 }, { XK_3, BG_KEY_3 }, { XK_4, BG_KEY_4 }, { XK_5, BG_KEY_5 }, { XK_6, BG_KEY_6 }, { XK_7, BG_KEY_7 }, { XK_8, BG_KEY_8 }, { XK_9, BG_KEY_9 }, { XK_space, BG_KEY_SPACE }, { XK_Return, BG_KEY_RETURN }, { XK_Left, BG_KEY_LEFT }, { XK_Right, BG_KEY_RIGHT }, { XK_Up, BG_KEY_UP }, { XK_Down, BG_KEY_DOWN }, { XK_Page_Up, BG_KEY_PAGE_UP }, { XK_Page_Down, BG_KEY_PAGE_DOWN }, { XK_Home, BG_KEY_HOME }, { XK_plus, BG_KEY_PLUS }, { XK_minus, BG_KEY_MINUS }, { XK_Tab, BG_KEY_TAB }, { XK_Escape, BG_KEY_ESCAPE }, { XK_Menu, BG_KEY_MENU }, { XK_question, BG_KEY_QUESTION }, //!< ? { XK_exclam, BG_KEY_EXCLAM }, //!< ! { XK_quotedbl, BG_KEY_QUOTEDBL, }, //!< " { XK_dollar, BG_KEY_DOLLAR, }, //!< $ { XK_percent, BG_KEY_PERCENT, }, //!< % { XK_ampersand, BG_KEY_APMERSAND, }, //!< & { XK_slash, BG_KEY_SLASH, }, //!< / { XK_parenleft, BG_KEY_LEFTPAREN, }, //!< ( { XK_parenright, BG_KEY_RIGHTPAREN, }, //!< ) { XK_equal, BG_KEY_EQUAL, }, //!< = { XK_backslash, BG_KEY_BACKSLASH, }, //!< :-) { XK_a, BG_KEY_a }, { XK_b, BG_KEY_b }, { XK_c, BG_KEY_c }, { XK_d, BG_KEY_d }, { XK_e, BG_KEY_e }, { XK_f, BG_KEY_f }, { XK_g, BG_KEY_g }, { XK_h, BG_KEY_h }, { XK_i, BG_KEY_i }, { XK_j, BG_KEY_j }, { XK_k, BG_KEY_k }, { XK_l, BG_KEY_l }, { XK_m, BG_KEY_m }, { XK_n, BG_KEY_n }, { XK_o, BG_KEY_o }, { XK_p, BG_KEY_p }, { XK_q, BG_KEY_q }, { XK_r, BG_KEY_r }, { XK_s, BG_KEY_s }, { XK_t, BG_KEY_t }, { XK_u, BG_KEY_u }, { XK_v, BG_KEY_v }, { XK_w, BG_KEY_w }, { XK_x, BG_KEY_x }, { XK_y, BG_KEY_y }, { XK_z, BG_KEY_z }, { XK_A, BG_KEY_A }, { XK_B, BG_KEY_B }, { XK_C, BG_KEY_C }, { XK_D, BG_KEY_D }, { XK_E, BG_KEY_E }, { XK_F, BG_KEY_F }, { XK_G, BG_KEY_G }, { XK_H, BG_KEY_H }, { XK_I, BG_KEY_I }, { XK_J, BG_KEY_J }, { XK_K, BG_KEY_K }, { XK_L, BG_KEY_L }, { XK_M, BG_KEY_M }, { XK_N, BG_KEY_N }, { XK_O, BG_KEY_O }, { XK_P, BG_KEY_P }, { XK_Q, BG_KEY_Q }, { XK_R, BG_KEY_R }, { XK_S, BG_KEY_S }, { XK_T, BG_KEY_T }, { XK_U, BG_KEY_U }, { XK_V, BG_KEY_V }, { XK_W, BG_KEY_W }, { XK_X, BG_KEY_X }, { XK_Y, BG_KEY_Y }, { XK_Z, BG_KEY_Z }, { XK_F1, BG_KEY_F1 }, { XK_F2, BG_KEY_F2 }, { XK_F3, BG_KEY_F3 }, { XK_F4, BG_KEY_F4 }, { XK_F5, BG_KEY_F5 }, { XK_F6, BG_KEY_F6 }, { XK_F7, BG_KEY_F7 }, { XK_F8, BG_KEY_F8 }, { XK_F9, BG_KEY_F9 }, { XK_F10, BG_KEY_F10 }, { XK_F11, BG_KEY_F11 }, { XK_F12, BG_KEY_F12 }, }; static int keysym_to_key_code(KeySym x11) { int i; for(i = 0; i < sizeof(keycodes)/sizeof(keycodes[0]); i++) { if(x11 == keycodes[i].x11) return keycodes[i].bg; } return BG_KEY_NONE; } static KeySym key_code_to_keysym(int bg_code) { int i; for(i = 0; i < sizeof(keycodes)/sizeof(keycodes[0]); i++) { if(bg_code == keycodes[i].bg) return keycodes[i].x11; } return XK_VoidSymbol; } static int x11_to_key_mask(int x11_mask) { int ret = 0; if(x11_mask & ShiftMask) ret |= BG_KEY_SHIFT_MASK; if(x11_mask & ControlMask) ret |= BG_KEY_CONTROL_MASK; if(x11_mask & Mod1Mask) ret |= BG_KEY_ALT_MASK; if(x11_mask & Mod4Mask) ret |= BG_KEY_SUPER_MASK; if(x11_mask & Button1Mask) ret |= BG_KEY_BUTTON1_MASK; if(x11_mask & Button2Mask) ret |= BG_KEY_BUTTON2_MASK; if(x11_mask & Button3Mask) ret |= BG_KEY_BUTTON3_MASK; if(x11_mask & Button4Mask) ret |= BG_KEY_BUTTON4_MASK; if(x11_mask & Button5Mask) ret |= BG_KEY_BUTTON5_MASK; return ret; } #if 1 static int key_mask_to_xembed(int bg_mask) { int ret = 0; if(bg_mask & BG_KEY_SHIFT_MASK) ret |= XEMBED_MODIFIER_SHIFT; if(bg_mask & BG_KEY_CONTROL_MASK) ret |= XEMBED_MODIFIER_CONTROL; if(bg_mask & BG_KEY_ALT_MASK) ret |= XEMBED_MODIFIER_ALT; if(bg_mask & BG_KEY_SUPER_MASK) ret |= XEMBED_MODIFIER_SUPER; // XEMBED_MODIFIER_HYPER ?? return ret; } #endif static int xembed_to_key_mask(int xembed_mask) { int ret = 0; if(xembed_mask & XEMBED_MODIFIER_SHIFT) ret |= BG_KEY_SHIFT_MASK; if(xembed_mask & XEMBED_MODIFIER_CONTROL) ret |= BG_KEY_CONTROL_MASK; if(xembed_mask & XEMBED_MODIFIER_ALT) ret |= BG_KEY_ALT_MASK; if(xembed_mask & XEMBED_MODIFIER_SUPER) ret |= BG_KEY_SUPER_MASK; // XEMBED_MODIFIER_HYPER ?? return ret; } static int x11_window_next_event(bg_x11_window_t * w, XEvent * evt, int milliseconds) { int fd; struct timeval timeout; fd_set read_fds; if(milliseconds < 0) /* Block */ { XNextEvent(w->dpy, evt); return 1; } else if(!milliseconds) { if(!XPending(w->dpy)) return 0; else { XNextEvent(w->dpy, evt); return 1; } } else /* Use timeout */ { fd = ConnectionNumber(w->dpy); FD_ZERO (&read_fds); FD_SET (fd, &read_fds); timeout.tv_sec = milliseconds / 1000; timeout.tv_usec = 1000 * (milliseconds % 1000); if(!select(fd+1, &read_fds, NULL,NULL,&timeout)) return 0; else { XNextEvent(w->dpy, evt); return 1; } } } static int window_is_mapped(Display * dpy, Window w) { XWindowAttributes attr; if(w == None) return 0; XGetWindowAttributes(dpy, w, &attr); if(attr.map_state != IsUnmapped) return 1; return 0; } static int window_is_viewable(Display * dpy, Window w) { XWindowAttributes attr; if(w == None) return 0; XGetWindowAttributes(dpy, w, &attr); if(attr.map_state == IsViewable) return 1; return 0; } static void register_xembed_accelerators(bg_x11_window_t * w, window_t * win) { int i; const bg_accelerator_t * accels; if(!w->callbacks || !w->callbacks->accel_map) return; accels = bg_accelerator_map_get_accels(w->callbacks->accel_map); i = 0; while(accels[i].key != BG_KEY_NONE) { bg_x11_window_send_xembed_message(w, win->parent, CurrentTime, XEMBED_REGISTER_ACCELERATOR, accels[i].id, key_code_to_keysym(accels[i].key), key_mask_to_xembed(accels[i].mask)); i++; } } #if 0 static void unregister_xembed_accelerators(bg_x11_window_t * w, window_t * win) { int i; const bg_accelerator_t * accels; if(!w->callbacks || !w->callbacks->accel_map) return; accels = bg_accelerator_map_get_accels(w->callbacks->accel_map); i = 0; while(accels[i].key != BG_KEY_NONE) { bg_x11_window_send_xembed_message(w, win->win, CurrentTime, XEMBED_UNREGISTER_ACCELERATOR, accels[i].id, 0, 0); i++; } } #endif /* Transform coordinates if we playback video */ static void transform_coords(bg_x11_window_t * w, int x_raw, int y_raw, int * x_ret, int * y_ret) { double coord_norm; if(!w->video_open) { *x_ret = x_raw; *y_ret = y_raw; } else { coord_norm = (double)(x_raw - w->dst_rect.x) / w->dst_rect.w; *x_ret = (int)(w->src_rect.x + coord_norm * w->src_rect.w + 0.5); coord_norm = (double)(y_raw - w->dst_rect.y) / w->dst_rect.h; *y_ret = (int)(w->src_rect.y + coord_norm * w->src_rect.h + 0.5); } } void bg_x11_window_handle_event(bg_x11_window_t * w, XEvent * evt) { KeySym keysym; char key_char; int key_code; int key_mask; int accel_id; int button_number = 0; window_t * cur; int x_src, y_src; w->do_delete = 0; if(!evt || (evt->type != MotionNotify)) { w->idle_counter++; if(w->idle_counter >= IDLE_MAX) { if(!w->pointer_hidden) { if(w->current->child == None) XDefineCursor(w->dpy, w->current->win, w->fullscreen_cursor); XFlush(w->dpy); w->pointer_hidden = 1; } w->idle_counter = 0; } } bg_x11_screensaver_ping(&w->scr); if(w->need_focus && window_is_viewable(w->dpy, w->current->focus_child)) { XSetInputFocus(w->dpy, w->current->focus_child, RevertToParent, w->focus_time); w->need_focus = 0; } if(w->need_fullscreen && window_is_viewable(w->dpy, w->fullscreen.win)) { bg_x11_window_set_fullscreen_mapped(w, &w->fullscreen); w->need_fullscreen = 0; } if(!evt) return; if(evt->type == w->shm_completion_type) { w->wait_for_completion = 0; return; } switch(evt->type) { case Expose: if(w->still_mode && w->still_frame) bg_x11_window_put_frame_internal(w, w->still_frame); break; case PropertyNotify: if(evt->xproperty.atom == w->_XEMBED_INFO) { if(evt->xproperty.window == w->normal.child) { bg_x11_window_check_embed_property(w, &w->normal); } else if(evt->xproperty.window == w->fullscreen.child) { bg_x11_window_check_embed_property(w, &w->fullscreen); } } break; case ClientMessage: if(evt->xclient.message_type == w->WM_PROTOCOLS) { if(evt->xclient.data.l[0] == w->WM_DELETE_WINDOW) { w->do_delete = 1; return; } else if(evt->xclient.data.l[0] == w->WM_TAKE_FOCUS) { int result; if(window_is_viewable(w->dpy, w->current->focus_child)) result = XSetInputFocus(w->dpy, w->current->focus_child, RevertToParent, evt->xclient.data.l[1]); else { w->need_focus = 1; w->focus_time = evt->xclient.data.l[1]; result = 0; } } } if(evt->xclient.message_type == w->_XEMBED) { if((evt->xclient.window == w->normal.win) || (evt->xclient.window == w->normal.child)) cur = &w->normal; else if((evt->xclient.window == w->fullscreen.win) || (evt->xclient.window == w->fullscreen.child)) cur = &w->fullscreen; else return; switch(evt->xclient.data.l[1]) { /* XEMBED messages */ case XEMBED_EMBEDDED_NOTIFY: if(evt->xclient.window == cur->win) { cur->parent_xembed = 1; /* * In gtk this isn't necessary, didn't try other * toolkits. Strange that this is sometimes called with * None as parent window, so we're better off ignoring this here */ // fprintf(stderr, "XEMBED_EMBEDDED_NOTIFY %08lx %08lx\n", // cur->parent, evt->xclient.data.l[3]); // cur->parent = evt->xclient.data.l[3]; if(window_is_mapped(w->dpy, cur->parent)) { unsigned long buffer[2]; buffer[0] = 0; // Version buffer[1] = XEMBED_MAPPED; XChangeProperty(w->dpy, cur->win, w->_XEMBED_INFO, w->_XEMBED_INFO, 32, PropModeReplace, (unsigned char *)buffer, 2); XSync(w->dpy, False); } /* Register our accelerators */ register_xembed_accelerators(w, cur); } break; case XEMBED_WINDOW_ACTIVATE: if((evt->xclient.window == cur->win) && (cur->child_xembed)) { /* Redirect to child */ bg_x11_window_send_xembed_message(w, cur->child, XEMBED_WINDOW_ACTIVATE, evt->xclient.data.l[0], 0, 0, 0); } break; case XEMBED_WINDOW_DEACTIVATE: if((evt->xclient.window == cur->win) && (cur->child_xembed)) { /* Redirect to child */ bg_x11_window_send_xembed_message(w, cur->child, XEMBED_WINDOW_DEACTIVATE, evt->xclient.data.l[0], 0, 0, 0); } break; case XEMBED_REQUEST_FOCUS: break; case XEMBED_FOCUS_IN: if((evt->xclient.window == cur->win) && (cur->child_xembed)) { /* Redirect to child */ bg_x11_window_send_xembed_message(w, cur->child, evt->xclient.data.l[0], XEMBED_FOCUS_IN, evt->xclient.data.l[2], 0, 0); } break; case XEMBED_FOCUS_OUT: if((evt->xclient.window == cur->win) && (cur->child_xembed)) { /* Redirect to child */ bg_x11_window_send_xembed_message(w, cur->child, evt->xclient.data.l[0], XEMBED_FOCUS_OUT, 0, 0, 0); } break; case XEMBED_FOCUS_NEXT: break; case XEMBED_FOCUS_PREV: /* 8-9 were used for XEMBED_GRAB_KEY/XEMBED_UNGRAB_KEY */ break; case XEMBED_MODALITY_ON: if((evt->xclient.window == cur->win) && (cur->child_xembed)) { /* Redirect to child */ bg_x11_window_send_xembed_message(w, cur->child, evt->xclient.data.l[0], XEMBED_MODALITY_ON, 0, 0, 0); } cur->modality = 1; break; case XEMBED_MODALITY_OFF: if((evt->xclient.window == cur->win) && (cur->child_xembed)) { /* Redirect to child */ bg_x11_window_send_xembed_message(w, cur->child, evt->xclient.data.l[0], XEMBED_MODALITY_OFF, 0, 0, 0); } cur->modality = 0; break; case XEMBED_REGISTER_ACCELERATOR: /* Don't process our own accelerators */ /* Child wants to register an accelerator */ /* detail accelerator_id data1 X key symbol data2 bit field of modifier values */ if(!cur->parent_xembed) { /* Add to out accel map */ bg_accelerator_map_append(cur->child_accel_map, keysym_to_key_code(evt->xclient.data.l[3]), xembed_to_key_mask(evt->xclient.data.l[4]), evt->xclient.data.l[2]); } else { /* Propagate */ bg_x11_window_send_xembed_message(w, cur->parent, evt->xclient.data.l[0], XEMBED_REGISTER_ACCELERATOR, evt->xclient.data.l[2], evt->xclient.data.l[3], evt->xclient.data.l[4]); } // break; case XEMBED_UNREGISTER_ACCELERATOR: /* Child wants to unregister an accelerator */ if(!cur->parent_xembed) { /* Remove from our accel map */ bg_accelerator_map_remove(cur->child_accel_map, evt->xclient.data.l[2]); } else { /* Propagate */ bg_x11_window_send_xembed_message(w, cur->parent, evt->xclient.data.l[0], XEMBED_UNREGISTER_ACCELERATOR, evt->xclient.data.l[2], 0, 0); } break; case XEMBED_ACTIVATE_ACCELERATOR: /* Check if we have the accelerator */ // fprintf(stderr, "Activate accelerator\n"); if(w->callbacks && w->callbacks->accel_map && w->callbacks->accel_callback && bg_accelerator_map_has_accel_with_id(w->callbacks->accel_map, evt->xclient.data.l[2])) { w->callbacks->accel_callback(w->callbacks->data, evt->xclient.data.l[2]); return; } else { /* Propagate to child */ bg_x11_window_send_xembed_message(w, cur->parent, evt->xclient.data.l[0], XEMBED_ACTIVATE_ACCELERATOR, evt->xclient.data.l[2], evt->xclient.data.l[3], 0); } break; } return; } break; case CreateNotify: if(evt->xcreatewindow.parent == w->normal.win) cur = &w->normal; else if(evt->xcreatewindow.parent == w->fullscreen.win) cur = &w->fullscreen; else break; if((evt->xcreatewindow.window != cur->focus_child) && (evt->xcreatewindow.window != cur->subwin)) { cur->child = evt->xcreatewindow.window; fprintf(stderr, "Embed child %ld\n", evt->xcreatewindow.window); bg_x11_window_embed_child(w, cur); fprintf(stderr, "Embed child done\n"); } break; case DestroyNotify: if(evt->xdestroywindow.event == w->normal.win) cur = &w->normal; else if(evt->xdestroywindow.event == w->fullscreen.win) cur = &w->fullscreen; else break; if(evt->xdestroywindow.window == cur->child) { fprintf(stderr, "UnEmbed child\n"); cur->child = None; cur->child_xembed = 0; if(cur->child_accel_map) bg_accelerator_map_clear(cur->child_accel_map); fprintf(stderr, "Unembed child done\n"); } break; #if 0 case FocusIn: break; case FocusOut: break; #endif case ConfigureNotify: if(w->current->win == w->normal.win) { if(evt->xconfigure.window == w->normal.win) { w->window_width = evt->xconfigure.width; w->window_height = evt->xconfigure.height; if(w->normal.parent == w->root) { bg_x11_window_get_coords(w->dpy, w->normal.win, &w->window_x, &w->window_y, NULL, NULL); } bg_x11_window_size_changed(w); if(w->normal.subwin != None) { XResizeWindow(w->dpy, w->normal.subwin, evt->xconfigure.width, evt->xconfigure.height); } } else if(evt->xconfigure.window == w->normal.parent) { XResizeWindow(w->dpy, w->normal.win, evt->xconfigure.width, evt->xconfigure.height); } } else { if(evt->xconfigure.window == w->fullscreen.win) { w->window_width = evt->xconfigure.width; w->window_height = evt->xconfigure.height; bg_x11_window_size_changed(w); if(w->fullscreen.subwin != None) { XResizeWindow(w->dpy, w->fullscreen.subwin, evt->xconfigure.width, evt->xconfigure.height); } } else if(evt->xconfigure.window == w->fullscreen.parent) { XResizeWindow(w->dpy, w->fullscreen.win, evt->xconfigure.width, evt->xconfigure.height); } } break; case MotionNotify: /* Check if we had a fake motion event from the screensaver */ if(w->scr.fake_motion > 0) { w->scr.fake_motion--; return; } w->idle_counter = 0; if(w->pointer_hidden) { XDefineCursor(w->dpy, w->normal.win, None); XDefineCursor(w->dpy, w->fullscreen.win, None); XFlush(w->dpy); w->pointer_hidden = 0; } if((evt->xmotion.window == w->normal.win) || (evt->xmotion.window == w->normal.subwin)) cur = &w->normal; else if((evt->xmotion.window == w->fullscreen.win) || (evt->xmotion.window == w->fullscreen.subwin)) cur = &w->fullscreen; else return; if(cur->modality) return; transform_coords(w, evt->xmotion.x, evt->xmotion.y, &x_src, &y_src); if(w->callbacks && w->callbacks->motion_callback) { key_mask = x11_to_key_mask(evt->xmotion.state); w->callbacks->motion_callback(w->callbacks->data, x_src, y_src, key_mask); } break; case UnmapNotify: if(evt->xunmap.window == w->normal.win) w->normal.mapped = 0; else if(evt->xunmap.window == w->fullscreen.win) w->fullscreen.mapped = 0; else if(evt->xunmap.window == w->fullscreen.toplevel) bg_x11_window_init(w); break; case MapNotify: if(evt->xmap.window == w->normal.win) { w->normal.mapped = 1; /* Kindly ask for keyboard focus */ if(w->normal.parent_xembed) bg_x11_window_send_xembed_message(w, w->normal.parent, CurrentTime, XEMBED_REQUEST_FOCUS, 0, 0, 0); XDefineCursor(w->dpy, w->normal.win, None); w->idle_counter = 0; w->pointer_hidden = 0; } else if(evt->xmap.window == w->fullscreen.win) { w->fullscreen.mapped = 1; /* Kindly ask for keyboard focus */ if(w->fullscreen.parent_xembed) bg_x11_window_send_xembed_message(w, w->fullscreen.parent, CurrentTime, XEMBED_REQUEST_FOCUS, 0, 0, 0); XDefineCursor(w->dpy, w->fullscreen.win, None); w->idle_counter = 0; w->pointer_hidden = 0; // bg_x11_window_set_fullscreen_mapped(w, &w->fullscreen); } else if(evt->xmap.window == w->fullscreen.toplevel) { bg_x11_window_init(w); bg_x11_window_show(w, 1); } break; case KeyPress: case KeyRelease: XLookupString(&evt->xkey, &key_char, 1, &keysym, NULL); evt->xkey.state &= STATE_IGNORE; if((evt->xkey.window == w->normal.win) || (evt->xkey.window == w->normal.focus_child) || (evt->xkey.window == w->normal.subwin)) cur = &w->normal; else if((evt->xkey.window == w->fullscreen.win) || (evt->xkey.window == w->fullscreen.focus_child) || (evt->xkey.window == w->fullscreen.subwin)) cur = &w->fullscreen; else { return; } key_code = keysym_to_key_code(keysym); key_mask = x11_to_key_mask(evt->xkey.state); if(key_code != BG_KEY_NONE) { if(evt->type == KeyPress) { /* Try if it's our accel */ if(w->callbacks && w->callbacks->accel_callback && w->callbacks->accel_map && bg_accelerator_map_has_accel(w->callbacks->accel_map, key_code, key_mask, &accel_id) && w->callbacks->accel_callback(w->callbacks->data, accel_id)) return; /* Check if the child wants tht shortcut */ if(cur->child_accel_map && cur->child && cur->child_xembed && bg_accelerator_map_has_accel(cur->child_accel_map, key_code, key_mask, &accel_id)) { bg_x11_window_send_xembed_message(w, cur->child, evt->xkey.time, XEMBED_ACTIVATE_ACCELERATOR, accel_id, 0, 0); return; } /* Here, we see why generic key callbacks are bad: One key callback is ok, but if we have more than one (i.e. in embedded or embedding windows), one might always eat up all events. At least callbacks should return zero to notify, that the event should be propagated */ if(w->callbacks && w->callbacks->key_callback && w->callbacks->key_callback(w->callbacks->data, key_code, key_mask)) return; } else // KeyRelease { if(w->callbacks && w->callbacks->key_release_callback && w->callbacks->key_release_callback(w->callbacks->data, key_code, key_mask)) return; } } if(cur->child != None) { XKeyEvent key_event; /* Send event to child window */ memset(&key_event, 0, sizeof(key_event)); key_event.display = w->dpy; key_event.window = cur->child; key_event.root = w->root; key_event.subwindow = None; key_event.time = evt->xkey.time; key_event.x = 0; key_event.y = 0; key_event.x_root = 0; key_event.y_root = 0; key_event.same_screen = True; key_event.type = evt->type; key_event.keycode = evt->xkey.keycode; key_event.state = evt->xkey.state; XSendEvent(key_event.display, key_event.window, False, NoEventMask, (XEvent *)(&key_event)); XFlush(w->dpy); } break; case ButtonPress: case ButtonRelease: if((evt->xbutton.window == w->normal.win) || (evt->xbutton.window == w->normal.subwin)) cur = &w->normal; else if((evt->xbutton.window == w->fullscreen.win) || (evt->xbutton.window == w->fullscreen.subwin)) cur = &w->fullscreen; else return; if(cur->modality) return; transform_coords(w, evt->xbutton.x, evt->xbutton.y, &x_src, &y_src); evt->xkey.state &= STATE_IGNORE; if(w->callbacks) { switch(evt->xbutton.button) { case Button1: button_number = 1; break; case Button2: button_number = 2; break; case Button3: button_number = 3; break; case Button4: button_number = 4; break; case Button5: button_number = 5; break; } if(w->callbacks->button_callback && (evt->type == ButtonPress)) w->callbacks->button_callback(w->callbacks->data, x_src, y_src, button_number, x11_to_key_mask(evt->xbutton.state)); else if(w->callbacks->button_release_callback && (evt->type == ButtonRelease)) w->callbacks->button_release_callback(w->callbacks->data, x_src, y_src, button_number, x11_to_key_mask(evt->xbutton.state)); } /* Also send to parent */ if(w->current->parent != w->root) { XButtonEvent button_event; memset(&button_event, 0, sizeof(button_event)); button_event.type = evt->type; button_event.display = w->dpy; button_event.window = w->current->parent; button_event.root = w->root; button_event.time = CurrentTime; button_event.x = evt->xbutton.x; button_event.y = evt->xbutton.y; button_event.x_root = evt->xbutton.x_root; button_event.y_root = evt->xbutton.y_root; button_event.state = evt->xbutton.state; button_event.button = evt->xbutton.button; button_event.same_screen = evt->xbutton.same_screen; XSendEvent(button_event.display, button_event.window, False, NoEventMask, (XEvent *)(&button_event)); // XFlush(w->dpy); } } } void bg_x11_window_handle_events(bg_x11_window_t * win, int milliseconds) { XEvent evt; if(win->wait_for_completion) { while(win->wait_for_completion) { x11_window_next_event(win, &evt, -1); bg_x11_window_handle_event(win, &evt); } } else { while(1) { if(!x11_window_next_event(win, &evt, milliseconds)) { /* Still need to hide the mouse cursor and ping the screensaver */ bg_x11_window_handle_event(win, NULL); return; } bg_x11_window_handle_event(win, &evt); } } } gmerlin-1.2.0~dfsg/lib/x11/x11_window.c0000644000175000017500000013131011764363410017420 0ustar alessioalessio/***************************************************************** * gmerlin - a general purpose multimedia framework and applications * * Copyright (c) 2001 - 2011 Members of the Gmerlin project * gmerlin-general@lists.sourceforge.net * http://gmerlin.sourceforge.net * * 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 of the License, 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 this program. If not, see . * *****************************************************************/ #include #include #include #include #include #include #include #include #include #include #define LOG_DOMAIN "x11" #include #include #ifdef HAVE_GLX #include #endif #define _NET_WM_STATE_REMOVE 0 /* remove/unset property */ #define _NET_WM_STATE_ADD 1 /* add/set property */ // #define FULLSCREEN_MODE_OLD 0 #define FULLSCREEN_MODE_NET_FULLSCREEN (1<<0) #define FULLSCREEN_MODE_NET_ABOVE (1<<1) #define FULLSCREEN_MODE_NET_STAYS_ON_TOP (1<<2) #define FULLSCREEN_MODE_WIN_LAYER (1<<2) #define HAVE_XSHM static char bm_no_data[] = { 0,0,0,0, 0,0,0,0 }; /* since it doesn't seem to be defined on some platforms */ int XShmGetEventBase (Display *); /* Screensaver detection */ static int check_disable_screensaver(bg_x11_window_t * w) { if(!w->current) return 0; /* Never change global settings if we are embedded */ if(w->current->parent != w->root) return 0; if(!w->is_fullscreen) return w->disable_screensaver_normal; else return w->disable_screensaver_fullscreen; } void bg_x11_window_ping_screensaver(bg_x11_window_t * w) { } static int wm_check_capability(Display *dpy, Window root, Atom list, Atom wanted) { Atom type; int format; unsigned int i; unsigned long nitems, bytesafter; unsigned char *args; unsigned long *ldata; int retval = 0; if (Success != XGetWindowProperty (dpy, root, list, 0, 16384, False, AnyPropertyType, &type, &format, &nitems, &bytesafter, &args)) return 0; if (type != XA_ATOM) return 0; ldata = (unsigned long*)args; for (i = 0; i < nitems; i++) { if (ldata[i] == wanted) retval = 1; } XFree(ldata); return retval; } void bg_x11_window_set_netwm_state(Display * dpy, Window win, Window root, int action, Atom state) { /* Setting _NET_WM_STATE by XSendEvent works only, if the window is already mapped!! */ XEvent e; memset(&e,0,sizeof(e)); e.xclient.type = ClientMessage; e.xclient.message_type = XInternAtom(dpy, "_NET_WM_STATE", False); e.xclient.window = win; e.xclient.send_event = True; e.xclient.format = 32; e.xclient.data.l[0] = action; e.xclient.data.l[1] = state; XSendEvent(dpy, root, False, SubstructureRedirectMask | SubstructureNotifyMask, &e); } static int get_fullscreen_mode(bg_x11_window_t * w) { int ret = 0; Atom type; int format; unsigned int i; unsigned long nitems, bytesafter; unsigned char *args; unsigned long *ldata; if (Success != XGetWindowProperty (w->dpy, w->root, w->_NET_SUPPORTED, 0, (65536 / sizeof(long)), False, AnyPropertyType, &type, &format, &nitems, &bytesafter, &args)) return 0; if (type != XA_ATOM) return 0; ldata = (unsigned long*)args; for (i = 0; i < nitems; i++) { if (ldata[i] == w->_NET_WM_STATE_FULLSCREEN) { ret |= FULLSCREEN_MODE_NET_FULLSCREEN; } if (ldata[i] == w->_NET_WM_STATE_ABOVE) { ret |= FULLSCREEN_MODE_NET_ABOVE; } if (ldata[i] == w->_NET_WM_STATE_STAYS_ON_TOP) { ret |= FULLSCREEN_MODE_NET_STAYS_ON_TOP; } } XFree(ldata); if(wm_check_capability(w->dpy, w->root, w->WIN_PROTOCOLS, w->WIN_LAYER)) { ret |= FULLSCREEN_MODE_WIN_LAYER; } return ret; } #define INIT_ATOM(a) w->a = XInternAtom(w->dpy, #a, False); static void init_atoms(bg_x11_window_t * w) { INIT_ATOM(WM_DELETE_WINDOW); INIT_ATOM(WM_TAKE_FOCUS); INIT_ATOM(WIN_PROTOCOLS); INIT_ATOM(WM_PROTOCOLS); INIT_ATOM(WIN_LAYER); INIT_ATOM(_NET_SUPPORTED); INIT_ATOM(_NET_WM_STATE); INIT_ATOM(_NET_WM_STATE_FULLSCREEN); INIT_ATOM(_NET_WM_STATE_ABOVE); INIT_ATOM(_NET_WM_STATE_STAYS_ON_TOP); INIT_ATOM(_NET_MOVERESIZE_WINDOW); INIT_ATOM(_XEMBED_INFO); INIT_ATOM(_XEMBED); INIT_ATOM(WM_CLASS); INIT_ATOM(STRING); } void bg_x11_window_set_fullscreen_mapped(bg_x11_window_t * win, window_t * w) { if(win->fullscreen_mode & FULLSCREEN_MODE_NET_ABOVE) { bg_x11_window_set_netwm_state(win->dpy, w->win, win->root, _NET_WM_STATE_ADD, win->_NET_WM_STATE_ABOVE); } else if(win->fullscreen_mode & FULLSCREEN_MODE_NET_STAYS_ON_TOP) { bg_x11_window_set_netwm_state(win->dpy, w->win, win->root, _NET_WM_STATE_ADD, win->_NET_WM_STATE_STAYS_ON_TOP); } if(win->fullscreen_mode & FULLSCREEN_MODE_NET_FULLSCREEN) { bg_x11_window_set_netwm_state(win->dpy, w->win, win->root, _NET_WM_STATE_ADD, win->_NET_WM_STATE_FULLSCREEN); } } static void show_window(bg_x11_window_t * win, window_t * w, int show) { unsigned long buffer[2]; if(!w) return; if(!show) { if(w->win == None) return; if(w->win == w->toplevel) { XUnmapWindow(win->dpy, w->win); XWithdrawWindow(win->dpy, w->win, DefaultScreen(win->dpy)); } else if(w->parent_xembed) { buffer[0] = 0; // Version buffer[1] = 0; XChangeProperty(win->dpy, w->win, win->_XEMBED_INFO, win->_XEMBED_INFO, 32, PropModeReplace, (unsigned char *)buffer, 2); return; } else XUnmapWindow(win->dpy, w->win); XSync(win->dpy, False); return; } /* Do it the XEMBED way */ if(w->parent_xembed) { buffer[0] = 0; // Version buffer[1] = XEMBED_MAPPED; XChangeProperty(win->dpy, w->win, win->_XEMBED_INFO, win->_XEMBED_INFO, 32, PropModeReplace, (unsigned char *)buffer, 2); return; } /* If the window was already mapped, raise it */ if(w->mapped) XRaiseWindow(win->dpy, w->win); else XMapWindow(win->dpy, w->win); if(w->win == w->toplevel) { if(!w->fullscreen) XMoveResizeWindow(win->dpy, w->win, win->window_x, win->window_y, win->window_width, win->window_height); } } void bg_x11_window_clear(bg_x11_window_t * win) { // XSetForeground(win->dpy, win->gc, win->black); // XFillRectangle(win->dpy, win->normal_window, win->gc, 0, 0, win->window_width, // win->window_height); if(win->normal.win != None) XClearArea(win->dpy, win->normal.win, 0, 0, win->window_width, win->window_height, True); if(win->fullscreen.win != None) XClearArea(win->dpy, win->fullscreen.win, 0, 0, win->window_width, win->window_height, True); // XSync(win->dpy, False); } /* MWM decorations */ #define MWM_HINTS_DECORATIONS (1L << 1) #define MWM_HINTS_FUNCTIONS (1L << 0) #define MWM_FUNC_ALL (1L<<0) #define PROP_MOTIF_WM_HINTS_ELEMENTS 5 typedef struct { CARD32 flags; CARD32 functions; CARD32 decorations; INT32 inputMode; CARD32 status; } PropMotifWmHints; static int mwm_set_decorations(bg_x11_window_t * w, Window win, int set) { PropMotifWmHints motif_hints; Atom hintsatom; /* setup the property */ motif_hints.flags = MWM_HINTS_DECORATIONS | MWM_HINTS_FUNCTIONS; motif_hints.decorations = set; motif_hints.functions = set ? MWM_FUNC_ALL : 0; /* get the atom for the property */ hintsatom = XInternAtom(w->dpy, "_MOTIF_WM_HINTS", False); XChangeProperty(w->dpy, win, hintsatom, hintsatom, 32, PropModeReplace, (unsigned char *) &motif_hints, PROP_MOTIF_WM_HINTS_ELEMENTS); return 1; } static void set_fullscreen(bg_x11_window_t * w, Window win) { if(w->fullscreen_mode & FULLSCREEN_MODE_NET_FULLSCREEN) { } else mwm_set_decorations(w, win, 0); } static void set_min_size(bg_x11_window_t * w, Window win, int width, int height) { XSizeHints * h; h = XAllocSizeHints(); h->flags = PMinSize; h->min_width = width; h->min_height = height; XSetWMNormalHints(w->dpy, win, h); XFree(h); } static int open_display(bg_x11_window_t * w) { char * normal_id; char * fullscreen_id; #ifdef HAVE_LIBXINERAMA int foo,bar; #endif /* * Display string is in the form * :: * It can be NULL. Also, can be missing */ if(!w->display_string_parent) { w->dpy = XOpenDisplay(NULL); if(!w->dpy) return 0; w->normal.parent = None; w->fullscreen.parent = None; } else { fullscreen_id = strrchr(w->display_string_parent, ':'); if(!fullscreen_id) { return 0; } *fullscreen_id = '\0'; fullscreen_id++; normal_id = strrchr(w->display_string_parent, ':'); if(!normal_id) { return 0; } *normal_id = '\0'; normal_id++; w->dpy = XOpenDisplay(w->display_string_parent); if(!w->dpy) return 0; w->normal.parent = strtoul(normal_id, NULL, 16); if(!(*fullscreen_id)) w->fullscreen.parent = None; else w->fullscreen.parent = strtoul(fullscreen_id, NULL, 16); // fprintf(stderr, "Initialized windows: %ld %ld\n", // w->normal.parent, w->fullscreen.parent); } w->screen = DefaultScreen(w->dpy); w->root = RootWindow(w->dpy, w->screen); if(w->normal.parent == None) w->normal.parent = w->root; if(w->fullscreen.parent == None) w->fullscreen.parent = w->root; w->normal.child = None; w->fullscreen.child = None; init_atoms(w); /* Check, which fullscreen modes we have */ w->fullscreen_mode = get_fullscreen_mode(w); bg_x11_screensaver_init(&w->scr, w->dpy); /* Get xinerama screens */ #ifdef HAVE_LIBXINERAMA if (XineramaQueryExtension(w->dpy,&foo,&bar) && XineramaIsActive(w->dpy)) { w->xinerama = XineramaQueryScreens(w->dpy,&w->nxinerama); } #endif /* Check for XShm */ w->have_shm = bg_x11_window_check_shm(w->dpy, &w->shm_completion_type); return 1; } void bg_x11_window_get_coords(Display * dpy, Window win, int * x, int * y, int * width, int * height) { Window root_return; Window parent_return; Window * children_return; unsigned int nchildren_return; int x_return, y_return; unsigned int width_return, height_return; unsigned int border_width_return; unsigned int depth_return; // Window child_return; XGetGeometry(dpy, win, &root_return, &x_return, &y_return, &width_return, &height_return, &border_width_return, &depth_return); XQueryTree(dpy, win, &root_return, &parent_return, &children_return, &nchildren_return); if(nchildren_return) XFree(children_return); if(x) *x = x_return; if(y) *y = y_return; if(width) *width = width_return; if(height) *height = height_return; if((x || y) && (parent_return != root_return)) { XGetGeometry(dpy, parent_return, &root_return, &x_return, &y_return, &width_return, &height_return, &border_width_return, &depth_return); if(x) *x = x_return; if(y) *y = y_return; } } static int window_is_viewable(Display * dpy, Window w) { XWindowAttributes attr; if(w == None) return 0; XGetWindowAttributes(dpy, w, &attr); if(attr.map_state == IsViewable) return 1; return 0; } void bg_x11_window_size_changed(bg_x11_window_t * w) { /* Frame size remains unchanged, to let set_rectangles find out, if the image must be reallocated */ /* Nothing changed actually. */ if((w->window_format.image_width == w->window_width) && (w->window_format.image_height == w->window_height)) return; w->window_format.image_width = w->window_width; w->window_format.image_height = w->window_height; if(w->callbacks && w->callbacks->size_changed) w->callbacks->size_changed(w->callbacks->data, w->window_width, w->window_height); } void bg_x11_window_init(bg_x11_window_t * w) { int send_event = -1; /* Decide current window */ if((w->fullscreen.parent != w->root) && window_is_viewable(w->dpy, w->fullscreen.parent)) { // fprintf(stderr, "Is fullscreen\n"); if(!w->is_fullscreen) send_event = 1; w->current = &w->fullscreen; w->is_fullscreen = 1; } else { if(w->is_fullscreen) send_event = 0; w->current = &w->normal; w->is_fullscreen = 0; } #if 1 if(w->current->parent != w->root) { // fprintf(stderr, "bg_x11_window_init %ld %ld\n", w->current->win, // w->current->parent); bg_x11_window_get_coords(w->dpy, w->current->parent, NULL, NULL, &w->window_width, &w->window_height); XMoveResizeWindow(w->dpy, w->current->win, 0, 0, w->window_width, w->window_height); } else bg_x11_window_get_coords(w->dpy, w->current->win, NULL, NULL, &w->window_width, &w->window_height); #endif // fprintf(stderr, "Window size: %dx%d\n", w->window_width, w->window_height); if((send_event >= 0) && w->callbacks && w->callbacks->set_fullscreen) w->callbacks->set_fullscreen(w->callbacks->data, send_event); bg_x11_window_size_changed(w); } void bg_x11_window_embed_parent(bg_x11_window_t * win, window_t * w) { unsigned long buffer[2]; buffer[0] = 0; // Version buffer[1] = 0; // XMapWindow(dpy, child); XChangeProperty(win->dpy, w->win, win->_XEMBED_INFO, win->_XEMBED_INFO, 32, PropModeReplace, (unsigned char *)buffer, 2); w->toplevel = bg_x11_window_get_toplevel(win, w->parent); /* We need StructureNotify of both the toplevel and the parent */ XSelectInput(win->dpy, w->parent, StructureNotifyMask); if(w->parent != w->toplevel) XSelectInput(win->dpy, w->toplevel, StructureNotifyMask); XSync(win->dpy, False); } void bg_x11_window_embed_child(bg_x11_window_t * win, window_t * w) { XSelectInput(win->dpy, w->child, FocusChangeMask | ExposureMask | PropertyChangeMask); /* Define back the cursor */ XDefineCursor(win->dpy, w->win, None); win->pointer_hidden = 0; bg_x11_window_check_embed_property(win, w); } static void create_subwin(bg_x11_window_t * w, window_t * win, int depth, Visual * v, unsigned long attr_mask, XSetWindowAttributes * attr) { int width, height; bg_x11_window_get_coords(w->dpy, win->win, NULL, NULL, &width, &height); win->subwin = XCreateWindow(w->dpy, win->win, 0, 0, width, height, 0, depth, InputOutput, v, attr_mask, attr); XMapWindow(w->dpy, win->subwin); } void bg_x11_window_create_subwins(bg_x11_window_t * w, int depth, Visual * v) { unsigned long attr_mask; XSetWindowAttributes attr; w->sub_colormap = XCreateColormap(w->dpy, RootWindow(w->dpy, w->screen), v, AllocNone); memset(&attr, 0, sizeof(attr)); attr_mask = CWEventMask | CWColormap; attr.event_mask = ExposureMask | ButtonPressMask | ButtonReleaseMask | KeyPressMask | PointerMotionMask | KeyReleaseMask; attr.colormap = w->sub_colormap; create_subwin(w, &w->normal, depth, v, attr_mask, &attr); create_subwin(w, &w->fullscreen, depth, v, attr_mask, &attr); } static void destroy_subwin(bg_x11_window_t * w, window_t * win) { if(win->subwin != None) { XDestroyWindow(w->dpy, win->subwin); win->subwin = None; } } void bg_x11_window_destroy_subwins(bg_x11_window_t * w) { destroy_subwin(w, &w->normal); destroy_subwin(w, &w->fullscreen); } static int create_window(bg_x11_window_t * w, int width, int height) { const char * display_name; unsigned long event_mask; XColor black; Atom wm_protocols[2]; XWMHints * wmhints; // int i; /* Stuff for making the cursor */ XSetWindowAttributes attr; unsigned long attr_flags; if((!w->dpy) && !open_display(w)) return 0; wmhints = XAllocWMHints(); wmhints->input = True; wmhints->initial_state = NormalState; wmhints->flags |= InputHint|StateHint; /* Creating windows without colormap results in a BadMatch error */ w->colormap = XCreateColormap(w->dpy, RootWindow(w->dpy, w->screen), w->visual, AllocNone); /* Setup event mask */ event_mask = StructureNotifyMask | PointerMotionMask | ExposureMask | ButtonPressMask | ButtonReleaseMask | PropertyChangeMask | KeyPressMask | KeyReleaseMask | FocusChangeMask; /* Create normal window */ memset(&attr, 0, sizeof(attr)); attr.backing_store = NotUseful; attr.border_pixel = 0; attr.background_pixel = 0; attr.event_mask = event_mask; attr.colormap = w->colormap; attr_flags = (CWBackingStore | CWEventMask | CWBorderPixel | CWBackPixel | CWColormap); wm_protocols[0] = w->WM_DELETE_WINDOW; wm_protocols[1] = w->WM_TAKE_FOCUS; /* Create normal window */ w->normal.win = XCreateWindow(w->dpy, w->normal.parent, 0 /* x */, 0 /* y */, width, height, 0 /* border_width */, w->depth, InputOutput, w->visual, attr_flags, &attr); if(w->normal.parent == w->root) { // set_decorations(w, w->normal.win, 1); XSetWMProtocols(w->dpy, w->normal.win, wm_protocols, 2); if(w->min_width && w->min_height) set_min_size(w, w->normal.win, w->min_width, w->min_height); w->normal.toplevel = w->normal.win; w->normal.focus_child = XCreateSimpleWindow(w->dpy, w->normal.win, -1, -1, 1, 1, 0, 0, 0); XSelectInput(w->dpy, w->normal.focus_child, KeyPressMask | KeyReleaseMask | FocusChangeMask); XSetWMHints(w->dpy, w->normal.win, wmhints); XMapWindow(w->dpy, w->normal.focus_child); w->normal.child_accel_map = bg_accelerator_map_create(); } else bg_x11_window_embed_parent(w, &w->normal); /* The fullscreen window will be created with the same size for now */ w->fullscreen.win = XCreateWindow (w->dpy, w->fullscreen.parent, 0 /* x */, 0 /* y */, width, height, 0 /* border_width */, w->depth, InputOutput, w->visual, attr_flags, &attr); w->fullscreen.fullscreen = 1; if(w->fullscreen.parent == w->root) { /* Setup protocols */ set_fullscreen(w, w->fullscreen.win); XSetWMProtocols(w->dpy, w->fullscreen.win, wm_protocols, 2); w->fullscreen.toplevel = w->fullscreen.win; #if 0 w->fullscreen.focus_child = XCreateWindow(w->dpy, w->fullscreen.win, 0, 0, width, height, 0, 0, InputOnly, vi->visual, attr_flags_input_only, &attr); #endif w->fullscreen.focus_child = XCreateSimpleWindow(w->dpy, w->fullscreen.win, -1, -1, 1, 1, 0, 0, 0); XSelectInput(w->dpy, w->fullscreen.focus_child, KeyPressMask | KeyReleaseMask | FocusChangeMask); XSetWMHints(w->dpy, w->fullscreen.win, wmhints); XMapWindow(w->dpy, w->fullscreen.focus_child); w->fullscreen.child_accel_map = bg_accelerator_map_create(); } else { bg_x11_window_embed_parent(w, &w->fullscreen); } /* Set the final event masks now. We blocked SubstructureNotifyMask * before because we don't want our focus children as * embeded clients.. */ XSync(w->dpy, False); XSelectInput(w->dpy, w->normal.win, event_mask | SubstructureNotifyMask); XSelectInput(w->dpy, w->fullscreen.win, event_mask | SubstructureNotifyMask); /* Create GC */ w->gc = XCreateGC(w->dpy, w->normal.win, 0, NULL); /* Create colormap and fullscreen cursor */ w->fullscreen_cursor_pixmap = XCreateBitmapFromData(w->dpy, w->fullscreen.win, bm_no_data, 8, 8); black.pixel = BlackPixel(w->dpy, w->screen); XQueryColor(w->dpy, DefaultColormap(w->dpy, w->screen), &black); w->fullscreen_cursor= XCreatePixmapCursor(w->dpy, w->fullscreen_cursor_pixmap, w->fullscreen_cursor_pixmap, &black, &black, 0, 0); w->black = BlackPixel(w->dpy, w->screen); display_name = XDisplayName(DisplayString(w->dpy)); XFree(wmhints); /* Determine if we are in fullscreen mode */ bg_x11_window_init(w); return 1; } static void get_fullscreen_coords(bg_x11_window_t * w, int * x, int * y, int * width, int * height) { #ifdef HAVE_LIBXINERAMA int x_return, y_return; int i; Window child; /* Get the coordinates of the normal window */ *x = 0; *y = 0; *width = DisplayWidth(w->dpy, w->screen); *height = DisplayHeight(w->dpy, w->screen); if(w->nxinerama) { XTranslateCoordinates(w->dpy, w->normal.win, w->root, 0, 0, &x_return, &y_return, &child); /* Get the xinerama screen we are on */ for(i = 0; i < w->nxinerama; i++) { if((x_return >= w->xinerama[i].x_org) && (y_return >= w->xinerama[i].y_org) && (x_return < w->xinerama[i].x_org + w->xinerama[i].width) && (y_return < w->xinerama[i].y_org + w->xinerama[i].height)) { *x = w->xinerama[i].x_org; *y = w->xinerama[i].y_org; *width = w->xinerama[i].width; *height = w->xinerama[i].height; break; } } } #else *x = 0; *y = 0; *width = DisplayWidth(w->dpy, w->screen); *height = DisplayHeight(w->dpy, w->screen); #endif } int bg_x11_window_set_fullscreen(bg_x11_window_t * w,int fullscreen) { int ret = 0; int width; int height; int x; int y; /* Return early if there is nothing to do */ if(!!fullscreen == !!w->is_fullscreen) return 0; /* Normal->fullscreen */ if(fullscreen) { if(w->normal.parent != w->root) return 0; get_fullscreen_coords(w, &x, &y, &width, &height); w->normal_width = w->window_width; w->normal_height = w->window_height; w->window_width = width; w->window_height = height; w->current = &w->fullscreen; w->is_fullscreen = 1; w->need_fullscreen = 1; bg_x11_window_show(w, 1); if(w->callbacks && w->callbacks->set_fullscreen) w->callbacks->set_fullscreen(w->callbacks->data, 1); bg_x11_window_clear(w); /* Hide old window */ if(w->normal.win == w->normal.toplevel) XWithdrawWindow(w->dpy, w->normal.toplevel, w->screen); XFlush(w->dpy); ret = 1; } else { if(w->fullscreen.parent != w->root) return 0; /* Unmap fullscreen window */ #if 1 bg_x11_window_set_netwm_state(w->dpy, w->fullscreen.win, w->root, _NET_WM_STATE_REMOVE, w->_NET_WM_STATE_FULLSCREEN); bg_x11_window_set_netwm_state(w->dpy, w->fullscreen.win, w->root, _NET_WM_STATE_REMOVE, w->_NET_WM_STATE_ABOVE); XUnmapWindow(w->dpy, w->fullscreen.win); #endif XWithdrawWindow(w->dpy, w->fullscreen.win, w->screen); /* Map normal window */ w->current = &w->normal; w->is_fullscreen = 0; w->window_width = w->normal_width; w->window_height = w->normal_height; bg_x11_window_show(w, 1); if(w->callbacks && w->callbacks->set_fullscreen) w->callbacks->set_fullscreen(w->callbacks->data, 0); bg_x11_window_clear(w); XFlush(w->dpy); ret = 1; } if(ret) { if(check_disable_screensaver(w)) bg_x11_screensaver_disable(&w->scr); else bg_x11_screensaver_enable(&w->scr); } return ret; } void bg_x11_window_resize(bg_x11_window_t * win, int width, int height) { win->normal_width = width; win->normal_height = height; if(!win->is_fullscreen && (win->normal.parent == win->root)) { win->window_width = width; win->window_height = height; XResizeWindow(win->dpy, win->normal.win, width, height); } } void bg_x11_window_get_size(bg_x11_window_t * win, int * width, int * height) { *width = win->window_width; *height = win->window_height; } /* Public methods */ bg_x11_window_t * bg_x11_window_create(const char * display_string) { bg_x11_window_t * ret; ret = calloc(1, sizeof(*ret)); ret->display_string_parent = bg_strdup(ret->display_string_parent, display_string); ret->scaler = gavl_video_scaler_create(); /* Set default OpenGL attributes */ bg_x11_window_set_gl_attribute(ret, BG_GL_ATTRIBUTE_RGBA, 1); bg_x11_window_set_gl_attribute(ret, BG_GL_ATTRIBUTE_RED_SIZE, 8); bg_x11_window_set_gl_attribute(ret, BG_GL_ATTRIBUTE_GREEN_SIZE, 8); bg_x11_window_set_gl_attribute(ret, BG_GL_ATTRIBUTE_BLUE_SIZE, 8); bg_x11_window_set_gl_attribute(ret, BG_GL_ATTRIBUTE_DOUBLEBUFFER, 1); ret->icon = None; ret->icon_mask = None; return ret; } const char * bg_x11_window_get_display_string(bg_x11_window_t * w) { if(w->normal.win == None) create_window(w, w->window_width, w->window_height); if(!w->display_string_child) w->display_string_child = bg_sprintf("%s:%08lx:%08lx", XDisplayName(DisplayString(w->dpy)), w->normal.win, w->fullscreen.win); return w->display_string_child; } void bg_x11_window_destroy(bg_x11_window_t * w) { bg_x11_window_cleanup_video(w); bg_x11_window_cleanup_gl(w); bg_x11_window_destroy_subwins(w); if(w->colormap != None) XFreeColormap(w->dpy, w->colormap); if(w->normal.win != None) XDestroyWindow(w->dpy, w->normal.win); if(w->fullscreen.win != None) XDestroyWindow(w->dpy, w->fullscreen.win); if(w->fullscreen_cursor != None) XFreeCursor(w->dpy, w->fullscreen_cursor); if(w->fullscreen_cursor_pixmap != None) XFreePixmap(w->dpy, w->fullscreen_cursor_pixmap); if(w->gc != None) XFreeGC(w->dpy, w->gc); if(w->normal.child_accel_map) bg_accelerator_map_destroy(w->normal.child_accel_map); if(w->fullscreen.child_accel_map) bg_accelerator_map_destroy(w->fullscreen.child_accel_map); #ifdef HAVE_LIBXINERAMA if(w->xinerama) XFree(w->xinerama); #endif #ifdef GAVE_GLX if(w->gl_fbconfigs) XFree(w->gl_fbconfigs); #endif if(w->icon != None) XFreePixmap(w->dpy, w->icon); if(w->icon_mask != None) XFreePixmap(w->dpy, w->icon_mask); if(w->dpy) { XCloseDisplay(w->dpy); bg_x11_screensaver_cleanup(&w->scr); } if(w->display_string_parent) free(w->display_string_parent); if(w->display_string_child) free(w->display_string_child); if(w->scaler) gavl_video_scaler_destroy(w->scaler); free(w); } static const bg_parameter_info_t common_parameters[] = { { BG_LOCALE, .name = "window", .long_name = TRS("General"), }, { .name = "auto_resize", .long_name = TRS("Auto resize window"), .type = BG_PARAMETER_CHECKBUTTON, .val_default = { .val_i = 1 } }, { .name = "window_width", .long_name = "Window width", .type = BG_PARAMETER_INT, .flags = BG_PARAMETER_HIDE_DIALOG, .val_default = { .val_i = 320 } }, { .name = "window_height", .long_name = "Window height", .type = BG_PARAMETER_INT, .flags = BG_PARAMETER_HIDE_DIALOG, .val_default = { .val_i = 240 } }, { .name = "window_x", .long_name = "Window x", .type = BG_PARAMETER_INT, .flags = BG_PARAMETER_HIDE_DIALOG, .val_default = { .val_i = 100 } }, { .name = "window_y", .long_name = "Window y", .type = BG_PARAMETER_INT, .flags = BG_PARAMETER_HIDE_DIALOG, .val_default = { .val_i = 100 } }, { .name = "disable_xscreensaver_normal", .long_name = TRS("Disable Screensaver for normal playback"), .type = BG_PARAMETER_CHECKBUTTON, .val_default = { .val_i = 0 } }, { .name = "disable_xscreensaver_fullscreen", .long_name = TRS("Disable Screensaver for fullscreen playback"), .type = BG_PARAMETER_CHECKBUTTON, .val_default = { .val_i = 1 } }, { .name = "force_hw_scale", .long_name = TRS("Force hardware scaling"), .type = BG_PARAMETER_CHECKBUTTON, .val_default = { .val_i = 1 }, .help_string = TRS("Use hardware scaling even if it involves more CPU intensive pixelformat conversions"), }, #ifdef HAVE_GLX { .name = "background_color", .long_name = TRS("Background color"), .type = BG_PARAMETER_COLOR_RGB, .flags = BG_PARAMETER_SYNC, .help_string = TRS("Specify the background color for videos with alpha channel. This is only used by the OpenGL driver."), }, #endif { .name = "sw_scaler", .long_name = TRS("Software scaler"), .type = BG_PARAMETER_SECTION, }, { .name = "scale_mode", .long_name = TRS("Scale mode"), .type = BG_PARAMETER_STRINGLIST, .multi_names = (char const*[]){ "auto", "nearest", "bilinear", "quadratic", "cubic_bspline", "cubic_mitchell", "cubic_catmull", "sinc_lanczos", NULL }, .multi_labels = (char const*[]){ TRS("Auto"), TRS("Nearest"), TRS("Bilinear"), TRS("Quadratic"), TRS("Cubic B-Spline"), TRS("Cubic Mitchell-Netravali"), TRS("Cubic Catmull-Rom"), TRS("Sinc with Lanczos window"), NULL }, .val_default = { .val_str = "auto" }, .help_string = TRS("Choose scaling method. Auto means to choose based on the conversion quality. Nearest is fastest, Sinc with Lanczos window is slowest."), }, { .name = "scale_order", .long_name = TRS("Scale order"), .type = BG_PARAMETER_INT, .val_min = { .val_i = 4 }, .val_max = { .val_i = 1000 }, .val_default = { .val_i = 4 }, .help_string = TRS("Order for sinc scaling"), }, { .name = "scale_quality", .long_name = TRS("Scale quality"), .type = BG_PARAMETER_SLIDER_INT, .val_min = { .val_i = GAVL_QUALITY_FASTEST }, .val_max = { .val_i = GAVL_QUALITY_BEST }, .val_default = { .val_i = GAVL_QUALITY_DEFAULT }, .help_string = TRS("Scale quality"), }, { /* End of parameters */ }, }; const bg_parameter_info_t * bg_x11_window_get_parameters(bg_x11_window_t * win) { return common_parameters; } void bg_x11_window_set_parameter(void * data, const char * name, const bg_parameter_value_t * val) { gavl_scale_mode_t scale_mode = GAVL_SCALE_AUTO; gavl_video_options_t * opt; bg_x11_window_t * win; if(!name) return; win = (bg_x11_window_t *)data; if(!strcmp(name, "auto_resize")) { win->auto_resize = val->val_i; } else if(!strcmp(name, "window_x")) { if(win->normal.parent == win->root) win->window_x = val->val_i; } else if(!strcmp(name, "window_y")) { if(win->normal.parent == win->root) win->window_y = val->val_i; } else if(!strcmp(name, "window_width")) { if(win->normal.parent == win->root) win->window_width = val->val_i; } else if(!strcmp(name, "window_height")) { if(win->normal.parent == win->root) win->window_height = val->val_i; } else if(!strcmp(name, "disable_xscreensaver_normal")) { win->disable_screensaver_normal = val->val_i; } else if(!strcmp(name, "disable_xscreensaver_fullscreen")) { win->disable_screensaver_fullscreen = val->val_i; } #ifdef HAVE_GLX else if(!strcmp(name, "background_color")) { memcpy(win->background_color, val->val_color, 3 * sizeof(float)); } #endif else if(!strcmp(name, "force_hw_scale")) { win->force_hw_scale = val->val_i; } else if(!strcmp(name, "scale_mode")) { if(!strcmp(val->val_str, "auto")) scale_mode = GAVL_SCALE_AUTO; else if(!strcmp(val->val_str, "nearest")) scale_mode = GAVL_SCALE_NEAREST; else if(!strcmp(val->val_str, "bilinear")) scale_mode = GAVL_SCALE_BILINEAR; else if(!strcmp(val->val_str, "quadratic")) scale_mode = GAVL_SCALE_QUADRATIC; else if(!strcmp(val->val_str, "cubic_bspline")) scale_mode = GAVL_SCALE_CUBIC_BSPLINE; else if(!strcmp(val->val_str, "cubic_mitchell")) scale_mode = GAVL_SCALE_CUBIC_MITCHELL; else if(!strcmp(val->val_str, "cubic_catmull")) scale_mode = GAVL_SCALE_CUBIC_CATMULL; else if(!strcmp(val->val_str, "sinc_lanczos")) scale_mode = GAVL_SCALE_SINC_LANCZOS; opt = gavl_video_scaler_get_options(win->scaler); if(scale_mode != gavl_video_options_get_scale_mode(opt)) { win->scaler_options_changed = 1; gavl_video_options_set_scale_mode(opt, scale_mode); } } else if(!strcmp(name, "scale_order")) { opt = gavl_video_scaler_get_options(win->scaler); if(val->val_i != gavl_video_options_get_scale_order(opt)) { win->scaler_options_changed = 1; gavl_video_options_set_scale_order(opt, val->val_i); } } else if(!strcmp(name, "scale_quality")) { opt = gavl_video_scaler_get_options(win->scaler); if(val->val_i != gavl_video_options_get_quality(opt)) { win->scaler_options_changed = 1; gavl_video_options_set_quality(opt, val->val_i); } } } int bg_x11_window_get_parameter(void * data, const char * name, bg_parameter_value_t * val) { bg_x11_window_t * win; if(!name) return 0; win = (bg_x11_window_t *)data; if(!strcmp(name, "window_x")) { val->val_i = win->window_x; return 1; } else if(!strcmp(name, "window_y")) { val->val_i = win->window_y; return 1; } else if(!strcmp(name, "window_width")) { val->val_i = win->window_width; return 1; } else if(!strcmp(name, "window_height")) { val->val_i = win->window_height; return 1; } return 0; } void bg_x11_window_set_size(bg_x11_window_t * win, int width, int height) { win->window_width = width; win->window_height = height; } int bg_x11_window_realize(bg_x11_window_t * win) { int ret; if(!win->dpy && !open_display(win)) return 0; // #ifdef HAVE_GLX #if 0 win->gl_vi = glXChooseVisual(win->dpy, win->screen, attr_list); if(!win->gl_vi) { bg_log(BG_LOG_WARNING, LOG_DOMAIN, "Could not get GL Visual"); win->visual = DefaultVisual(win->dpy, win->screen); win->depth = DefaultDepth(win->dpy, win->screen); } else { win->visual = win->gl_vi->visual; win->depth = win->gl_vi->depth; } #endif win->visual = DefaultVisual(win->dpy, win->screen); win->depth = DefaultDepth(win->dpy, win->screen); bg_log(BG_LOG_DEBUG, LOG_DOMAIN, "Got Visual 0x%lx depth %d", win->visual->visualid, win->depth); ret = create_window(win, win->window_width, win->window_height); bg_x11_window_init_gl(win); return ret; } /* Handle X11 events, callbacks are called from here */ void bg_x11_window_set_callbacks(bg_x11_window_t * win, bg_x11_window_callbacks_t * callbacks) { win->callbacks = callbacks; } void bg_x11_window_set_title(bg_x11_window_t * w, const char * title) { if(w->normal.parent == w->root) XmbSetWMProperties(w->dpy, w->normal.win, title, title, NULL, 0, NULL, NULL, NULL); if(w->fullscreen.parent == w->root) XmbSetWMProperties(w->dpy, w->fullscreen.win, title, title, NULL, 0, NULL, NULL, NULL); } void bg_x11_window_set_options(bg_x11_window_t * w, const char * name, const char * klass, const gavl_video_frame_t * icon, const gavl_video_format_t * icon_format) { /* Set Class hints */ if(name && klass) { XClassHint xclasshint; /* const madness */ xclasshint.res_name = bg_strdup(NULL, name); xclasshint.res_class = bg_strdup(NULL, klass); if(w->normal.parent == w->root) XSetClassHint(w->dpy, w->normal.win, &xclasshint); if(w->fullscreen.parent == w->root) XSetClassHint(w->dpy, w->fullscreen.win, &xclasshint); free(xclasshint.res_name); free(xclasshint.res_class); } /* Set Icon (TODO) */ if(icon && icon_format) { XWMHints xwmhints; memset(&xwmhints, 0, sizeof(xwmhints)); if((w->normal.parent == w->root) || (w->fullscreen.parent == w->root)) { if(w->icon != None) { XFreePixmap(w->dpy, w->icon); w->icon = None; } if(w->icon_mask != None) { XFreePixmap(w->dpy, w->icon_mask); w->icon_mask = None; } bg_x11_window_make_icon(w, icon, icon_format, &w->icon, &w->icon_mask); xwmhints.icon_pixmap = w->icon; xwmhints.icon_mask = w->icon_mask; if(xwmhints.icon_pixmap != None) xwmhints.flags |= IconPixmapHint; if(xwmhints.icon_mask != None) xwmhints.flags |= IconMaskHint; if(w->normal.parent == w->root) XSetWMHints(w->dpy, w->normal.win, &xwmhints); if(w->fullscreen.parent == w->root) XSetWMHints(w->dpy, w->fullscreen.win, &xwmhints); } } } void bg_x11_window_show(bg_x11_window_t * win, int show) { show_window(win, win->current, show); if(show && check_disable_screensaver(win)) bg_x11_screensaver_disable(&win->scr); else bg_x11_screensaver_enable(&win->scr); if(!show) { XSync(win->dpy, False); bg_x11_window_handle_events(win, 0); } } Window bg_x11_window_get_toplevel(bg_x11_window_t * w, Window win) { Window *children_return; Window root_return; Window parent_return; Atom type_ret; int format_ret; unsigned long nitems_ret; unsigned long bytes_after_ret; unsigned char *prop_ret; unsigned int nchildren_return; while(1) { XGetWindowProperty(w->dpy, win, w->WM_CLASS, 0L, 0L, 0, w->STRING, &type_ret,&format_ret,&nitems_ret, &bytes_after_ret,&prop_ret); if(type_ret!=None) { XFree(prop_ret); return win; } XQueryTree(w->dpy, win, &root_return, &parent_return, &children_return, &nchildren_return); if(nchildren_return) XFree(children_return); if(parent_return == root_return) break; win = parent_return; } return win; } void bg_x11_window_send_xembed_message(bg_x11_window_t * w, Window win, long time, int message, int detail, int data1, int data2) { XClientMessageEvent xclient; xclient.window = win; xclient.type = ClientMessage; xclient.message_type = w->_XEMBED; xclient.format = 32; xclient.data.l[0] = time; xclient.data.l[1] = message; xclient.data.l[2] = detail; xclient.data.l[3] = data1; xclient.data.l[4] = data2; XSendEvent(w->dpy, win, False, NoEventMask, (XEvent *)&xclient); XSync(w->dpy, False); } int bg_x11_window_check_embed_property(bg_x11_window_t * win, window_t * w) { Atom type; int format; unsigned long nitems, bytes_after; unsigned char *data; unsigned long *data_long; int flags; if(XGetWindowProperty(win->dpy, w->child, win->_XEMBED_INFO, 0, 2, False, win->_XEMBED_INFO, &type, &format, &nitems, &bytes_after, &data) != Success) return 0; if (type == None) /* No info property */ return 0; if (type != win->_XEMBED_INFO) return 0; data_long = (unsigned long *)data; flags = data_long[1]; XFree(data); if(flags & XEMBED_MAPPED) { XMapWindow(win->dpy, w->child); XRaiseWindow(win->dpy, w->focus_child); } else { /* Window should not be mapped right now */ // XUnmapWindow(win->dpy, w->child); } if(!w->child_xembed) { w->child_xembed = 1; bg_x11_window_send_xembed_message(win, w->child, CurrentTime, XEMBED_EMBEDDED_NOTIFY, 0, w->win, 0); XFlush(win->dpy); } return 1; } gavl_pixelformat_t bg_x11_window_get_pixelformat(Display * dpy, Visual * visual, int depth) { int bpp; XPixmapFormatValues * pf; int i; int num_pf; gavl_pixelformat_t ret = GAVL_PIXELFORMAT_NONE; bpp = 0; pf = XListPixmapFormats(dpy, &num_pf); for(i = 0; i < num_pf; i++) { if(pf[i].depth == depth) bpp = pf[i].bits_per_pixel; } XFree(pf); ret = GAVL_PIXELFORMAT_NONE; switch(bpp) { case 16: if((visual->red_mask == 63488) && (visual->green_mask == 2016) && (visual->blue_mask == 31)) ret = GAVL_RGB_16; else if((visual->blue_mask == 63488) && (visual->green_mask == 2016) && (visual->red_mask == 31)) ret = GAVL_BGR_16; break; case 24: if((visual->red_mask == 0xff) && (visual->green_mask == 0xff00) && (visual->blue_mask == 0xff0000)) ret = GAVL_RGB_24; else if((visual->red_mask == 0xff0000) && (visual->green_mask == 0xff00) && (visual->blue_mask == 0xff)) ret = GAVL_BGR_24; break; case 32: if((visual->red_mask == 0xff) && (visual->green_mask == 0xff00) && (visual->blue_mask == 0xff0000)) ret = GAVL_RGB_32; else if((visual->red_mask == 0xff0000) && (visual->green_mask == 0xff00) && (visual->blue_mask == 0xff)) ret = GAVL_BGR_32; break; } return ret; } gmerlin-1.2.0~dfsg/lib/x11/x11_video.c0000644000175000017500000002605511764363410017230 0ustar alessioalessio/***************************************************************** * gmerlin - a general purpose multimedia framework and applications * * Copyright (c) 2001 - 2011 Members of the Gmerlin project * gmerlin-general@lists.sourceforge.net * http://gmerlin.sourceforge.net * * 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 of the License, 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 this program. If not, see . * *****************************************************************/ #include #include #include #include #define LOG_DOMAIN "x11_video" static video_driver_t const * const drivers[] = { &ximage_driver, #ifdef HAVE_LIBXV &xv_driver, #endif #ifdef HAVE_GLX &gl_driver, #endif }; static int set_brightness(bg_x11_window_t * w) { if(w->video_open && w->current_driver->driver->set_brightness && (w->current_driver->flags & DRIVER_FLAG_BRIGHTNESS)) { w->current_driver->driver->set_brightness(w->current_driver, w->brightness); return 1; } return 0; } int bg_x11_window_set_brightness(bg_x11_window_t * w, float val) { w->brightness = val; return set_brightness(w); } static int set_saturation(bg_x11_window_t * w) { if(w->video_open && w->current_driver->driver->set_saturation && (w->current_driver->flags & DRIVER_FLAG_SATURATION)) { w->current_driver->driver->set_saturation(w->current_driver, w->saturation); return 1; } return 0; } int bg_x11_window_set_saturation(bg_x11_window_t * w, float val) { w->saturation = val; return set_saturation(w); } static int set_contrast(bg_x11_window_t * w) { if(w->video_open && w->current_driver->driver->set_contrast && (w->current_driver->flags & DRIVER_FLAG_CONTRAST)) { w->current_driver->driver->set_contrast(w->current_driver, w->contrast); return 1; } return 0; } int bg_x11_window_set_contrast(bg_x11_window_t * w, float val) { w->contrast = val; return set_contrast(w); } static void init(bg_x11_window_t * w) { int num_drivers, i; num_drivers = sizeof(drivers) / sizeof(drivers[0]); for(i = 0; i < num_drivers; i++) { w->drivers[i].driver = drivers[i]; w->drivers[i].win = w; if(w->drivers[i].driver->init) w->drivers[i].driver->init(&w->drivers[i]); } /* * Possible TODO: Get screen resolution * (maybe better if we don't care at all) */ w->window_format.pixel_width = 1; w->window_format.pixel_height = 1; w->idle_counter = 0; } void bg_x11_window_cleanup_video(bg_x11_window_t * w) { int num_drivers, i; num_drivers = sizeof(drivers) / sizeof(drivers[0]); /* Not initialized */ if(!w->drivers[0].driver) return; for(i = 0; i < num_drivers; i++) { if(w->drivers[i].driver->cleanup) w->drivers[i].driver->cleanup(&w->drivers[i]); if(w->drivers[i].pixelformats) free(w->drivers[i].pixelformats); } } /* For Video output */ #define PAD_SIZE 16 #define PAD(sz) (((sz+PAD_SIZE-1) / PAD_SIZE) * PAD_SIZE) int bg_x11_window_open_video(bg_x11_window_t * w, gavl_video_format_t * format) { int num_drivers; int i; int force_hw_scale; int min_penalty, min_index; w->do_sw_scale = 0; w->current_driver = NULL; if(!w->drivers_initialized) { init(w); w->drivers_initialized = 1; } gavl_video_format_copy(&w->video_format, format); /* Pad sizes, which might screw up some drivers */ w->video_format.frame_width = PAD(w->video_format.frame_width); w->video_format.frame_height = PAD(w->video_format.frame_height); if(w->auto_resize) { bg_x11_window_resize(w, (w->video_format.image_width * w->video_format.pixel_width) / w->video_format.pixel_height, w->video_format.image_height); } num_drivers = sizeof(drivers) / sizeof(drivers[0]); /* Query the best pixelformats for each driver */ for(i = 0; i < num_drivers; i++) { w->drivers[i].pixelformat = gavl_pixelformat_get_best(format->pixelformat, w->drivers[i].pixelformats, &w->drivers[i].penalty); } /* * Now, get the driver with the lowest penalty. * Scaling would be nice as well */ force_hw_scale = w->force_hw_scale; while(1) { min_index = -1; min_penalty = -1; /* Find out best driver. Drivers, which don't initialize, have the pixelformat unset */ for(i = 0; i < num_drivers; i++) { if(!w->drivers[i].driver->can_scale && force_hw_scale) continue; if(w->drivers[i].pixelformat != GAVL_PIXELFORMAT_NONE) { if((min_penalty < 0) || w->drivers[i].penalty < min_penalty) { min_penalty = w->drivers[i].penalty; min_index = i; } } } /* If we have found no driver, playing video is doomed to failure */ if(min_penalty < 0) { if(force_hw_scale) { force_hw_scale = 0; continue; } else break; } if(!w->drivers[min_index].driver->open) { w->current_driver = &w->drivers[min_index]; break; } /* Flag as unusable */ bg_log(BG_LOG_DEBUG, LOG_DOMAIN, "Trying %s driver", w->drivers[min_index].driver->name); if(!w->drivers[min_index].driver->open(&w->drivers[min_index])) { bg_log(BG_LOG_DEBUG, LOG_DOMAIN, "Opening %s driver failed", w->drivers[min_index].driver->name); w->drivers[min_index].pixelformat = GAVL_PIXELFORMAT_NONE; } else { w->current_driver = &w->drivers[min_index]; bg_log(BG_LOG_DEBUG, LOG_DOMAIN, "Opening %s driver succeeded", w->drivers[min_index].driver->name); break; } } if(!w->current_driver) return 0; w->video_format.pixelformat = w->current_driver->pixelformat; gavl_video_format_copy(format, &w->video_format); /* All other values are already set or will be set by set_rectangles */ w->window_format.pixelformat = format->pixelformat; if(!w->current_driver->driver->can_scale) { w->do_sw_scale = 1; } set_contrast(w); set_saturation(w); set_brightness(w); XSync(w->dpy, False); bg_x11_window_handle_events(w, 0); return 1; } gavl_video_frame_t * bg_x11_window_create_frame(bg_x11_window_t * w) { if(!w->do_sw_scale) { if(w->current_driver->driver->create_frame) return w->current_driver->driver->create_frame(w->current_driver); else return gavl_video_frame_create(&w->video_format); } else return gavl_video_frame_create(&w->video_format); } void bg_x11_window_destroy_frame(bg_x11_window_t * w, gavl_video_frame_t * f) { if(!w->do_sw_scale) { if(w->current_driver->driver->destroy_frame) w->current_driver->driver->destroy_frame(w->current_driver, f); else gavl_video_frame_destroy(f); } else gavl_video_frame_destroy(f); } #define PADD_SIZE 128 #define PADD_IMAGE_SIZE(s) \ s = ((s + PADD_SIZE - 1) / PADD_SIZE) * PADD_SIZE void bg_x11_window_set_rectangles(bg_x11_window_t * w, gavl_rectangle_f_t * src_rect, gavl_rectangle_i_t * dst_rect) { gavl_video_options_t * opt; gavl_rectangle_f_copy(&w->src_rect, src_rect); gavl_rectangle_i_copy(&w->dst_rect, dst_rect); if(!w->video_open) w->video_open = 1; if(w->current_driver && w->do_sw_scale) { if((w->window_format.image_width > w->window_format.frame_width) || (w->window_format.image_height > w->window_format.frame_height)) { w->window_format.frame_width = w->window_format.image_width; w->window_format.frame_height = w->window_format.image_height; PADD_IMAGE_SIZE(w->window_format.frame_width); PADD_IMAGE_SIZE(w->window_format.frame_height); if(w->window_frame) { if(w->current_driver->driver->destroy_frame) w->current_driver->driver->destroy_frame(w->current_driver, w->window_frame); else gavl_video_frame_destroy(w->window_frame); w->window_frame = NULL; } } if(!w->window_frame) { if(w->current_driver->driver->create_frame) w->window_frame = w->current_driver->driver->create_frame(w->current_driver); else w->window_frame = gavl_video_frame_create(&w->window_format); } /* Clear window */ gavl_video_frame_clear(w->window_frame, &w->window_format); /* Reinitialize scaler */ opt = gavl_video_scaler_get_options(w->scaler); gavl_video_options_set_rectangles(opt, &w->src_rect, &w->dst_rect); gavl_video_scaler_init(w->scaler, &w->video_format, &w->window_format); } bg_x11_window_clear(w); } #undef PADD_IMAGE_SIZE void bg_x11_window_put_frame_internal(bg_x11_window_t * w, gavl_video_frame_t * f) { if(w->do_sw_scale) { gavl_video_scaler_scale(w->scaler, f, w->window_frame); w->current_driver->driver->put_frame(w->current_driver, w->window_frame); } else w->current_driver->driver->put_frame(w->current_driver, f); } void bg_x11_window_put_frame(bg_x11_window_t * w, gavl_video_frame_t * f) { w->still_mode = 0; bg_x11_window_put_frame_internal(w, f); } void bg_x11_window_put_still(bg_x11_window_t * w, gavl_video_frame_t * f) { w->still_mode = 1; if(!w->still_frame) { w->still_frame = bg_x11_window_create_frame(w); } gavl_video_frame_copy(&w->video_format, w->still_frame, f); bg_x11_window_put_frame_internal(w, w->still_frame); } void bg_x11_window_close_video(bg_x11_window_t * w) { if(w->window_frame) { if(w->current_driver->driver->destroy_frame) w->current_driver->driver->destroy_frame(w->current_driver, w->window_frame); else gavl_video_frame_destroy(w->window_frame); w->window_frame = NULL; } if(w->still_frame) { bg_x11_window_destroy_frame(w, w->still_frame); w->still_frame = NULL; } if(w->overlay_streams) { free(w->overlay_streams); w->num_overlay_streams = 0; w->overlay_streams = NULL; } if(w->current_driver->driver->close) w->current_driver->driver->close(w->current_driver); w->video_open = 0; XSync(w->dpy, False); bg_x11_window_handle_events(w, 0); } gmerlin-1.2.0~dfsg/lib/x11/x11_gl.c0000644000175000017500000001613311764363410016520 0ustar alessioalessio/***************************************************************** * gmerlin - a general purpose multimedia framework and applications * * Copyright (c) 2001 - 2011 Members of the Gmerlin project * gmerlin-general@lists.sourceforge.net * http://gmerlin.sourceforge.net * * 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 of the License, 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 this program. If not, see . * *****************************************************************/ #include #include #include #include #include #define LOG_DOMAIN "GL" /* For OpenGL support */ #ifdef HAVE_GLX static const struct { int glx_attribute; } gl_attribute_map[BG_GL_ATTRIBUTE_NUM] = { [BG_GL_ATTRIBUTE_BUFFER_SIZE] = { GLX_BUFFER_SIZE, }, [BG_GL_ATTRIBUTE_LEVEL] = { GLX_LEVEL, }, [BG_GL_ATTRIBUTE_RGBA] = { GLX_RGBA, }, [BG_GL_ATTRIBUTE_DOUBLEBUFFER] = { GLX_DOUBLEBUFFER, }, [BG_GL_ATTRIBUTE_STEREO] = { GLX_STEREO, }, [BG_GL_ATTRIBUTE_AUX_BUFFERS] = { GLX_AUX_BUFFERS, }, [BG_GL_ATTRIBUTE_RED_SIZE] = { GLX_RED_SIZE, }, [BG_GL_ATTRIBUTE_GREEN_SIZE] = { GLX_GREEN_SIZE, }, [BG_GL_ATTRIBUTE_BLUE_SIZE] = { GLX_BLUE_SIZE, }, [BG_GL_ATTRIBUTE_ALPHA_SIZE] = { GLX_ALPHA_SIZE, }, [BG_GL_ATTRIBUTE_DEPTH_SIZE] = { GLX_DEPTH_SIZE, }, [BG_GL_ATTRIBUTE_STENCIL_SIZE] = { GLX_STENCIL_SIZE, }, [BG_GL_ATTRIBUTE_ACCUM_RED_SIZE] = { GLX_ACCUM_RED_SIZE, }, [BG_GL_ATTRIBUTE_ACCUM_GREEN_SIZE] = { GLX_ACCUM_GREEN_SIZE, }, [BG_GL_ATTRIBUTE_ACCUM_BLUE_SIZE] = { GLX_ACCUM_BLUE_SIZE, }, [BG_GL_ATTRIBUTE_ACCUM_ALPHA_SIZE] = { GLX_ACCUM_ALPHA_SIZE, }, }; int bg_x11_window_init_gl(bg_x11_window_t * win) { int version_major, version_minor; int rgba = 0; int num_fbconfigs; /* Build the attribute list */ int attr_index = 0, i; /* Attributes we need for video playback */ int attr_list[64]; /* Check glX presence and version */ if(!glXQueryVersion(win->dpy, &version_major, &version_minor)) { bg_log(BG_LOG_WARNING, LOG_DOMAIN, "GLX extension missing"); return 0; } if((version_major < 1) || (version_minor < 3)) { bg_log(BG_LOG_WARNING, LOG_DOMAIN, "GLX version too old: requested >= 1.3 but got %d.%d", version_major, version_minor); return 0; } bg_log(BG_LOG_DEBUG, LOG_DOMAIN, "Got GLX version %d.%d", version_major, version_minor); for(i = 0; i < BG_GL_ATTRIBUTE_NUM; i++) { if(!win->gl_attributes[i].changed) continue; if(i == BG_GL_ATTRIBUTE_RGBA) { if(win->gl_attributes[i].value) { attr_list[attr_index++] = GLX_RENDER_TYPE; attr_list[attr_index++] = GLX_RGBA_BIT; rgba = 1; } } else { attr_list[attr_index++] = gl_attribute_map[i].glx_attribute; attr_list[attr_index++] = win->gl_attributes[i].value; } } attr_list[attr_index] = None; /* Choose FBCOnfig */ // if(!win->gl_vi) // return 0; /* Check GLX version (need at least 1.3) */ win->gl_fbconfigs = glXChooseFBConfig(win->dpy, win->screen, attr_list, &num_fbconfigs); if(!win->gl_fbconfigs) { bg_log(BG_LOG_ERROR, LOG_DOMAIN, "No framebuffer configs found (insufficient driver or hardware)"); return 0; } /* Create context */ win->glxcontext = glXCreateNewContext(win->dpy, win->gl_fbconfigs[0], rgba ? GLX_RGBA_TYPE : GLX_COLOR_INDEX_TYPE, NULL, True); if(!win->glxcontext) return 0; return 1; } void bg_x11_window_set_gl_attribute(bg_x11_window_t * win, int attribute, int value) { if((attribute < 0) || (attribute >= BG_GL_ATTRIBUTE_NUM)) return; win->gl_attributes[attribute].value = value; win->gl_attributes[attribute].changed = 1; } int bg_x11_window_start_gl(bg_x11_window_t * win) { XVisualInfo * vi; if(!win->gl_fbconfigs) return 0; vi = glXGetVisualFromFBConfig(win->dpy, win->gl_fbconfigs[0]); /* Create subwindows */ bg_x11_window_create_subwins(win, vi->depth, vi->visual); /* Create GLX windows */ win->normal.glx_win = glXCreateWindow(win->dpy, win->gl_fbconfigs[0], win->normal.subwin, NULL); win->fullscreen.glx_win = glXCreateWindow(win->dpy, win->gl_fbconfigs[0], win->fullscreen.subwin, NULL); XFree(vi); return 1; } void bg_x11_window_stop_gl(bg_x11_window_t * win) { /* Destroy GLX windows */ if(win->normal.glx_win != None) { glXDestroyWindow(win->dpy, win->normal.glx_win); win->normal.glx_win = None; } if(win->fullscreen.glx_win != None) { glXDestroyWindow(win->dpy, win->fullscreen.glx_win); win->fullscreen.glx_win = None; } /* Destroy subwindows */ bg_x11_window_destroy_subwins(win); } /* * All opengl calls must be enclosed by x11_window_set_gl() and * x11_window_unset_gl() */ void bg_x11_window_set_gl(bg_x11_window_t * win) { glXMakeContextCurrent(win->dpy, win->current->glx_win, win->current->glx_win, win->glxcontext); // glXMakeCurrent(win->dpy, win->current->win, win->glxcontext); } void bg_x11_window_unset_gl(bg_x11_window_t * win) { glXMakeContextCurrent(win->dpy, None, None, NULL); // glXMakeCurrent(win->dpy, 0, NULL); } /* * Swap buffers and make your rendered work visible */ void bg_x11_window_swap_gl(bg_x11_window_t * win) { glXSwapBuffers(win->dpy, win->current->glx_win); } void bg_x11_window_cleanup_gl(bg_x11_window_t * win) { if(win->glxcontext) { glXDestroyContext(win->dpy, win->glxcontext); win->glxcontext = NULL; } } #else // !HAVE_GLX int bg_x11_window_init_gl(bg_x11_window_t * win) { return 0; } int bg_x11_window_start_gl(bg_x11_window_t * win) { return 0; } void bg_x11_window_stop_gl(bg_x11_window_t * win) { } void bg_x11_window_set_gl_attribute(bg_x11_window_t * win, int attribute, int value) { } void bg_x11_window_set_gl(bg_x11_window_t * win) { } void bg_x11_window_unset_gl(bg_x11_window_t * win) { } void bg_x11_window_swap_gl(bg_x11_window_t * win) { } void bg_x11_window_cleanup_gl(bg_x11_window_t * win) { } #endif gmerlin-1.2.0~dfsg/lib/x11/glvideo.c0000644000175000017500000003365011764363410017061 0ustar alessioalessio/***************************************************************** * gmerlin - a general purpose multimedia framework and applications * * Copyright (c) 2001 - 2011 Members of the Gmerlin project * gmerlin-general@lists.sourceforge.net * http://gmerlin.sourceforge.net * * 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 of the License, 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 this program. If not, see . * *****************************************************************/ #include #include #include #include #define texture_non_power_of_two (1<<0) typedef struct { GLuint texture; GLenum format; GLenum type; int width, height; /* For overlays only */ int active; gavl_rectangle_i_t src_rect; int dst_x, dst_y; } texture_t; typedef struct { int extensions; texture_t video; texture_t * overlays; } gl_priv_t; static int has_extension(const char * extensions, const char * name) { int len; const char * pos; if(!extensions) return 0; len = strlen(name); while(1) { if(!(pos = strstr(extensions, name))) return 0; if((pos[len] == ' ') || (pos[len] == '\0')) return 1; extensions = pos + len; } return 0; } static int check_gl(bg_x11_window_t * win, gavl_pixelformat_t * formats_ret, gl_priv_t * priv) { int format_index = 0; if(!win->gl_fbconfigs) { formats_ret[0] = GAVL_PIXELFORMAT_NONE; return 0; } formats_ret[format_index++] = GAVL_RGB_24; formats_ret[format_index++] = GAVL_RGBA_32; formats_ret[format_index++] = GAVL_RGB_48; formats_ret[format_index++] = GAVL_RGBA_64; formats_ret[format_index++] = GAVL_RGB_FLOAT; formats_ret[format_index++] = GAVL_RGBA_FLOAT; formats_ret[format_index++] = GAVL_GRAY_8; formats_ret[format_index++] = GAVL_GRAYA_16; formats_ret[format_index++] = GAVL_GRAY_16; formats_ret[format_index++] = GAVL_GRAYA_32; formats_ret[format_index++] = GAVL_GRAY_FLOAT; formats_ret[format_index++] = GAVL_GRAYA_FLOAT; formats_ret[format_index] = GAVL_PIXELFORMAT_NONE; return 1; } static int init_gl(driver_data_t * d) { gl_priv_t * priv; priv = calloc(1, sizeof(*priv)); d->priv = priv; d->pixelformats = malloc(13*sizeof(*d->pixelformats)); return check_gl(d->win, d->pixelformats, priv); } static void create_texture(gl_priv_t * priv, texture_t * ret, int width, int height, gavl_pixelformat_t pixelformat) { gavl_video_frame_t * dummy; gavl_video_format_t texture_format; switch(pixelformat) { case GAVL_GRAY_8: ret->type = GL_LUMINANCE; ret->format = GL_UNSIGNED_BYTE; break; case GAVL_GRAYA_16: ret->type = GL_LUMINANCE_ALPHA; ret->format = GL_UNSIGNED_BYTE; break; case GAVL_GRAY_16: ret->type = GL_LUMINANCE; ret->format = GL_UNSIGNED_SHORT; break; case GAVL_GRAYA_32: ret->type = GL_LUMINANCE_ALPHA; ret->format = GL_UNSIGNED_SHORT; break; case GAVL_GRAY_FLOAT: ret->type = GL_LUMINANCE; ret->format = GL_FLOAT; break; case GAVL_GRAYA_FLOAT: ret->type = GL_LUMINANCE_ALPHA; ret->format = GL_FLOAT; break; case GAVL_RGB_24: ret->type = GL_RGB; ret->format = GL_UNSIGNED_BYTE; break; case GAVL_RGBA_32: ret->type = GL_RGBA; ret->format = GL_UNSIGNED_BYTE; break; case GAVL_RGB_48: ret->type = GL_RGB; ret->format = GL_UNSIGNED_SHORT; break; case GAVL_RGBA_64: ret->type = GL_RGBA; ret->format = GL_UNSIGNED_SHORT; break; case GAVL_RGB_FLOAT: ret->type = GL_RGB; ret->format = GL_FLOAT; break; case GAVL_RGBA_FLOAT: ret->type = GL_RGBA; ret->format = GL_FLOAT; break; default: break; } memset(&texture_format, 0, sizeof(texture_format)); texture_format.image_width = width; texture_format.image_height = height; texture_format.pixelformat = pixelformat; texture_format.pixel_width = 1; texture_format.pixel_height = 1; if(!(priv->extensions & texture_non_power_of_two)) { texture_format.frame_width = 1; texture_format.frame_height = 1; while(texture_format.frame_width < width) texture_format.frame_width <<= 1; while(texture_format.frame_height < height) texture_format.frame_height <<= 1; } else { texture_format.frame_width = texture_format.image_width; texture_format.frame_height = texture_format.image_height; } ret->width = texture_format.frame_width; ret->height = texture_format.frame_height; dummy = gavl_video_frame_create_nopad(&texture_format); glGenTextures(1,&ret->texture); glBindTexture(GL_TEXTURE_2D,ret->texture); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, // ret->type, texture_format.frame_width, texture_format.frame_height, 0, ret->type, ret->format, dummy->planes[0]); gavl_video_frame_destroy(dummy); } static void delete_texture(texture_t * ret) { glDeleteTextures(1, &ret->texture); } static int open_gl(driver_data_t * d) { bg_x11_window_t * w; gl_priv_t * priv; const char * extensions; priv = (gl_priv_t *)(d->priv); w = d->win; bg_x11_window_start_gl(w); /* Get the format */ bg_x11_window_set_gl(w); extensions = (const char *) glGetString(GL_EXTENSIONS); if(has_extension(extensions, "GL_ARB_texture_non_power_of_two")) priv->extensions |= texture_non_power_of_two; create_texture(priv, &priv->video, w->video_format.image_width, w->video_format.image_height, d->pixelformat); glDisable(GL_DEPTH_TEST); glClearColor (0.0, 0.0, 0.0, 0.0); glShadeModel(GL_FLAT); glPixelStorei(GL_UNPACK_ALIGNMENT, 1); /* Video format will have frame_size == image_size */ w->video_format.frame_width = w->video_format.image_width; w->video_format.frame_height = w->video_format.image_height; bg_x11_window_unset_gl(w); return 1; } static gavl_video_frame_t * create_frame_gl(driver_data_t * d) { gavl_video_frame_t * ret; bg_x11_window_t * w; w = d->win; ret = gavl_video_frame_create_nopad(&w->video_format); return ret; } static void put_frame_gl(driver_data_t * d, gavl_video_frame_t * f) { int i; gl_priv_t * priv; bg_x11_window_t * w; float tex_x1, tex_x2, tex_y1, tex_y2; float v_x1, v_x2, v_y1, v_y2; priv = (gl_priv_t *)(d->priv); w = d->win; bg_x11_window_set_gl(w); glClear(GL_COLOR_BUFFER_BIT); /* Setup Viewport */ glViewport(w->dst_rect.x, w->dst_rect.y, w->dst_rect.w, w->dst_rect.h); glMatrixMode(GL_PROJECTION); glLoadIdentity(); glOrtho(0, // Left w->dst_rect.w,// Right 0,// Bottom w->dst_rect.h,// Top -1.0, 1.0); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); /* Put image into texture */ glEnable(GL_TEXTURE_2D); glBindTexture(GL_TEXTURE_2D,priv->video.texture); glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, w->video_format.image_width, w->video_format.image_height, priv->video.type, priv->video.format, f->planes[0]); /* Draw this */ tex_x1 = (w->src_rect.x+2.0) / priv->video.width; tex_y1 = (w->src_rect.y+2.0) / priv->video.height; tex_x2 = (w->src_rect.x + w->src_rect.w) / priv->video.width; tex_y2 = (w->src_rect.y + w->src_rect.h) / priv->video.height; glColor4f(w->background_color[0], w->background_color[1], w->background_color[2], 1.0); glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL); glBegin(GL_QUADS); glTexCoord2f(tex_x1,tex_y2); glVertex3f(0, 0, 0); glTexCoord2f(tex_x1,tex_y1); glVertex3f(0, w->dst_rect.h, 0); glTexCoord2f(tex_x2,tex_y1); glVertex3f(w->dst_rect.w, w->dst_rect.h, 0); glTexCoord2f(tex_x2,tex_y2); glVertex3f(w->dst_rect.w, 0, 0); glEnd(); /* Draw overlays */ if(w->num_overlay_streams) { glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); for(i = 0; i < w->num_overlay_streams; i++) { if(!priv->overlays[i].active) continue; glBindTexture(GL_TEXTURE_2D,priv->overlays[i].texture); tex_x1 = (float)(priv->overlays[i].src_rect.x) / priv->overlays[i].width; tex_y1 = (float)(priv->overlays[i].src_rect.y) / priv->overlays[i].height; tex_x2 = (float)(priv->overlays[i].src_rect.x + priv->overlays[i].src_rect.w) / priv->overlays[i].width; tex_y2 = (float)(priv->overlays[i].src_rect.y + priv->overlays[i].src_rect.h) / priv->overlays[i].height; v_x1 = priv->overlays[i].dst_x - w->src_rect.x; v_y1 = priv->overlays[i].dst_y - w->src_rect.y; v_x2 = v_x1 + priv->overlays[i].src_rect.w; v_y2 = v_y1 + priv->overlays[i].src_rect.h; v_x1 = (v_x1 * w->dst_rect.w) / w->src_rect.w; v_x2 = (v_x2 * w->dst_rect.w) / w->src_rect.w; v_y1 = w->dst_rect.h - (v_y1 * w->dst_rect.h) / w->src_rect.h; v_y2 = w->dst_rect.h - (v_y2 * w->dst_rect.h) / w->src_rect.h; glBegin(GL_QUADS); glTexCoord2f(tex_x1,tex_y2); glVertex3f(v_x1, v_y2, 0.1); glTexCoord2f(tex_x1,tex_y1); glVertex3f(v_x1, v_y1, 0.1); glTexCoord2f(tex_x2,tex_y1); glVertex3f(v_x2, v_y1, 0.1); glTexCoord2f(tex_x2,tex_y2); glVertex3f(v_x2, v_y2, 0.1); glEnd(); } glDisable(GL_BLEND); } bg_x11_window_swap_gl(w); glDisable(GL_TEXTURE_2D); bg_x11_window_unset_gl(w); } static void destroy_frame_gl(driver_data_t * d, gavl_video_frame_t * f) { gavl_video_frame_destroy(f); } /* Overlay support */ static void add_overlay_stream_gl(driver_data_t* d) { gl_priv_t * priv; bg_x11_window_t * w; priv = (gl_priv_t *)(d->priv); w = d->win; priv->overlays = realloc(priv->overlays, (w->num_overlay_streams+1) * sizeof(*(priv->overlays))); memset(&priv->overlays[w->num_overlay_streams], 0, sizeof(priv->overlays[w->num_overlay_streams])); if(!gavl_pixelformat_is_rgb(w->overlay_streams[w->num_overlay_streams].format.pixelformat)) w->overlay_streams[w->num_overlay_streams].format.pixelformat = GAVL_RGBA_32; bg_x11_window_set_gl(w); create_texture(priv, &priv->overlays[w->num_overlay_streams], w->overlay_streams[w->num_overlay_streams].format.image_width, w->overlay_streams[w->num_overlay_streams].format.image_height, w->overlay_streams[w->num_overlay_streams].format.pixelformat); bg_x11_window_unset_gl(w); } static void set_overlay_gl(driver_data_t* d, int stream, gavl_overlay_t * ovl) { gl_priv_t * priv; bg_x11_window_t * w; priv = (gl_priv_t *)(d->priv); w = d->win; if(ovl) { bg_x11_window_set_gl(w); glBindTexture(GL_TEXTURE_2D,priv->overlays[stream].texture); glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, w->overlay_streams[stream].format.image_width, w->overlay_streams[stream].format.image_height, priv->overlays[stream].type, priv->overlays[stream].format, ovl->frame->planes[0]); priv->overlays[stream].active = 1; bg_x11_window_unset_gl(w); gavl_rectangle_i_copy(&priv->overlays[stream].src_rect, &ovl->ovl_rect); priv->overlays[stream].dst_x = ovl->dst_x; priv->overlays[stream].dst_y = ovl->dst_y; } else priv->overlays[stream].active = 0; } static gavl_video_frame_t * create_overlay_gl(driver_data_t* d, int stream) { return gavl_video_frame_create_nopad(&d->win->overlay_streams[stream].format); } static void destroy_overlay_gl(driver_data_t* d, int stream, gavl_video_frame_t* ovl) { gavl_video_frame_destroy(ovl); } static void close_gl(driver_data_t * d) { int i; gl_priv_t * priv; bg_x11_window_t * w; priv = (gl_priv_t *)(d->priv); w = d->win; bg_x11_window_set_gl(w); delete_texture(&priv->video); for(i = 0; i < w->num_overlay_streams; i++) delete_texture(&priv->overlays[i]); if(priv->overlays) { free(priv->overlays); priv->overlays = NULL; } bg_x11_window_unset_gl(w); bg_x11_window_stop_gl(w); } static void cleanup_gl(driver_data_t * d) { gl_priv_t * priv; priv = (gl_priv_t *)(d->priv); free(priv); } const video_driver_t gl_driver = { .name = "OpenGL", .can_scale = 1, .init = init_gl, .open = open_gl, .create_frame = create_frame_gl, .put_frame = put_frame_gl, .destroy_frame = destroy_frame_gl, .close = close_gl, .cleanup = cleanup_gl, .add_overlay_stream = add_overlay_stream_gl, .set_overlay = set_overlay_gl, .create_overlay = create_overlay_gl, .destroy_overlay = destroy_overlay_gl, }; gmerlin-1.2.0~dfsg/lib/x11/xvideo.c0000644000175000017500000004071611764363410016727 0ustar alessioalessio/***************************************************************** * gmerlin - a general purpose multimedia framework and applications * * Copyright (c) 2001 - 2011 Members of the Gmerlin project * gmerlin-general@lists.sourceforge.net * http://gmerlin.sourceforge.net * * 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 of the License, 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 this program. If not, see . * *****************************************************************/ #include #include #include #include #include #define LOG_DOMAIN "xv" #define XV_ID_YV12 0x32315659 #define XV_ID_I420 0x30323449 #define XV_ID_YUY2 0x32595559 #define XV_ID_UYVY 0x59565955 #define XV_ATTR_BRIGHTNESS 0 #define XV_ATTR_SATURATION 1 #define XV_ATTR_CONTRAST 2 #define XV_ATTR_NUM 3 typedef struct { XvPortID start_port; XvPortID end_port; XvPortID current_port; int * format_ids; int have_xv_colorkey; int xv_colorkey; int xv_colorkey_orig; Atom xv_colorkey_atom; int xv_colorkey_settable; int format; int max_width, max_height; struct { Atom atom; int index; } attributes[XV_ATTR_NUM]; XvAttribute * xv_attributes; } xv_priv_t; static void check_xv(driver_data_t * d) { xv_priv_t * priv; unsigned int version; unsigned int release; unsigned int dummy; unsigned int adaptors; unsigned int i; XvAdaptorInfo * adaptorInfo; XvEncodingInfo * encodingInfo; XvImageFormatValues * formatValues; int num; unsigned int numu; int formats; int k; int found = 0; int format_index = 0; int have_420 = 0; priv = (xv_priv_t*)d->priv; d->pixelformats[0] = GAVL_PIXELFORMAT_NONE; if ((XvQueryExtension (d->win->dpy, &version, &release, &dummy, &dummy, &dummy) != Success) || (version < 2) || ((version == 2) && (release < 2))) return; XvQueryAdaptors (d->win->dpy, d->win->root, &adaptors, &adaptorInfo); for(i = 0; i < adaptors; i++) { /* Continue if this adaptor doesn't support XvPutImage */ if((adaptorInfo[i].type & (XvImageMask|XvInputMask)) != (XvImageMask| XvInputMask)) continue; #if 0 /* Our visual was probably selected using GLXChooseVisual. Sometimes, XVideo adaptors don't support all visuals, XVPutImage will trigger a BadMatch then. Difficult to solve this in an elegant way. Here, we just disable XVideo support in such cases */ for(k = 0; k < adaptorInfo[i].num_formats; k++) { if((adaptorInfo[i].formats[k].depth == d->win->depth) && (adaptorInfo[i].formats[k].visual_id == d->win->visual->visualid)) break; } if(k >= adaptorInfo[i].num_formats) { bg_log(BG_LOG_WARNING, LOG_DOMAIN, "Visual and depth not supported by adaptor %d", i+1); continue; } #endif /* Image formats are the same for each port of a given adaptor, it is enough to list the image formats just for the base port. At least this is what xvinfo does. */ formatValues = XvListImageFormats(d->win->dpy, adaptorInfo[i].base_id, &formats); for (k = 0; k < formats; k++) { if(formatValues[k].id == XV_ID_I420) { if(!have_420) { d->pixelformats[format_index] = GAVL_YUV_420_P; priv->format_ids[format_index++] = formatValues[k].id; found = 1; have_420 = 1; } } else if (formatValues[k].id == XV_ID_YV12) { if(!have_420) { d->pixelformats[format_index] = GAVL_YUV_420_P; priv->format_ids[format_index++] = formatValues[k].id; found = 1; have_420 = 1; } } else if(formatValues[k].id == XV_ID_YUY2) { d->pixelformats[format_index] = GAVL_YUY2; priv->format_ids[format_index++] = formatValues[k].id; found = 1; } else if(formatValues[k].id == XV_ID_UYVY) { d->pixelformats[format_index] = GAVL_UYVY; priv->format_ids[format_index++] = formatValues[k].id; found = 1; } } XFree (formatValues); if(found) { priv->start_port = adaptorInfo[i].base_id; priv->end_port = adaptorInfo[i].base_id + adaptorInfo[i].num_ports; break; } } XvFreeAdaptorInfo (adaptorInfo); d->pixelformats[format_index] = GAVL_PIXELFORMAT_NONE; if(found) { /* Check for attributes */ priv->xv_attributes = XvQueryPortAttributes(d->win->dpy, priv->start_port, &num); for(i = 0; i < num; i++) { if(!strcmp(priv->xv_attributes[i].name, "XV_BRIGHTNESS")) { priv->attributes[XV_ATTR_BRIGHTNESS].index = i; priv->attributes[XV_ATTR_BRIGHTNESS].atom = XInternAtom(d->win->dpy, "XV_BRIGHTNESS", False); d->flags |= DRIVER_FLAG_BRIGHTNESS; } else if(!strcmp(priv->xv_attributes[i].name, "XV_CONTRAST")) { priv->attributes[XV_ATTR_CONTRAST].index = i; priv->attributes[XV_ATTR_CONTRAST].atom = XInternAtom(d->win->dpy, "XV_CONTRAST", False); d->flags |= DRIVER_FLAG_CONTRAST; } else if(!strcmp(priv->xv_attributes[i].name, "XV_SATURATION")) { priv->attributes[XV_ATTR_SATURATION].index = i; priv->attributes[XV_ATTR_SATURATION].atom = XInternAtom(d->win->dpy, "XV_SATURATION", False); d->flags |= DRIVER_FLAG_SATURATION; } } num = 0; XvQueryEncodings(d->win->dpy, priv->start_port, &numu, &encodingInfo); for(i = 0; i < numu; i++) { if(!strcmp(encodingInfo[i].name, "XV_IMAGE")) { priv->max_width = encodingInfo[i].width; priv->max_height = encodingInfo[i].height; } } if(numu) XvFreeEncodingInfo(encodingInfo); } return; } static int init_xv(driver_data_t * d) { xv_priv_t * priv; priv = calloc(1, sizeof(*priv)); d->priv = priv; priv->format_ids = malloc(5*sizeof(*priv->format_ids)); d->pixelformats = malloc(5*sizeof(*d->pixelformats)); check_xv(d); return 0; } static int open_xv(driver_data_t * d) { bg_x11_window_t * w; xv_priv_t * priv; int i; int result; priv = (xv_priv_t *)(d->priv); w = d->win; /* Check agaist the maximum size */ if(priv->max_width && (d->win->video_format.frame_width > priv->max_width)) { bg_log(BG_LOG_ERROR, LOG_DOMAIN, "Image width out of range"); return 0; } if(priv->max_height && (d->win->video_format.frame_height > priv->max_height)) { bg_log(BG_LOG_ERROR, LOG_DOMAIN, "Image height out of range"); return 0; } /* Get the format */ i = 0; while(d->pixelformats[i] != GAVL_PIXELFORMAT_NONE) { if(d->pixelformats[i] == d->pixelformat) { priv->format = priv->format_ids[i]; bg_log(BG_LOG_INFO, LOG_DOMAIN, "Using XV format: %c%c%c%c", priv->format & 0xff, (priv->format >> 8) & 0xff, (priv->format >> 16) & 0xff, (priv->format >> 24) & 0xff); break; } i++; } if(d->pixelformats[i] == GAVL_PIXELFORMAT_NONE) { bg_log(BG_LOG_ERROR, LOG_DOMAIN, "No suitable pixelformat"); return 0; } priv->current_port = priv->start_port; while(priv->current_port < priv->end_port) { result = XvGrabPort(w->dpy, priv->current_port, CurrentTime); switch(result) { case Success: break; case XvAlreadyGrabbed: bg_log(BG_LOG_DEBUG, LOG_DOMAIN, "Port %li already grabbed, trying next one", priv->current_port); priv->current_port++; break; case XvInvalidTime: bg_log(BG_LOG_ERROR, LOG_DOMAIN, "Grabbing Port %li failed (invalid time), trying next one", priv->current_port); priv->current_port++; break; default: bg_log(BG_LOG_ERROR, LOG_DOMAIN, "Grabbing Port %li failed (unknown error)", priv->current_port); return 0; break; } if(result == Success) break; } if(priv->current_port >= priv->end_port) { bg_log(BG_LOG_ERROR, LOG_DOMAIN, "Could not find free port"); return 0; } if(priv->have_xv_colorkey) { XvGetPortAttribute(w->dpy, priv->current_port, priv->xv_colorkey_atom, &priv->xv_colorkey_orig); if(priv->xv_colorkey_settable) { priv->xv_colorkey = 0x00010100; XvSetPortAttribute(w->dpy, priv->current_port, priv->xv_colorkey_atom, priv->xv_colorkey); XSetWindowBackground(w->dpy, w->normal.win, priv->xv_colorkey); XSetWindowBackground(w->dpy, w->fullscreen.win, priv->xv_colorkey); } else priv->xv_colorkey = priv->xv_colorkey_orig; } return 1; } typedef struct { XvImage * xv_image; XShmSegmentInfo shminfo; } xv_frame_t; static gavl_video_frame_t * create_frame_xv(driver_data_t * d) { xv_frame_t * frame; gavl_video_frame_t * ret; bg_x11_window_t * w; xv_priv_t * priv; priv = (xv_priv_t *)(d->priv); w = d->win; frame = calloc(1, sizeof(*frame)); if(w->have_shm) { frame->xv_image = XvShmCreateImage(w->dpy, priv->current_port, priv->format, NULL, w->video_format.frame_width, w->video_format.frame_height, &frame->shminfo); if(!frame->xv_image) w->have_shm = 0; else { if(!bg_x11_window_create_shm(w, &frame->shminfo, frame->xv_image->data_size)) { XFree(frame->xv_image); frame->xv_image = NULL; w->have_shm = 0; } else frame->xv_image->data = frame->shminfo.shmaddr; } } if(!w->have_shm) { ret = gavl_video_frame_create(&w->video_format); frame->xv_image = XvCreateImage(w->dpy, priv->current_port, priv->format, (char*)(ret->planes[0]), w->video_format.frame_width, w->video_format.frame_height); } else ret = gavl_video_frame_create(NULL); switch(priv->format) { case XV_ID_YV12: ret->planes[0] = (uint8_t*)(frame->xv_image->data + frame->xv_image->offsets[0]); ret->planes[1] = (uint8_t*)(frame->xv_image->data + frame->xv_image->offsets[2]); ret->planes[2] = (uint8_t*)(frame->xv_image->data + frame->xv_image->offsets[1]); ret->strides[0] = frame->xv_image->pitches[0]; ret->strides[1] = frame->xv_image->pitches[2]; ret->strides[2] = frame->xv_image->pitches[1]; break; case XV_ID_I420: ret->planes[0] = (uint8_t*)(frame->xv_image->data + frame->xv_image->offsets[0]); ret->planes[1] = (uint8_t*)(frame->xv_image->data + frame->xv_image->offsets[1]); ret->planes[2] = (uint8_t*)(frame->xv_image->data + frame->xv_image->offsets[2]); ret->strides[0] = frame->xv_image->pitches[0]; ret->strides[1] = frame->xv_image->pitches[1]; ret->strides[2] = frame->xv_image->pitches[2]; break; case XV_ID_YUY2: case XV_ID_UYVY: ret->planes[0] = (uint8_t*)(frame->xv_image->data + frame->xv_image->offsets[0]); ret->strides[0] = frame->xv_image->pitches[0]; break; } ret->user_data = frame; return ret; } static void put_frame_xv(driver_data_t * d, gavl_video_frame_t * f) { xv_priv_t * priv; xv_frame_t * frame = (xv_frame_t*)f->user_data; bg_x11_window_t * w; priv = (xv_priv_t *)(d->priv); w = d->win; if(w->have_shm) { XvShmPutImage(w->dpy, priv->current_port, w->current->win, w->gc, frame->xv_image, (int)w->src_rect.x, /* src_x */ (int)w->src_rect.y, /* src_y */ (int)w->src_rect.w, /* src_w */ (int)w->src_rect.h, /* src_h */ w->dst_rect.x, /* dest_x */ w->dst_rect.y, /* dest_y */ w->dst_rect.w, /* dest_w */ w->dst_rect.h, /* dest_h */ True); w->wait_for_completion = 1; } else { XvPutImage(w->dpy, priv->current_port, w->current->win, w->gc, frame->xv_image, (int)w->src_rect.x, /* src_x */ (int)w->src_rect.y, /* src_y */ (int)w->src_rect.w, /* src_w */ (int)w->src_rect.h, /* src_h */ w->dst_rect.x, /* dest_x */ w->dst_rect.y, /* dest_y */ w->dst_rect.w, /* dest_w */ w->dst_rect.h); /* dest_h */ } } static void destroy_frame_xv(driver_data_t * d, gavl_video_frame_t * f) { xv_frame_t * frame = (xv_frame_t*)f->user_data; bg_x11_window_t * w = d->win; if(frame->xv_image) XFree(frame->xv_image); if(w->have_shm) { bg_x11_window_destroy_shm(w, &frame->shminfo); gavl_video_frame_null(f); gavl_video_frame_destroy(f); } else { gavl_video_frame_destroy(f); } free(frame); } static void close_xv(driver_data_t * d) { xv_priv_t * priv; bg_x11_window_t * w; priv = (xv_priv_t *)(d->priv); w = d->win; XvUngrabPort(w->dpy, priv->current_port, CurrentTime); XvStopVideo(w->dpy, priv->current_port, w->current->win); if(priv->xv_colorkey_settable) XvSetPortAttribute(w->dpy, priv->current_port, priv->xv_colorkey_atom, priv->xv_colorkey_orig); } static void cleanup_xv(driver_data_t * d) { xv_priv_t * priv; priv = (xv_priv_t *)(d->priv); if(priv->format_ids) free(priv->format_ids); if(priv->xv_attributes) XFree(priv->xv_attributes); free(priv); } static int rescale(XvAttribute * attr, float val, float min, float max) { int ret; ret = attr->min_value + (int)((attr->max_value - attr->min_value) * (val - min) / (max - min) + 0.5); if(ret < attr->min_value) ret = attr->min_value; if(ret > attr->max_value) ret = attr->max_value; return ret; } static void set_brightness_xv(driver_data_t* d,float val) { xv_priv_t * priv; int val_i; priv = d->priv; val_i = rescale(&priv->xv_attributes[priv->attributes[XV_ATTR_BRIGHTNESS].index], val, BG_BRIGHTNESS_MIN, BG_BRIGHTNESS_MAX); XvSetPortAttribute(d->win->dpy, priv->current_port, priv->attributes[XV_ATTR_BRIGHTNESS].atom, val_i); } static void set_saturation_xv(driver_data_t* d,float val) { xv_priv_t * priv; priv = (xv_priv_t *)(d->priv); XvSetPortAttribute(d->win->dpy, priv->current_port, priv->attributes[XV_ATTR_SATURATION].atom, rescale(&priv->xv_attributes[priv->attributes[XV_ATTR_SATURATION].index], val, BG_SATURATION_MIN, BG_SATURATION_MAX)); } static void set_contrast_xv(driver_data_t* d,float val) { xv_priv_t * priv; priv = (xv_priv_t *)(d->priv); XvSetPortAttribute(d->win->dpy, priv->current_port, priv->attributes[XV_ATTR_CONTRAST].atom, rescale(&priv->xv_attributes[priv->attributes[XV_ATTR_CONTRAST].index], val, BG_CONTRAST_MIN, BG_CONTRAST_MAX)); } const video_driver_t xv_driver = { .name = "XVideo", .can_scale = 1, .init = init_xv, .open = open_xv, .create_frame = create_frame_xv, .set_brightness = set_brightness_xv, .set_saturation = set_saturation_xv, .set_contrast = set_contrast_xv, .put_frame = put_frame_xv, .destroy_frame = destroy_frame_xv, .close = close_xv, .cleanup = cleanup_xv, }; gmerlin-1.2.0~dfsg/lib/x11/overlay.c0000644000175000017500000000610711764363410017106 0ustar alessioalessio/***************************************************************** * gmerlin - a general purpose multimedia framework and applications * * Copyright (c) 2001 - 2011 Members of the Gmerlin project * gmerlin-general@lists.sourceforge.net * http://gmerlin.sourceforge.net * * 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 of the License, 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 this program. If not, see . * *****************************************************************/ #include #include #include int bg_x11_window_add_overlay_stream(bg_x11_window_t * w, gavl_video_format_t * format) { if(!w->current_driver->driver->add_overlay_stream) return -1; w->overlay_streams = realloc(w->overlay_streams, (w->num_overlay_streams+1) * sizeof(*(w->overlay_streams))); memset(&w->overlay_streams[w->num_overlay_streams], 0, sizeof(w->overlay_streams[w->num_overlay_streams])); /* Initialize */ gavl_video_format_copy(&w->overlay_streams[w->num_overlay_streams].format, format); w->current_driver->driver->add_overlay_stream(w->current_driver); gavl_video_format_copy(format, &w->overlay_streams[w->num_overlay_streams].format); w->num_overlay_streams++; return w->num_overlay_streams - 1; } void bg_x11_window_set_overlay(bg_x11_window_t * w, int stream, gavl_overlay_t * ovl) { int i; w->overlay_streams[stream].ovl = ovl; w->current_driver->driver->set_overlay(w->current_driver, stream, ovl); w->has_overlay = 0; for(i = 0; i < w->num_overlay_streams; i++) { if(w->overlay_streams[i].ovl) { w->has_overlay = 1; break; } } } gavl_overlay_t * bg_x11_window_create_overlay(bg_x11_window_t * w, int stream) { gavl_overlay_t * ret; ret = calloc(1, sizeof(*ret)); if(w->current_driver->driver->create_overlay) ret->frame = w->current_driver->driver->create_overlay(w->current_driver, stream); else ret->frame = gavl_video_frame_create(&w->overlay_streams[stream].format); return ret; } void bg_x11_window_destroy_overlay(bg_x11_window_t * w, int stream, gavl_overlay_t * ovl) { if(w->current_driver->driver->destroy_overlay) w->current_driver->driver->destroy_overlay(w->current_driver, stream, ovl->frame); else gavl_video_frame_destroy(ovl->frame); free(ovl); } gmerlin-1.2.0~dfsg/lib/x11/shm.c0000644000175000017500000000514411764363410016214 0ustar alessioalessio/***************************************************************** * gmerlin - a general purpose multimedia framework and applications * * Copyright (c) 2001 - 2011 Members of the Gmerlin project * gmerlin-general@lists.sourceforge.net * http://gmerlin.sourceforge.net * * 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 of the License, 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 this program. If not, see . * *****************************************************************/ #include #include #include #include #define LOG_DOMAIN "x11_shm" #include /* Check for xshm extension */ int bg_x11_window_check_shm(Display * dpy, int * completion_type) { #if 0 return 0; #else int major; int minor; Bool pixmaps; int ret; if ((XShmQueryVersion (dpy, &major, &minor, &pixmaps) == 0) || (major < 1) || ((major == 1) && (minor < 1))) ret = 0; else ret = 1; if(ret) *completion_type = XShmGetEventBase(dpy) + ShmCompletion; return ret; #endif } static int shmerror = 0; static int handle_error (Display * display, XErrorEvent * error) { shmerror = 1; return 0; } int bg_x11_window_create_shm(bg_x11_window_t * win, XShmSegmentInfo * shminfo, int size) { shmerror = 0; shminfo->shmid = shmget (IPC_PRIVATE, size, IPC_CREAT | 0777); if (shminfo->shmid == -1) goto error; shminfo->shmaddr = (char *) shmat (shminfo->shmid, 0, 0); if (shminfo->shmaddr == (char *)-1) goto error; XSync (win->dpy, False); XSetErrorHandler (handle_error); shminfo->readOnly = True; if(!(XShmAttach (win->dpy, shminfo))) shmerror = 1; XSync (win->dpy, False); XSetErrorHandler(NULL); if(shmerror) { error: bg_log(BG_LOG_DEBUG, LOG_DOMAIN, "Cannot create shared memory"); return 0; } return 1; } void bg_x11_window_destroy_shm(bg_x11_window_t * win, XShmSegmentInfo * shminfo) { XShmDetach (win->dpy, shminfo); shmdt (shminfo->shmaddr); shmctl (shminfo->shmid, IPC_RMID, 0); } gmerlin-1.2.0~dfsg/lib/x11/grab.c0000644000175000017500000005705011764363410016343 0ustar alessioalessio/***************************************************************** * gmerlin - a general purpose multimedia framework and applications * * Copyright (c) 2001 - 2011 Members of the Gmerlin project * gmerlin-general@lists.sourceforge.net * http://gmerlin.sourceforge.net * * 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 of the License, 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 this program. If not, see . * *****************************************************************/ #include #include #include #include // INT_MIN #include #include #include #include #include #include #ifdef HAVE_XFIXES #include #endif #include #define DRAW_CURSOR (1<<0) #define GRAB_ROOT (1<<1) #define WIN_ONTOP (1<<2) #define WIN_STICKY (1<<3) #define DISABLE_SCREENSAVER (1<<4) #define LOG_DOMAIN "x11grab" #include #define MAX_CURSOR_SIZE 32 static const bg_parameter_info_t parameters[] = { { .name = "root", .long_name = TRS("Grab from root window"), .type = BG_PARAMETER_CHECKBUTTON, }, { .name = "draw_cursor", .long_name = TRS("Draw cursor"), .type = BG_PARAMETER_CHECKBUTTON, .val_default = { .val_i = 1 }, }, { .name = "win_ontop", .long_name = TRS("Keep grab window on top"), .type = BG_PARAMETER_CHECKBUTTON, .val_default = { .val_i = 1 }, }, { .name = "win_sticky", .long_name = TRS("Make grab window sticky"), .type = BG_PARAMETER_CHECKBUTTON, .val_default = { .val_i = 1 }, }, { .name = "disable_screensaver", .long_name = TRS("Disable screensaver"), .type = BG_PARAMETER_CHECKBUTTON, .val_default = { .val_i = 1 }, .help_string = TRS("Disable screensaver and energy saving mode"), }, { .name = "x", .long_name = "X", .type = BG_PARAMETER_INT, .flags = BG_PARAMETER_HIDE_DIALOG, .val_default = { .val_i = 0 }, }, { .name = "y", .long_name = "Y", .type = BG_PARAMETER_INT, .flags = BG_PARAMETER_HIDE_DIALOG, .val_default = { .val_i = 0 }, }, { .name = "w", .long_name = "W", .type = BG_PARAMETER_INT, .flags = BG_PARAMETER_HIDE_DIALOG, .val_default = { .val_i = 320 }, }, { .name = "h", .long_name = "H", .type = BG_PARAMETER_INT, .flags = BG_PARAMETER_HIDE_DIALOG, .val_default = { .val_i = 240 }, }, { .name = "decoration_x", .long_name = "DX", .type = BG_PARAMETER_INT, .flags = BG_PARAMETER_HIDE_DIALOG, .val_default = { .val_i = 0 }, }, { .name = "decoration_y", .long_name = "DY", .type = BG_PARAMETER_INT, .flags = BG_PARAMETER_HIDE_DIALOG, .val_default = { .val_i = 0 }, }, { /* End */ }, }; struct bg_x11_grab_window_s { Display * dpy; Window win; Window root; gavl_rectangle_i_t grab_rect; gavl_rectangle_i_t win_rect; int flags; int cfg_flags; gavl_pixelformat_t pixelformat; gavl_timer_t * timer; XImage * image; gavl_video_frame_t * frame; gavl_video_format_t format; Visual * visual; int depth; int use_shm; XShmSegmentInfo shminfo; int root_width, root_height; int screen; int decoration_x, decoration_y; #ifdef HAVE_XFIXES int use_xfixes; int xfixes_eventbase; int cursor_changed; #endif gavl_overlay_t cursor; gavl_video_format_t cursor_format; int cursor_off_x; int cursor_off_y; int cursor_x; int cursor_y; gavl_rectangle_i_t cursor_rect; gavl_overlay_blend_context_t * blend; bg_x11_screensaver_t scr; }; const bg_parameter_info_t * bg_x11_grab_window_get_parameters(bg_x11_grab_window_t * win) { return parameters; } void bg_x11_grab_window_set_parameter(void * data, const char * name, const bg_parameter_value_t * val) { bg_x11_grab_window_t * win = data; if(!name) { return; } else if(!strcmp(name, "x")) { win->win_rect.x = val->val_i; } else if(!strcmp(name, "y")) { win->win_rect.y = val->val_i; } else if(!strcmp(name, "w")) { win->win_rect.w = val->val_i; } else if(!strcmp(name, "h")) { win->win_rect.h = val->val_i; } else if(!strcmp(name, "decoration_x")) { win->decoration_x = val->val_i; } else if(!strcmp(name, "decoration_y")) { win->decoration_y = val->val_i; } else if(!strcmp(name, "root")) { if(val->val_i) win->cfg_flags |= GRAB_ROOT; else win->cfg_flags &= ~GRAB_ROOT; } else if(!strcmp(name, "win_ontop")) { if(val->val_i) win->cfg_flags |= WIN_ONTOP; else win->cfg_flags &= ~WIN_ONTOP; } else if(!strcmp(name, "win_sticky")) { if(val->val_i) win->cfg_flags |= WIN_STICKY; else win->cfg_flags &= ~WIN_STICKY; } else if(!strcmp(name, "draw_cursor")) { if(val->val_i) win->cfg_flags |= DRAW_CURSOR; else win->cfg_flags &= ~DRAW_CURSOR; } else if(!strcmp(name, "disable_screensaver")) { if(val->val_i) win->cfg_flags |= DISABLE_SCREENSAVER; else win->cfg_flags &= ~DISABLE_SCREENSAVER; } } int bg_x11_grab_window_get_parameter(void * data, const char * name, bg_parameter_value_t * val) { bg_x11_grab_window_t * win = data; if(!strcmp(name, "x")) { val->val_i = win->win_rect.x; return 1; } else if(!strcmp(name, "y")) { val->val_i = win->win_rect.y; return 1; } else if(!strcmp(name, "w")) { val->val_i = win->win_rect.w; return 1; } else if(!strcmp(name, "h")) { val->val_i = win->win_rect.h; return 1; } else if(!strcmp(name, "decoration_x")) { val->val_i = win->decoration_x; return 1; } else if(!strcmp(name, "decoration_y")) { val->val_i = win->decoration_y; return 1; } return 0; } /* Static cursor bitmap taken from ffmpeg/libavdevice/x11grab.c Generation routine is native development though */ /* 16x20x1bpp bitmap for the black channel of the mouse pointer */ static const uint16_t const cursor_black[] = { 0x0000, 0x0003, 0x0005, 0x0009, 0x0011, 0x0021, 0x0041, 0x0081, 0x0101, 0x0201, 0x03c1, 0x0049, 0x0095, 0x0093, 0x0120, 0x0120, 0x0240, 0x0240, 0x0380, 0x0000 }; /* 16x20x1bpp bitmap for the white channel of the mouse pointer */ static const uint16_t const cursor_white[] = { 0x0000, 0x0000, 0x0002, 0x0006, 0x000e, 0x001e, 0x003e, 0x007e, 0x00fe, 0x01fe, 0x003e, 0x0036, 0x0062, 0x0060, 0x00c0, 0x00c0, 0x0180, 0x0180, 0x0000, 0x0000 }; static const float cursor_transparent[4] = { 0.0, 0.0, 0.0, 0.0 }; #define CURSOR_WIDTH 16 #define CURSOR_HEIGHT 20 static void create_cursor_static(bg_x11_grab_window_t * win) { int i, j; uint16_t black; uint16_t white; uint8_t * ptr; gavl_video_frame_fill(win->cursor.frame, &win->cursor_format, cursor_transparent); for(i = 0; i < CURSOR_HEIGHT; i++) { black = cursor_black[i]; white = cursor_white[i]; ptr = win->cursor.frame->planes[0] + i * win->cursor.frame->strides[0]; for(j = 0; j < CURSOR_WIDTH; j++) { if(white & 0x01) { ptr[0] = 0xff; ptr[1] = 0xff; ptr[2] = 0xff; ptr[3] = 0xff; } else if(black & 0x01) { ptr[0] = 0x00; ptr[1] = 0x00; ptr[2] = 0x00; ptr[3] = 0xff; } ptr += 4; black >>= 1; white >>= 1; } } win->cursor.ovl_rect.w = CURSOR_WIDTH; win->cursor.ovl_rect.h = CURSOR_HEIGHT; } static void create_window(bg_x11_grab_window_t * ret) { XSetWindowAttributes attr; unsigned long valuemask; Atom wm_protocols[1]; /* Create window */ attr.background_pixmap = None; valuemask = CWBackPixmap; ret->win = XCreateWindow(ret->dpy, ret->root, ret->win_rect.x, // int x, ret->win_rect.y, // int y, ret->win_rect.w, // unsigned int width, ret->win_rect.h, // unsigned int height, 0, // unsigned int border_width, ret->depth, InputOutput, ret->visual, valuemask, &attr); XSelectInput(ret->dpy, ret->win, StructureNotifyMask); XShapeCombineRectangles(ret->dpy, ret->win, ShapeBounding, 0, 0, NULL, 0, ShapeSet, YXBanded); wm_protocols[0] = XInternAtom(ret->dpy, "WM_DELETE_WINDOW", False); XSetWMProtocols(ret->dpy, ret->win, wm_protocols, 1); XmbSetWMProperties(ret->dpy, ret->win, "X11 grab", "X11 grab", NULL, 0, NULL, NULL, NULL); if(!(ret->flags & GRAB_ROOT)) { if(ret->flags & (WIN_ONTOP|WIN_STICKY)) { Atom wm_states[2]; int num_props = 0; Atom wm_state = XInternAtom(ret->dpy, "_NET_WM_STATE", False); if(ret->flags & WIN_ONTOP) { wm_states[num_props++] = XInternAtom(ret->dpy, "_NET_WM_STATE_ABOVE", False); } if(ret->flags & WIN_STICKY) { wm_states[num_props++] = XInternAtom(ret->dpy, "_NET_WM_STATE_STICKY", False); } XChangeProperty(ret->dpy, ret->win, wm_state, XA_ATOM, 32, PropModeReplace, (unsigned char *)wm_states, num_props); XSync(ret->dpy, False); } XMapWindow(ret->dpy, ret->win); XSync(ret->dpy, False); XMoveWindow(ret->dpy, ret->win, ret->decoration_x, ret->decoration_y); } } static int realize_window(bg_x11_grab_window_t * ret) { #ifdef HAVE_XFIXES int xfixes_errorbase; #endif /* Open Display */ ret->dpy = XOpenDisplay(NULL); if(!ret->dpy) return 0; bg_x11_screensaver_init(&ret->scr, ret->dpy); /* Get X11 stuff */ ret->screen = DefaultScreen(ret->dpy); ret->visual = DefaultVisual(ret->dpy, ret->screen); ret->depth = DefaultDepth(ret->dpy, ret->screen); ret->root = RootWindow(ret->dpy, ret->screen); /* Check for XFixes */ #ifdef HAVE_XFIXES ret->use_xfixes = XFixesQueryExtension(ret->dpy, &ret->xfixes_eventbase, &xfixes_errorbase); if(ret->use_xfixes) XFixesSelectCursorInput(ret->dpy, ret->root, XFixesDisplayCursorNotifyMask); else #endif create_cursor_static(ret); bg_x11_window_get_coords(ret->dpy, ret->root, NULL, NULL, &ret->root_width, &ret->root_height); ret->pixelformat = bg_x11_window_get_pixelformat(ret->dpy, ret->visual, ret->depth); ret->use_shm = XShmQueryExtension(ret->dpy); return 1; } bg_x11_grab_window_t * bg_x11_grab_window_create() { bg_x11_grab_window_t * ret = calloc(1, sizeof(*ret)); /* Initialize members */ ret->win = None; ret->timer = gavl_timer_create(); ret->blend = gavl_overlay_blend_context_create(); ret->cursor_format.image_width = MAX_CURSOR_SIZE; ret->cursor_format.image_height = MAX_CURSOR_SIZE; ret->cursor_format.frame_width = MAX_CURSOR_SIZE; ret->cursor_format.frame_height = MAX_CURSOR_SIZE; ret->cursor_format.pixel_width = 1; ret->cursor_format.pixel_height = 1; // Fixme: This will break for > 8 bit/channel RGB visuals // and other 8bit / channel RGBA formats ret->cursor_format.pixelformat = GAVL_RGBA_32; ret->cursor.frame = gavl_video_frame_create(&ret->cursor_format); return ret; } void bg_x11_grab_window_destroy(bg_x11_grab_window_t * win) { if(win->win != None) XDestroyWindow(win->dpy, win->win); bg_x11_screensaver_cleanup(&win->scr); if(win->dpy) XCloseDisplay(win->dpy); gavl_timer_destroy(win->timer); gavl_overlay_blend_context_destroy(win->blend); gavl_video_frame_destroy(win->cursor.frame); free(win); } static void handle_events(bg_x11_grab_window_t * win) { XEvent evt; bg_x11_screensaver_ping(&win->scr); while(XPending(win->dpy)) { XNextEvent(win->dpy, &evt); #ifdef HAVE_XFIXES if(evt.type == win->xfixes_eventbase + XFixesCursorNotify) { win->cursor_changed = 1; // fprintf(stderr, "Cursor notify\n"); continue; } #endif switch(evt.type) { case ConfigureNotify: { Window * children_return; Window root_return; Window parent_return; unsigned int nchildren_return; int x_return, y_return; unsigned int width_return, height_return; unsigned int border_width_return; unsigned int depth_return; win->win_rect.w = evt.xconfigure.width; win->win_rect.h = evt.xconfigure.height; XGetGeometry(win->dpy, win->win, &root_return, &x_return, &y_return, &width_return, &height_return, &border_width_return, &depth_return); win->win_rect.x = x_return; win->win_rect.y = y_return; XQueryTree(win->dpy, win->win, &root_return, &parent_return, &children_return, &nchildren_return); if(nchildren_return) XFree(children_return); /* Get offset of the window frame */ if(parent_return != root_return) { XGetGeometry(win->dpy, parent_return, &root_return, &x_return, &y_return, &width_return, &height_return, &border_width_return, &depth_return); win->decoration_x = x_return; win->decoration_y = y_return; win->win_rect.x += x_return; win->win_rect.y += y_return; } if(!(win->flags & GRAB_ROOT)) { win->grab_rect.x = win->win_rect.x; win->grab_rect.y = win->win_rect.y; } bg_log(BG_LOG_INFO, LOG_DOMAIN, "Window geometry: %dx%d+%d+%d", win->win_rect.w, win->win_rect.h, win->win_rect.x, win->win_rect.y); } break; } } } int bg_x11_grab_window_init(bg_x11_grab_window_t * win, gavl_video_format_t * format) { win->flags = win->cfg_flags; if(!win->dpy) { if(!realize_window(win)) return 0; } if(win->flags & GRAB_ROOT) { /* TODO */ format->image_width = win->root_width; format->image_height = win->root_height; win->grab_rect.x = 0; win->grab_rect.y = 0; win->grab_rect.w = win->root_width; win->grab_rect.h = win->root_height; } else { format->image_width = win->win_rect.w; format->image_height = win->win_rect.h; gavl_rectangle_i_copy(&win->grab_rect, &win->win_rect); } /* Common format parameters */ format->pixel_width = 1; format->pixel_height = 1; format->pixelformat = win->pixelformat; format->framerate_mode = GAVL_FRAMERATE_VARIABLE; format->timescale = 1000; format->frame_duration = 0; format->frame_width = format->image_width; format->frame_height = format->image_height; gavl_video_format_copy(&win->format, format); /* Create image */ if(win->use_shm) { win->frame = gavl_video_frame_create(NULL); win->image = XShmCreateImage(win->dpy, win->visual, win->depth, ZPixmap, NULL, &win->shminfo, format->frame_width, format->frame_height); win->shminfo.shmid = shmget(IPC_PRIVATE, win->image->bytes_per_line * win->image->height, IPC_CREAT|0777); if(win->shminfo.shmid == -1) { bg_log(BG_LOG_ERROR, LOG_DOMAIN, "Couldn't get shared memory segment"); return 0; } win->shminfo.shmaddr = shmat(win->shminfo.shmid, 0, 0); win->image->data = win->shminfo.shmaddr; if(!XShmAttach(win->dpy, &win->shminfo)) { bg_log(BG_LOG_ERROR, LOG_DOMAIN, "Couldn't attach shared memory segment"); return 0; } win->frame->planes[0] = (uint8_t*)win->image->data; win->frame->strides[0] = win->image->bytes_per_line; bg_log(BG_LOG_INFO, LOG_DOMAIN, "Using shared memory for grabbing"); } else { win->frame = gavl_video_frame_create(format); win->image = XCreateImage(win->dpy, win->visual, win->depth, ZPixmap, 0, (char*)(win->frame->planes[0]), format->frame_width, format->frame_height, 32, win->frame->strides[0]); } if(win->flags & DRAW_CURSOR) { gavl_overlay_blend_context_init(win->blend, &win->format, &win->cursor_format); #ifdef HAVE_XFIXES if(win->use_xfixes) win->cursor_changed = 1; #endif win->cursor_x = INT_MIN; win->cursor_y = INT_MIN; } create_window(win); handle_events(win); gavl_timer_set(win->timer, 0); gavl_timer_start(win->timer); if(win->flags & DISABLE_SCREENSAVER) bg_x11_screensaver_disable(&win->scr); return 1; } void bg_x11_grab_window_close(bg_x11_grab_window_t * win) { gavl_timer_stop(win->timer); bg_x11_screensaver_enable(&win->scr); if(win->use_shm) { gavl_video_frame_null(win->frame); gavl_video_frame_destroy(win->frame); XShmDetach(win->dpy, &win->shminfo); shmdt(win->shminfo.shmaddr); shmctl(win->shminfo.shmid, IPC_RMID, NULL); XDestroyImage(win->image); } else { gavl_video_frame_destroy(win->frame); win->image->data = NULL; XDestroyImage(win->image); } if(!(win->flags & GRAB_ROOT)) { XUnmapWindow(win->dpy, win->win); XSync(win->dpy, False); } // handle_events(win); XDestroyWindow(win->dpy, win->win); win->win = None; } #ifdef HAVE_XFIXES static void get_cursor_xfixes(bg_x11_grab_window_t * win) { int i, j; unsigned long * src; uint8_t * dst; XFixesCursorImage *im; im = XFixesGetCursorImage(win->dpy); win->cursor.ovl_rect.w = im->width; win->cursor.ovl_rect.h = im->height; if(win->cursor.ovl_rect.w > MAX_CURSOR_SIZE) { bg_log(BG_LOG_ERROR, LOG_DOMAIN, "Cursor too wide, increase MAX_CURSOR_SIZE in grab.c to %d", win->cursor.ovl_rect.w); win->cursor.ovl_rect.w = MAX_CURSOR_SIZE; } if(win->cursor.ovl_rect.h > MAX_CURSOR_SIZE) { bg_log(BG_LOG_ERROR, LOG_DOMAIN, "Cursor too high, increase MAX_CURSOR_SIZE in grab.c to %d", win->cursor.ovl_rect.h); win->cursor.ovl_rect.h = MAX_CURSOR_SIZE; } win->cursor_off_x = im->xhot; win->cursor_off_y = im->yhot; for(i = 0; i < win->cursor.ovl_rect.h; i++) { src = (im->pixels) + i * im->width; dst = win->cursor.frame->planes[0] + i * win->cursor.frame->strides[0]; for(j = 0; j < win->cursor.ovl_rect.w; j++) { dst[3] = *src >> 24; // A dst[0] = (*src >> 16) & 0xff; // R dst[1] = (*src >> 8) & 0xff; // G dst[2] = (*src) & 0xff; // B dst += 4; src ++; } } win->cursor_changed = 0; XFree(im); } #endif static void draw_cursor(bg_x11_grab_window_t * win, gavl_rectangle_i_t * rect, gavl_video_frame_t * frame) { Window root; Window child; int root_x; int root_y; int win_x; int win_y; unsigned int mask; int init_blend = 0; if(!XQueryPointer(win->dpy, win->root, &root, &child, &root_x, &root_y, &win_x, &win_y, &mask)) return; /* Bounding box check */ if(root_x >= rect->x + rect->w + MAX_CURSOR_SIZE) return; if(root_x + MAX_CURSOR_SIZE < rect->x) return; if(root_y >= rect->y + rect->h + MAX_CURSOR_SIZE) return; if(root_y + MAX_CURSOR_SIZE < rect->y) return; win->cursor.dst_x = root_x - rect->x - win->cursor_off_x; win->cursor.dst_y = root_y - rect->y - win->cursor_off_y; if((win->cursor.dst_x != win->cursor_x) || (win->cursor.dst_y != win->cursor_y)) init_blend = 1; #ifdef HAVE_XFIXES if(win->cursor_changed) { init_blend = 1; get_cursor_xfixes(win); } #endif if(init_blend) { gavl_overlay_blend_context_set_overlay(win->blend, &win->cursor); } gavl_overlay_blend(win->blend, frame); // fprintf(stderr, "Cursor 2: %d %d\n", win->cursor.dst_x, win->cursor.dst_y); win->cursor_x = win->cursor.dst_x; win->cursor_x = win->cursor.dst_y; } int bg_x11_grab_window_grab(bg_x11_grab_window_t * win, gavl_video_frame_t * frame) { int crop_left = 0; int crop_right = 0; int crop_top = 0; int crop_bottom = 0; gavl_rectangle_i_t rect; handle_events(win); /* Crop */ if(win->use_shm) { gavl_rectangle_i_copy(&rect, &win->grab_rect); if(rect.x < 0) rect.x = 0; if(rect.y < 0) rect.y = 0; if(rect.x + rect.w > win->root_width) rect.x = win->root_width - rect.w; if(rect.y + rect.h > win->root_height) rect.y = win->root_height - rect.h; // fprintf(stderr, "XShmGetImage %d %d\n", rect.x, rect.y); if(!XShmGetImage(win->dpy, win->root, win->image, rect.x, rect.y, AllPlanes)) { bg_log(BG_LOG_ERROR, LOG_DOMAIN, "XShmGetImage failed"); } } else { if(win->grab_rect.x < 0) crop_left = -win->grab_rect.x; if(win->grab_rect.y < 0) crop_top = -win->grab_rect.y; if(win->grab_rect.x + win->grab_rect.w > win->root_width) crop_right = win->grab_rect.x + win->grab_rect.w - win->root_width; if(win->grab_rect.y + win->grab_rect.h > win->root_height) crop_bottom = win->grab_rect.y + win->grab_rect.h - win->root_height; if(crop_left || crop_right || crop_top || crop_bottom) { gavl_video_frame_clear(win->frame, &win->format); } gavl_rectangle_i_copy(&rect, &win->grab_rect); rect.x += crop_left; rect.y += crop_top; rect.w -= (crop_left + crop_right); rect.h -= (crop_top + crop_bottom); XGetSubImage(win->dpy, win->root, rect.x, rect.y, rect.w, rect.h, AllPlanes, ZPixmap, win->image, crop_left, crop_top); } gavl_video_frame_copy(&win->format, frame, win->frame); if(win->flags & DRAW_CURSOR) draw_cursor(win, &rect, frame); frame->timestamp = gavl_time_scale(win->format.timescale, gavl_timer_get(win->timer)); return 1; } gmerlin-1.2.0~dfsg/lib/x11/Makefile.in0000644000175000017500000004552311764363424017340 0ustar alessioalessio# Makefile.in generated by automake 1.11.1 from Makefile.am. # @configure_input@ # Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, # 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation, # Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ VPATH = @srcdir@ pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ subdir = lib/x11 DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/m4/check_funcs.m4 \ $(top_srcdir)/m4/gavl_simd.m4 $(top_srcdir)/m4/gettext.m4 \ $(top_srcdir)/m4/iconv.m4 $(top_srcdir)/m4/lib-ld.m4 \ $(top_srcdir)/m4/lib-link.m4 $(top_srcdir)/m4/lib-prefix.m4 \ $(top_srcdir)/m4/lqt_opt_cflags.m4 $(top_srcdir)/m4/nls.m4 \ $(top_srcdir)/m4/po.m4 $(top_srcdir)/m4/progtest.m4 \ $(top_srcdir)/acinclude.m4 $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/include/config.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = LTLIBRARIES = $(noinst_LTLIBRARIES) am__DEPENDENCIES_1 = libx11_la_DEPENDENCIES = $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ $(am__DEPENDENCIES_1) am__libx11_la_SOURCES_DIST = grab.c icon.c shm.c x11_event.c x11_gl.c \ x11_video.c x11_window.c overlay.c screensaver.c ximage.c \ glvideo.c xvideo.c @HAVE_GLX_TRUE@am__objects_1 = glvideo.lo @HAVE_XV_TRUE@am__objects_2 = xvideo.lo am_libx11_la_OBJECTS = grab.lo icon.lo shm.lo x11_event.lo x11_gl.lo \ x11_video.lo x11_window.lo overlay.lo screensaver.lo ximage.lo \ $(am__objects_1) $(am__objects_2) libx11_la_OBJECTS = $(am_libx11_la_OBJECTS) DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)/include depcomp = $(SHELL) $(top_srcdir)/depcomp am__depfiles_maybe = depfiles am__mv = mv -f COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) LTCOMPILE = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \ --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) CCLD = $(CC) LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \ --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \ $(LDFLAGS) -o $@ SOURCES = $(libx11_la_SOURCES) DIST_SOURCES = $(am__libx11_la_SOURCES_DIST) ETAGS = etags CTAGS = ctags DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ ALSA_CFLAGS = @ALSA_CFLAGS@ ALSA_LIBS = @ALSA_LIBS@ ALSA_REQUIRED = @ALSA_REQUIRED@ AMTAR = @AMTAR@ AR = @AR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ BG_VERSION = @BG_VERSION@ BG_VERSION_MAJOR = @BG_VERSION_MAJOR@ BG_VERSION_MICRO = @BG_VERSION_MICRO@ BG_VERSION_MINOR = @BG_VERSION_MINOR@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CDDB_CFLAGS = @CDDB_CFLAGS@ CDDB_LIBS = @CDDB_LIBS@ CDIO_CDDA_CFLAGS = @CDIO_CDDA_CFLAGS@ CDIO_CDDA_LIBS = @CDIO_CDDA_LIBS@ CDIO_CFLAGS = @CDIO_CFLAGS@ CDIO_LIBS = @CDIO_LIBS@ CDIO_PARANOIA_CFLAGS = @CDIO_PARANOIA_CFLAGS@ CDIO_PARANOIA_LIBS = @CDIO_PARANOIA_LIBS@ CDIO_REQUIRED = @CDIO_REQUIRED@ CFLAGS = @CFLAGS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CYGPATH_W = @CYGPATH_W@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DOXYGEN = @DOXYGEN@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ ESD_CFLAGS = @ESD_CFLAGS@ ESD_CONFIG = @ESD_CONFIG@ ESD_LIBS = @ESD_LIBS@ ESD_REQUIRED = @ESD_REQUIRED@ EXEEXT = @EXEEXT@ FGREP = @FGREP@ FONTCONFIG_CFLAGS = @FONTCONFIG_CFLAGS@ FONTCONFIG_LIBS = @FONTCONFIG_LIBS@ FREETYPE_CFLAGS = @FREETYPE_CFLAGS@ FREETYPE_LIBS = @FREETYPE_LIBS@ GAVL_CFLAGS = @GAVL_CFLAGS@ GAVL_LIBS = @GAVL_LIBS@ GAVL_REQUIRED = @GAVL_REQUIRED@ GLX_CFLAGS = @GLX_CFLAGS@ GLX_LIBS = @GLX_LIBS@ GL_CFLAGS = @GL_CFLAGS@ GL_LIBS = @GL_LIBS@ GMERLIN_DEP_LIBS = @GMERLIN_DEP_LIBS@ GMERLIN_PLUGIN_LDFLAGS = @GMERLIN_PLUGIN_LDFLAGS@ GMSGFMT = @GMSGFMT@ GMSGFMT_015 = @GMSGFMT_015@ GREP = @GREP@ GTK_CFLAGS = @GTK_CFLAGS@ GTK_LIBS = @GTK_LIBS@ GTK_REQUIRED = @GTK_REQUIRED@ ICONV_LIBS = @ICONV_LIBS@ INCLUDES = -I$(top_srcdir)/include INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ INTLLIBS = @INTLLIBS@ INTL_MACOSX_LIBS = @INTL_MACOSX_LIBS@ JACK_CFLAGS = @JACK_CFLAGS@ JACK_LIBS = @JACK_LIBS@ JACK_REQUIRED = @JACK_REQUIRED@ JPEG_CFLAGS = @JPEG_CFLAGS@ JPEG_LIBS = @JPEG_LIBS@ JPEG_REQUIRED = @JPEG_REQUIRED@ LD = @LD@ LDFLAGS = @LDFLAGS@ LIBCDDB_REQUIRED = @LIBCDDB_REQUIRED@ LIBEXIF_CFLAGS = @LIBEXIF_CFLAGS@ LIBEXIF_LIBS = @LIBEXIF_LIBS@ LIBICONV = @LIBICONV@ LIBINTL = @LIBINTL@ LIBM = @LIBM@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIPO = @LIPO@ LN_S = @LN_S@ LQT_CFLAGS = @LQT_CFLAGS@ LQT_LIBS = @LQT_LIBS@ LQT_REQUIRED = @LQT_REQUIRED@ LTLIBICONV = @LTLIBICONV@ LTLIBINTL = @LTLIBINTL@ LTLIBOBJS = @LTLIBOBJS@ LTVERSION_AGE = @LTVERSION_AGE@ LTVERSION_CURRENT = @LTVERSION_CURRENT@ LTVERSION_REVISION = @LTVERSION_REVISION@ LV_CFLAGS = @LV_CFLAGS@ LV_LIBS = @LV_LIBS@ LV_REQUIRED = @LV_REQUIRED@ MAKEINFO = @MAKEINFO@ MKDIR_P = @MKDIR_P@ MODULE_LIBADD = @MODULE_LIBADD@ MSGFMT = @MSGFMT@ MSGFMT_015 = @MSGFMT_015@ MSGMERGE = @MSGMERGE@ MUSICBRAINZ_CFLAGS = @MUSICBRAINZ_CFLAGS@ MUSICBRAINZ_LIBS = @MUSICBRAINZ_LIBS@ MUSICBRAINZ_REQUIRED = @MUSICBRAINZ_REQUIRED@ NM = @NM@ NMEDIT = @NMEDIT@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OTOOL = @OTOOL@ OTOOL64 = @OTOOL64@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PKG_CONFIG = @PKG_CONFIG@ PNG_CFLAGS = @PNG_CFLAGS@ PNG_LIBS = @PNG_LIBS@ PNG_REQUIRED = @PNG_REQUIRED@ POSUB = @POSUB@ PULSEAUDIO_CFLAGS = @PULSEAUDIO_CFLAGS@ PULSEAUDIO_LIBS = @PULSEAUDIO_LIBS@ PULSEAUDIO_REQUIRED = @PULSEAUDIO_REQUIRED@ RANLIB = @RANLIB@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ SQLITE3_LIBS = @SQLITE3_LIBS@ STRIP = @STRIP@ TEXINFO = @TEXINFO@ TIFF_CFLAGS = @TIFF_CFLAGS@ TIFF_LIBS = @TIFF_LIBS@ TIFF_REQUIRED = @TIFF_REQUIRED@ TOP_SRCDIR = @TOP_SRCDIR@ USE_NLS = @USE_NLS@ V4LCONVERT_CFLAGS = @V4LCONVERT_CFLAGS@ V4LCONVERT_LIBS = @V4LCONVERT_LIBS@ V4LCONVERT_REQUIRED = @V4LCONVERT_REQUIRED@ VERSION = @VERSION@ XDPMS_LIBS = @XDPMS_LIBS@ XFIXES_LIBS = @XFIXES_LIBS@ XGETTEXT = @XGETTEXT@ XGETTEXT_015 = @XGETTEXT_015@ XINERAMA_LIBS = @XINERAMA_LIBS@ XMKMF = @XMKMF@ XML2_CFLAGS = @XML2_CFLAGS@ XML2_LIBS = @XML2_LIBS@ XML2_REQUIRED = @XML2_REQUIRED@ XTEST_LIBS = @XTEST_LIBS@ XV_LIBS = @XV_LIBS@ X_CFLAGS = @X_CFLAGS@ X_LIBS = @X_LIBS@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_CC = @ac_ct_CC@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_vendor = @build_vendor@ builddir = @builddir@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ lt_ECHO = @lt_ECHO@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ plugindir = $(pkglibdir)/plugins AM_CFLAGS = \ @X_CFLAGS@ \ -DLOCALE_DIR=\"$(localedir)\" \ -DPLUGIN_DIR=\"$(plugindir)\" \ -DDOC_DIR=\"$(docdir)\" \ -DDATA_DIR=\"$(pkgdatadir)\" @HAVE_XV_FALSE@xv_sources = @HAVE_XV_TRUE@xv_sources = xvideo.c @HAVE_XV_FALSE@xv_libs = @HAVE_XV_TRUE@xv_libs = @XV_LIBS@ @HAVE_GLX_FALSE@glx_sources = @HAVE_GLX_TRUE@glx_sources = glvideo.c @HAVE_GLX_FALSE@glx_libs = @HAVE_GLX_TRUE@glx_libs = @GL_LIBS@ @HAVE_XTEST_FALSE@xtest_libs = @HAVE_XTEST_TRUE@xtest_libs = @XTEST_LIBS@ noinst_LTLIBRARIES = \ libx11.la libx11_la_SOURCES = \ grab.c \ icon.c \ shm.c \ x11_event.c \ x11_gl.c \ x11_video.c \ x11_window.c \ overlay.c \ screensaver.c \ ximage.c \ $(glx_sources) \ $(xv_sources) libx11_la_LIBADD = @GMERLIN_DEP_LIBS@ @XINERAMA_LIBS@ @XFIXES_LIBS@ @XDPMS_LIBS@ $(xv_libs) $(glx_libs) $(xtest_libs) @X_LIBS@ all: all-am .SUFFIXES: .SUFFIXES: .c .lo .o .obj $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ && { if test -f $@; then exit 0; else break; fi; }; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu lib/x11/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --gnu lib/x11/Makefile .PRECIOUS: Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): clean-noinstLTLIBRARIES: -test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES) @list='$(noinst_LTLIBRARIES)'; for p in $$list; do \ dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \ test "$$dir" != "$$p" || dir=.; \ echo "rm -f \"$${dir}/so_locations\""; \ rm -f "$${dir}/so_locations"; \ done libx11.la: $(libx11_la_OBJECTS) $(libx11_la_DEPENDENCIES) $(LINK) $(libx11_la_OBJECTS) $(libx11_la_LIBADD) $(LIBS) mostlyclean-compile: -rm -f *.$(OBJEXT) distclean-compile: -rm -f *.tab.c @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/glvideo.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/grab.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/icon.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/overlay.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/screensaver.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/shm.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/x11_event.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/x11_gl.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/x11_video.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/x11_window.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ximage.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/xvideo.Plo@am__quote@ .c.o: @am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(COMPILE) -c $< .c.obj: @am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(COMPILE) -c `$(CYGPATH_W) '$<'` .c.lo: @am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(LTCOMPILE) -c -o $@ $< mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | \ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in files) print i; }; }'`; \ mkid -fID $$unique tags: TAGS TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ $(TAGS_FILES) $(LISP) set x; \ here=`pwd`; \ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | \ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in files) print i; }; }'`; \ shift; \ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ test -n "$$unique" || unique=$$empty_fix; \ if test $$# -gt 0; then \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ "$$@" $$unique; \ else \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ $$unique; \ fi; \ fi ctags: CTAGS CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ $(TAGS_FILES) $(LISP) list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | \ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in files) print i; }; }'`; \ test -z "$(CTAGS_ARGS)$$unique" \ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ $$unique GTAGS: here=`$(am__cd) $(top_builddir) && pwd` \ && $(am__cd) $(top_srcdir) \ && gtags -i $(GTAGS_ARGS) "$$here" distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags distdir: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done check-am: all-am check: check-am all-am: Makefile $(LTLIBRARIES) installdirs: install: install-am install-exec: install-exec-am install-data: install-data-am uninstall: uninstall-am install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-am install-strip: $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ `test -z '$(STRIP)' || \ echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install mostlyclean-generic: clean-generic: distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." clean: clean-am clean-am: clean-generic clean-libtool clean-noinstLTLIBRARIES \ mostlyclean-am distclean: distclean-am -rm -rf ./$(DEPDIR) -rm -f Makefile distclean-am: clean-am distclean-compile distclean-generic \ distclean-tags dvi: dvi-am dvi-am: html: html-am html-am: info: info-am info-am: install-data-am: install-dvi: install-dvi-am install-dvi-am: install-exec-am: install-html: install-html-am install-html-am: install-info: install-info-am install-info-am: install-man: install-pdf: install-pdf-am install-pdf-am: install-ps: install-ps-am install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-am -rm -rf ./$(DEPDIR) -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-compile mostlyclean-generic \ mostlyclean-libtool pdf: pdf-am pdf-am: ps: ps-am ps-am: uninstall-am: .MAKE: install-am install-strip .PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \ clean-libtool clean-noinstLTLIBRARIES ctags distclean \ distclean-compile distclean-generic distclean-libtool \ distclean-tags distdir dvi dvi-am html html-am info info-am \ install install-am install-data install-data-am install-dvi \ install-dvi-am install-exec install-exec-am install-html \ install-html-am install-info install-info-am install-man \ install-pdf install-pdf-am install-ps install-ps-am \ install-strip installcheck installcheck-am installdirs \ maintainer-clean maintainer-clean-generic mostlyclean \ mostlyclean-compile mostlyclean-generic mostlyclean-libtool \ pdf pdf-am ps ps-am tags uninstall uninstall-am # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: gmerlin-1.2.0~dfsg/lib/x11/screensaver.c0000644000175000017500000001332411764363410017744 0ustar alessioalessio/***************************************************************** * gmerlin - a general purpose multimedia framework and applications * * Copyright (c) 2001 - 2011 Members of the Gmerlin project * gmerlin-general@lists.sourceforge.net * http://gmerlin.sourceforge.net * * 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 of the License, 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 this program. If not, see . * *****************************************************************/ #include #include #include #ifdef HAVE_XTEST #include #endif #include #include void bg_x11_screensaver_init(bg_x11_screensaver_t * scr, Display * dpy) { char * env; #ifdef HAVE_XTEST int dummy; #endif scr->dpy = dpy; scr->timer = gavl_timer_create(); /* Get the screensaver mode */ #ifdef HAVE_XTEST if(XTestQueryExtension(scr->dpy, &dummy, &dummy, &dummy, &dummy)) { scr->mode = SCREENSAVER_MODE_XTEST; // scr->fake_keycode = XKeysymToKeycode(scr->dpy, XK_Shift_L); // fprintf(stderr, "Xtest detected\n"); return; } // else // fprintf(stderr, "No Xtest detected\n"); #endif /* Check for gnome */ env = getenv("GNOME_DESKTOP_SESSION_ID"); if(env) { scr->mode = SCREENSAVER_MODE_GNOME; return; } /* Check for KDE */ env = getenv("KDE_FULL_SESSION"); if(env && !strcmp(env, "true")) { scr->mode = SCREENSAVER_MODE_KDE; return; } /* TODO: xfce4 */ } static int check_ping(bg_x11_screensaver_t * scr, int force, int seconds) { gavl_time_t cur = gavl_timer_get(scr->timer); if(force || ((cur - scr->last_ping_time) / GAVL_TIME_SCALE >= seconds)) { scr->last_ping_time = cur; return 1; } return 0; } static void screensaver_ping(bg_x11_screensaver_t * scr, int force) { if(!scr->disabled) return; switch(scr->mode) { case SCREENSAVER_MODE_XLIB: break; case SCREENSAVER_MODE_GNOME: if(check_ping(scr, force, 40)) bg_system("gnome-screensaver-command --poke > /dev/null 2> /dev/null"); break; case SCREENSAVER_MODE_KDE: break; #ifdef HAVE_XTEST case SCREENSAVER_MODE_XTEST: if(check_ping(scr, force, 40)) { XTestFakeRelativeMotionEvent(scr->dpy, 1, 1, CurrentTime); scr->fake_motion++; // fprintf(stderr, "Sent fake motion event\n"); } break; #endif } } void bg_x11_screensaver_ping(bg_x11_screensaver_t * scr) { screensaver_ping(scr, 0); } void bg_x11_screensaver_enable(bg_x11_screensaver_t * scr) { int dummy, interval, prefer_blank, allow_exp; if(!scr->dpy || !scr->timer) return; gavl_timer_stop(scr->timer); if(!scr->disabled) return; #if HAVE_XDPMS if(scr->dpms_disabled) { if(DPMSQueryExtension(scr->dpy, &dummy, &dummy)) { if(DPMSEnable(scr->dpy)) { // DPMS does not seem to be enabled unless we call DPMSInfo BOOL onoff; CARD16 state; DPMSForceLevel(scr->dpy, DPMSModeOn); DPMSInfo(scr->dpy, &state, &onoff); } } scr->dpms_disabled = 0; } #endif // HAVE_XDPMS scr->disabled = 0; if(!scr->was_enabled) return; switch(scr->mode) { case SCREENSAVER_MODE_XLIB: XGetScreenSaver(scr->dpy, &dummy, &interval, &prefer_blank, &allow_exp); XSetScreenSaver(scr->dpy, scr->saved_timeout, interval, prefer_blank, allow_exp); break; case SCREENSAVER_MODE_GNOME: break; case SCREENSAVER_MODE_KDE: break; } } void bg_x11_screensaver_disable(bg_x11_screensaver_t * scr) { int interval, prefer_blank, allow_exp; #if HAVE_XDPMS int nothing; #endif // HAVE_XDPMS gavl_timer_start(scr->timer); if(scr->disabled) return; #if HAVE_XDPMS if(DPMSQueryExtension(scr->dpy, ¬hing, ¬hing)) { BOOL onoff; CARD16 state; DPMSInfo(scr->dpy, &state, &onoff); if(onoff) { scr->dpms_disabled = 1; DPMSDisable(scr->dpy); // monitor powersave off } } #endif // HAVE_XDPMS switch(scr->mode) { case SCREENSAVER_MODE_XLIB: XGetScreenSaver(scr->dpy, &scr->saved_timeout, &interval, &prefer_blank, &allow_exp); if(scr->saved_timeout) scr->was_enabled = 1; else scr->was_enabled = 0; XSetScreenSaver(scr->dpy, 0, interval, prefer_blank, allow_exp); break; case SCREENSAVER_MODE_GNOME: break; case SCREENSAVER_MODE_XTEST: scr->fake_motion = 0; break; case SCREENSAVER_MODE_KDE: scr->was_enabled = (bg_system ("dcop kdesktop KScreensaverIface isEnabled 2>/dev/null | sed 's/1/true/g' | grep true 2>/dev/null >/dev/null") == 0); if(scr->was_enabled) bg_system("dcop kdesktop KScreensaverIface enable false > /dev/null"); break; } scr->disabled = 1; screensaver_ping(scr, 1); } void bg_x11_screensaver_cleanup(bg_x11_screensaver_t * scr) { if(scr->timer) gavl_timer_destroy(scr->timer); } gmerlin-1.2.0~dfsg/lib/x11/ximage.c0000644000175000017500000001210611764363410016673 0ustar alessioalessio/***************************************************************** * gmerlin - a general purpose multimedia framework and applications * * Copyright (c) 2001 - 2011 Members of the Gmerlin project * gmerlin-general@lists.sourceforge.net * http://gmerlin.sourceforge.net * * 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 of the License, 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 this program. If not, see . * *****************************************************************/ #include #include /* XImage video driver */ static int init_ximage(driver_data_t * d) { d->pixelformats = malloc(2*sizeof(*d->pixelformats)); d->pixelformats[0] = bg_x11_window_get_pixelformat(d->win->dpy, d->win->visual, d->win->depth); d->pixelformats[1] = GAVL_PIXELFORMAT_NONE; return 1; } typedef struct { XImage * x11_image; XShmSegmentInfo shminfo; } ximage_frame_t; static gavl_video_frame_t * create_frame_ximage(driver_data_t * d) { ximage_frame_t * frame; gavl_video_frame_t * ret; bg_x11_window_t * w = d->win; frame = calloc(1, sizeof(*frame)); if(w->have_shm) { /* Create Shm Image */ frame->x11_image = XShmCreateImage(w->dpy, w->visual, w->depth, ZPixmap, NULL, &frame->shminfo, w->window_format.frame_width, w->window_format.frame_height); if(!frame->x11_image) w->have_shm = 0; else { if(!bg_x11_window_create_shm(w, &frame->shminfo, frame->x11_image->height * frame->x11_image->bytes_per_line)) { XDestroyImage(frame->x11_image); w->have_shm = 0; } frame->x11_image->data = frame->shminfo.shmaddr; ret = calloc(1, sizeof(*ret)); ret->planes[0] = (uint8_t*)(frame->x11_image->data); ret->strides[0] = frame->x11_image->bytes_per_line; } } if(!w->have_shm) { /* Use gavl to allocate memory aligned scanlines */ ret = gavl_video_frame_create(&w->window_format); frame->x11_image = XCreateImage(w->dpy, w->visual, w->depth, ZPixmap, 0, (char*)(ret->planes[0]), w->window_format.frame_width, w->window_format.frame_height, 32, ret->strides[0]); } ret->user_data = frame; return ret; } static void put_frame_ximage(driver_data_t * d, gavl_video_frame_t * f) { ximage_frame_t * frame = (ximage_frame_t*)f->user_data; bg_x11_window_t * w = d->win; if(w->have_shm) { XShmPutImage(w->dpy, /* dpy */ w->current->win, /* d */ w->gc, /* gc */ frame->x11_image, /* image */ w->dst_rect.x, /* src_x */ w->dst_rect.y, /* src_y */ w->dst_rect.x, /* dst_x */ w->dst_rect.y, /* dst_y */ w->dst_rect.w, /* src_width */ w->dst_rect.h, /* src_height */ True /* send_event */); w->wait_for_completion = 1; } else { XPutImage(w->dpy, /* dpy */ w->current->win, /* d */ w->gc, /* gc */ frame->x11_image, /* image */ w->dst_rect.x, /* src_x */ w->dst_rect.y, /* src_y */ w->dst_rect.x, /* dst_x */ w->dst_rect.y, /* dst_y */ w->dst_rect.w, /* src_width */ w->dst_rect.h); /* src_height */ } } static void destroy_frame_ximage(driver_data_t * d, gavl_video_frame_t * f) { ximage_frame_t * frame = (ximage_frame_t*)f->user_data; bg_x11_window_t * w = d->win; if(frame->x11_image) XFree(frame->x11_image); if(w->have_shm) { bg_x11_window_destroy_shm(w, &frame->shminfo); gavl_video_frame_null(f); gavl_video_frame_destroy(f); } else { gavl_video_frame_destroy(f); } free(frame); } const video_driver_t ximage_driver = { .name = "XImage", .init = init_ximage, .create_frame = create_frame_ximage, .put_frame = put_frame_ximage, .destroy_frame = destroy_frame_ximage }; gmerlin-1.2.0~dfsg/lib/ovl2text.c0000644000175000017500000001655211764363410016610 0ustar alessioalessio/***************************************************************** * gmerlin - a general purpose multimedia framework and applications * * Copyright (c) 2001 - 2011 Members of the Gmerlin project * gmerlin-general@lists.sourceforge.net * http://gmerlin.sourceforge.net * * 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 of the License, 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 this program. If not, see . * *****************************************************************/ #include #include #include #include #include #include #include #define LOG_DOMAIN "ovl2text" #include typedef struct { bg_encoder_callbacks_t * cb; bg_plugin_registry_t * plugin_reg; gavl_video_format_t format; bg_ocr_t * ocr; bg_parameter_info_t * parameters; bg_plugin_handle_t * enc_handle; bg_encoder_plugin_t * enc_plugin; } ovl2text_t; void * bg_ovl2text_create(bg_plugin_registry_t * plugin_reg) { ovl2text_t * ret = calloc(1, sizeof(*ret)); ret->plugin_reg = plugin_reg; ret->ocr = bg_ocr_create(ret->plugin_reg); return ret; } static void set_callbacks_ovl2text(void * data, bg_encoder_callbacks_t * cb) { ovl2text_t * e = data; e->cb = cb; } static int open_ovl2text(void * data, const char * filename, const gavl_metadata_t * metadata, const bg_chapter_list_t * chapter_list) { ovl2text_t * e = data; /* Open text subtitle encoder */ if(!e->enc_plugin || !e->enc_plugin->open(e->enc_handle->priv, filename, metadata, chapter_list)) return 0; return 1; } static int add_subtitle_overlay_stream_ovl2text(void * priv, const gavl_metadata_t * m, const gavl_video_format_t * format) { const char * language; ovl2text_t * e = priv; language = gavl_metadata_get(m, GAVL_META_LANGUAGE); if(!bg_ocr_init(e->ocr, format, language)) return -1; gavl_video_format_copy(&e->format, format); if(!e->enc_plugin || (e->enc_plugin->add_subtitle_text_stream(e->enc_handle->priv, m, &e->format.timescale) < 0)) return -1; return 0; } static int start_ovl2text(void * priv) { ovl2text_t * e = priv; if(e->enc_plugin->start && !e->enc_plugin->start(e->enc_handle->priv)) return 0; return 1; } static void get_subtitle_overlay_format_ovl2text(void * priv, int stream, gavl_video_format_t*ret) { ovl2text_t * e = priv; gavl_video_format_copy(ret, &e->format); } static int write_subtitle_overlay_ovl2text(void * priv, gavl_overlay_t * ovl, int stream) { int ret = 0; char * str = NULL; ovl2text_t * e = priv; bg_ocr_run(e->ocr, &e->format, ovl->frame, &str); if(str) ret = e->enc_plugin->write_subtitle_text(e->enc_handle->priv, str, ovl->frame->timestamp, ovl->frame->duration, stream); return ret; } static int close_ovl2text(void * priv, int do_delete) { ovl2text_t * e = priv; e->enc_plugin->close(e->enc_handle->priv, do_delete); return 1; } static void destroy_ovl2text(void * priv) { ovl2text_t * e = priv; bg_ocr_destroy(e->ocr); if(e->parameters) bg_parameter_info_destroy_array(e->parameters); if(e->enc_handle) bg_plugin_unref(e->enc_handle); free(e); } static const bg_parameter_info_t enc_section[] = { { .name = "plugin", .long_name = TRS("Plugin"), .type = BG_PARAMETER_MULTI_MENU, .help_string = TRS("Plugin for writing the text subtitles"), }, { /* End */ } }; static bg_parameter_info_t * create_parameters(bg_plugin_registry_t * plugin_reg) { const bg_parameter_info_t * info[3]; bg_parameter_info_t * enc; bg_parameter_info_t * ret; enc = bg_parameter_info_copy_array(enc_section); bg_plugin_registry_set_parameter_info(plugin_reg, BG_PLUGIN_ENCODER_SUBTITLE_TEXT, BG_PLUGIN_FILE, &enc[0]); info[0] = bg_ocr_get_parameters(); info[1] = enc; info[2] = NULL; ret = bg_parameter_info_concat_arrays(info); bg_parameter_info_destroy_array(enc); return ret; } static const bg_parameter_info_t * get_parameters_ovl2text(void * priv) { ovl2text_t * e = priv; if(e->parameters) return e->parameters; /* Create parameters */ e->parameters = create_parameters(e->plugin_reg); return e->parameters; } static void set_parameter_ovl2text(void * priv, const char * name, const bg_parameter_value_t * val) { ovl2text_t * e = priv; if(!name) { bg_ocr_set_parameter(e->ocr, NULL, NULL); return; } else if(bg_ocr_set_parameter(e->ocr, name, val)) return; else if(!strcmp(name, "plugin")) { const bg_plugin_info_t * info; if(e->enc_handle) { bg_plugin_unref(e->enc_handle); e->enc_handle = NULL; } info = bg_plugin_find_by_name(e->plugin_reg, val->val_str); e->enc_handle = bg_plugin_load(e->plugin_reg, info); e->enc_plugin = (bg_encoder_plugin_t*)(e->enc_handle->plugin); if(e->enc_plugin->set_callbacks && e->cb) e->enc_plugin->set_callbacks(e->enc_handle->priv, e->cb); } else e->enc_plugin->common.set_parameter(e->enc_handle->priv, name, val); } static const bg_encoder_plugin_t the_plugin = { .common = { BG_LOCALE, .name = "e_ovl2text", /* Unique short name */ .long_name = TRS("Overlay to text converter"), .description = TRS("Exports overlay subtitles to a text format by performing an OCR."), .type = BG_PLUGIN_ENCODER_SUBTITLE_OVERLAY, .flags = BG_PLUGIN_FILE, .priority = BG_PLUGIN_PRIORITY_MAX, .destroy = destroy_ovl2text, .get_parameters = get_parameters_ovl2text, .set_parameter = set_parameter_ovl2text, }, .max_subtitle_overlay_streams = 1, .set_callbacks = set_callbacks_ovl2text, .open = open_ovl2text, .add_subtitle_overlay_stream = add_subtitle_overlay_stream_ovl2text, .start = start_ovl2text, .get_subtitle_overlay_format = get_subtitle_overlay_format_ovl2text, .write_subtitle_overlay = write_subtitle_overlay_ovl2text, .close = close_ovl2text, }; const bg_plugin_common_t * bg_ovl2text_get() { return (bg_plugin_common_t *)&the_plugin; } bg_plugin_info_t * bg_ovl2text_info(bg_plugin_registry_t * reg) { bg_plugin_info_t * ret; ret = bg_plugin_info_create(&the_plugin.common); ret->parameters = create_parameters(reg); return ret; } gmerlin-1.2.0~dfsg/lib/preset.c0000644000175000017500000001602111764363410016312 0ustar alessioalessio/***************************************************************** * gmerlin - a general purpose multimedia framework and applications * * Copyright (c) 2001 - 2011 Members of the Gmerlin project * gmerlin-general@lists.sourceforge.net * http://gmerlin.sourceforge.net * * 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 of the License, 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 this program. If not, see . * *****************************************************************/ #include #include #include #include #include #include #include #include #include #include #include #include #include #define LOG_DOMAIN "preset" static bg_preset_t * append_to_list(bg_preset_t * list, bg_preset_t * p) { if(list) { bg_preset_t * end = list; while(end->next) end = end->next; end->next = p; } else list = p; p->next = NULL; return list; } static bg_preset_t * load_presets(const char * directory, bg_preset_t * ret, int private) { DIR * dir; struct dirent * dent_ptr; struct stat stat_buf; char * filename; bg_preset_t * p; char * pos; char * name; struct { struct dirent d; char b[NAME_MAX]; /* Make sure there is enough memory */ } dent; dir = opendir(directory); if(!dir) return NULL; while(!readdir_r(dir, &dent.d, &dent_ptr)) { if(!dent_ptr) break; if(dent.d.d_name[0] == '.') /* Don't import hidden files */ continue; filename = bg_sprintf("%s/%s", directory, dent.d.d_name); if(stat(filename, &stat_buf) || !S_ISREG(stat_buf.st_mode) || access(filename, R_OK | W_OK)) { free(filename); continue; } /* Got a preset */ p = calloc(1, sizeof(*p)); p->file = filename; /* Preset name is basename of the file */ pos = strrchr(filename, '/'); if(pos) { pos++; name = bg_strdup(NULL, pos); } else name = bg_strdup(NULL, filename); /* Check, if a preset with that name aready exists */ p = ret; while(p) { if(!strcmp(name, p->name)) break; p = p->next; } if(p) { free(name); free(filename); continue; } p = calloc(1, sizeof(*p)); p->name = name; p->file = filename; if(private) p->flags |= BG_PRESET_PRIVATE; ret = append_to_list(ret, p); } closedir(dir); return ret; } static int compare_func(const void * p1, const void * p2) { const bg_preset_t * const * preset1 = p1; const bg_preset_t * const * preset2 = p2; return strcmp((*preset1)->name, (*preset2)->name); } static bg_preset_t * sort_presets(bg_preset_t * p) { int i, num = 0; bg_preset_t ** arr; bg_preset_t * tmp; bg_preset_t * ret; /* Count presets */ tmp = p; while(tmp) { num++; tmp = tmp->next; } if(num < 2) return p; /* Create array */ arr = malloc(num * sizeof(*arr)); tmp = p; for(i = 0; i < num; i++) { arr[i] = tmp; tmp = tmp->next; } /* Sort */ qsort(arr, num, sizeof(*arr), compare_func); /* Array -> chain */ ret = arr[0]; tmp = ret; for(i = 1; i < num; i++) { tmp->next = arr[i]; tmp = tmp->next; } tmp->next = NULL; free(arr); return ret; } bg_preset_t * bg_presets_load(const char * preset_path) { const char * home_dir; char * directory; bg_preset_t * ret = NULL; /* First option: Try home directory */ home_dir = getenv("HOME"); if(home_dir) { directory = bg_sprintf("%s/.gmerlin/presets/%s", home_dir, preset_path); if(!access(directory, R_OK|W_OK|X_OK)) ret = load_presets(directory, ret, 1); free(directory); } /* Second option: system wide directory. We only load presets, which are not available in $HOME */ directory = bg_sprintf("%s/presets/%s", DATA_DIR, preset_path); if(!access(directory, R_OK|W_OK|X_OK)) ret = load_presets(directory, ret, 0); free(directory); return sort_presets(ret); } bg_preset_t * bg_preset_find_by_file(bg_preset_t * presets, const char * file) { while(presets) { if(!strcmp(presets->file, file)) return presets; presets = presets->next; } return NULL; } bg_preset_t * bg_preset_find_by_name(bg_preset_t * presets, const char * name) { while(presets) { if(!strcmp(presets->name, name)) return presets; presets = presets->next; } return NULL; } bg_preset_t * bg_preset_delete(bg_preset_t * presets, bg_preset_t * preset) { bg_preset_t * p; bg_preset_t * ret = NULL; /* First (or only) preset */ if(presets == preset) { ret = preset->next; } /* Later preset */ else { p = presets; while(1) { if(p->next == preset) break; p = p->next; } if(p) p->next = preset->next; ret = presets; } remove(preset->file); if(preset->name) free(preset->name); if(preset->file) free(preset->file); free(preset); return ret; } bg_preset_t * bg_preset_add(bg_preset_t * presets, const char * preset_path, const char * name, const bg_cfg_section_t * s) { char * home_dir; bg_preset_t * p; home_dir = getenv("HOME"); if(!home_dir) { bg_log(BG_LOG_ERROR, LOG_DOMAIN, "Cannot make new preset: No home directory"); return presets; } /* Check if the preset already exists */ p = bg_preset_find_by_name(presets, name); if(!p) { char * dir; dir = bg_sprintf("%s/.gmerlin/presets/%s", home_dir, preset_path); if(!bg_ensure_directory(dir)) { bg_log(BG_LOG_ERROR, LOG_DOMAIN, "Could not create directory: %s", dir); free(dir); return presets; } p = calloc(1, sizeof(*p)); p->name = bg_strdup(p->name, name); p->file = bg_sprintf("%s/%s", dir, name); p->next = presets; presets = p; free(dir); } bg_preset_save(p, s); return sort_presets(presets); } void bg_presets_destroy(bg_preset_t * p) { bg_preset_t * tmp; while(p) { tmp = p->next; if(p->name) free(p->name); if(p->file) free(p->file); free(p); p = tmp; } } gmerlin-1.2.0~dfsg/lib/tree_xml.c0000644000175000017500000001734611764363410016642 0ustar alessioalessio/***************************************************************** * gmerlin - a general purpose multimedia framework and applications * * Copyright (c) 2001 - 2011 Members of the Gmerlin project * gmerlin-general@lists.sourceforge.net * http://gmerlin.sourceforge.net * * 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 of the License, 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 this program. If not, see . * *****************************************************************/ #include #include #include #include #include static bg_album_t * append_album(bg_album_t * list, bg_album_t * new_album) { bg_album_t * a; if(!list) return new_album; a = list; while(a->next) a = a->next; a->next = new_album; return list; } /* tree_xml.c */ static bg_album_t * load_album(xmlDocPtr xml_doc, bg_media_tree_t * tree, xmlNodePtr node, bg_album_t * parent) { bg_album_t * ret = NULL; bg_album_t * child_album; char * tmp_string; xmlNodePtr child; int is_open = 0; tmp_string = BG_XML_GET_PROP(node, "incoming"); if(tmp_string) { ret = bg_album_create(&tree->com, BG_ALBUM_TYPE_INCOMING, parent); xmlFree(tmp_string); } if(!ret) { tmp_string = BG_XML_GET_PROP(node, "favourites"); if(tmp_string) { ret = bg_album_create(&tree->com, BG_ALBUM_TYPE_FAVOURITES, parent); xmlFree(tmp_string); } } if(!ret) { tmp_string = BG_XML_GET_PROP(node, "plugin"); if(tmp_string) { ret = bg_album_create(&tree->com, BG_ALBUM_TYPE_PLUGIN, parent); xmlFree(tmp_string); } } if(!ret) { tmp_string = BG_XML_GET_PROP(node, "tuner"); if(tmp_string) { ret = bg_album_create(&tree->com, BG_ALBUM_TYPE_TUNER, parent); xmlFree(tmp_string); } } if(!ret) { ret = bg_album_create(&tree->com, BG_ALBUM_TYPE_REGULAR, parent); } child = node->children; while(child) { if(!child->name) { child = child->next; continue; } tmp_string = (char*)xmlNodeListGetString(xml_doc, child->children, 1); if(!BG_XML_STRCMP(child->name, "NAME")) ret->name = bg_strdup(ret->name, tmp_string); else if(!BG_XML_STRCMP(child->name, "LOCATION")) ret->xml_file = bg_strdup(ret->xml_file, tmp_string); else if(!BG_XML_STRCMP(child->name, "DEVICE")) ret->device = bg_strdup(ret->device, tmp_string); else if(!BG_XML_STRCMP(child->name, "WATCH_DIR")) ret->watch_dir = bg_strdup(ret->watch_dir, tmp_string); else if(!BG_XML_STRCMP(child->name, "PLUGIN")) ret->plugin_info = bg_plugin_find_by_name(ret->com->plugin_reg, tmp_string); if(tmp_string) xmlFree(tmp_string); child = child->next; } tmp_string = BG_XML_GET_PROP(node, "expanded"); if(tmp_string) { if(atoi(tmp_string)) ret->flags |= BG_ALBUM_EXPANDED; xmlFree(tmp_string); } tmp_string = BG_XML_GET_PROP(node, "open"); if(tmp_string) { if(atoi(tmp_string)) { is_open = 1; } xmlFree(tmp_string); } bg_album_set_default_location(ret); /* Load the album if necessary */ if(is_open) { bg_album_open(ret); } /* Read children */ node = node->children; while(node) { if(node->name && !BG_XML_STRCMP(node->name, "ALBUM")) { child_album = load_album(xml_doc, tree, node, ret); if(child_album) ret->children = append_album(ret->children, child_album); } node = node->next; } return ret; } void bg_media_tree_load(bg_media_tree_t * tree) { xmlDocPtr xml_doc; xmlNodePtr node; bg_album_t * new_album; xml_doc = bg_xml_parse_file(tree->filename); if(!xml_doc) return; node = xml_doc->children; if(BG_XML_STRCMP(node->name, "MEDIATREE")) { xmlFreeDoc(xml_doc); return; } node = node->children; while(node) { if(node->name) { if(!BG_XML_STRCMP(node->name, "ALBUM")) { new_album = load_album(xml_doc, tree, node, NULL); if(new_album) tree->children = append_album(tree->children, new_album); } else if(!BG_XML_STRCMP(node->name, "CFG_SECTION")) { bg_cfg_xml_2_section(xml_doc, node, tree->cfg_section); } } node = node->next; } xmlFreeDoc(xml_doc); } static void save_album(bg_album_t * album, xmlNodePtr parent) { xmlNodePtr xml_album; bg_album_t * child; xmlNodePtr node; if(album->type == BG_ALBUM_TYPE_PLUGIN) { if(album->plugin_info->flags & BG_PLUGIN_REMOVABLE) return; } else if(album->type == BG_ALBUM_TYPE_REMOVABLE) return; /* Create XML album */ xml_album = xmlNewTextChild(parent, NULL, (xmlChar*)"ALBUM", NULL); if(bg_album_is_open(album)) BG_XML_SET_PROP(xml_album, "open", "1"); if(bg_album_get_expanded(album)) BG_XML_SET_PROP(xml_album, "expanded", "1"); if(album->type == BG_ALBUM_TYPE_INCOMING) BG_XML_SET_PROP(xml_album, "incoming", "1"); else if(album->type == BG_ALBUM_TYPE_FAVOURITES) BG_XML_SET_PROP(xml_album, "favourites", "1"); else if(album->type == BG_ALBUM_TYPE_PLUGIN) BG_XML_SET_PROP(xml_album, "plugin", "1"); else if(album->type == BG_ALBUM_TYPE_TUNER) BG_XML_SET_PROP(xml_album, "tuner", "1"); node = xmlNewTextChild(xml_album, NULL, (xmlChar*)"NAME", NULL); xmlAddChild(node, BG_XML_NEW_TEXT(album->name)); if(album->xml_file) { node = xmlNewTextChild(xml_album, NULL, (xmlChar*)"LOCATION", NULL); xmlAddChild(node, BG_XML_NEW_TEXT(album->xml_file)); } if(album->device) { node = xmlNewTextChild(xml_album, NULL, (xmlChar*)"DEVICE", NULL); xmlAddChild(node, BG_XML_NEW_TEXT(album->device)); } if(album->watch_dir) { node = xmlNewTextChild(xml_album, NULL, (xmlChar*)"WATCH_DIR", NULL); xmlAddChild(node, BG_XML_NEW_TEXT(album->watch_dir)); } xmlAddChild(parent, BG_XML_NEW_TEXT("\n")); if(album->plugin_info) { node = xmlNewTextChild(xml_album, NULL, (xmlChar*)"PLUGIN", NULL); xmlAddChild(node, BG_XML_NEW_TEXT(album->plugin_info->name)); } xmlAddChild(parent, BG_XML_NEW_TEXT("\n")); child = album->children; while(child) { save_album(child, xml_album); child = child->next; } } void bg_media_tree_save(bg_media_tree_t * tree) { bg_album_t * child; char * filename; xmlDocPtr xml_doc; xmlNodePtr xml_mediatree; xmlNodePtr node; xml_doc = xmlNewDoc((xmlChar*)"1.0"); xml_mediatree = xmlNewDocRawNode(xml_doc, NULL, (xmlChar*)"MEDIATREE", NULL); xmlDocSetRootElement(xml_doc, xml_mediatree); xmlAddChild(xml_mediatree, BG_XML_NEW_TEXT("\n")); /* Config stuff */ if(tree->cfg_section) { node = xmlNewTextChild(xml_mediatree, NULL, (xmlChar*)"CFG_SECTION", NULL); bg_cfg_section_2_xml(tree->cfg_section, node); xmlAddChild(xml_mediatree, BG_XML_NEW_TEXT("\n")); } child = tree->children; while(child) { save_album(child, xml_mediatree); child = child->next; } filename = bg_sprintf("%s/%s", tree->com.directory, "tree.xml"); xmlSaveFile(filename, xml_doc); free(filename); xmlFreeDoc(xml_doc); } gmerlin-1.2.0~dfsg/lib/edl.c0000644000175000017500000002571011764363410015561 0ustar alessioalessio/***************************************************************** * gmerlin - a general purpose multimedia framework and applications * * Copyright (c) 2001 - 2011 Members of the Gmerlin project * gmerlin-general@lists.sourceforge.net * http://gmerlin.sourceforge.net * * 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 of the License, 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 this program. If not, see . * *****************************************************************/ #include #include #include #include #include #include #include bg_edl_t * bg_edl_create() { bg_edl_t * ret; ret = calloc(1, sizeof(*ret)); return ret; } bg_edl_track_t * bg_edl_add_track(bg_edl_t * e) { e->tracks = realloc(e->tracks, (e->num_tracks+1)*sizeof(*e->tracks)); memset(e->tracks + e->num_tracks, 0, sizeof(*e->tracks)); e->num_tracks++; return e->tracks + (e->num_tracks-1); } bg_edl_stream_t * bg_edl_add_audio_stream(bg_edl_track_t * t) { t->audio_streams = realloc(t->audio_streams, (t->num_audio_streams+1)*sizeof(*t->audio_streams)); memset(t->audio_streams + t->num_audio_streams, 0, sizeof(*t->audio_streams)); t->num_audio_streams++; return t->audio_streams + (t->num_audio_streams-1); } bg_edl_stream_t * bg_edl_add_video_stream(bg_edl_track_t * t) { t->video_streams = realloc(t->video_streams, (t->num_video_streams+1)*sizeof(*t->video_streams)); memset(t->video_streams + t->num_video_streams, 0, sizeof(*t->video_streams)); t->num_video_streams++; return t->video_streams + (t->num_video_streams-1); } bg_edl_stream_t * bg_edl_add_subtitle_text_stream(bg_edl_track_t * t) { t->subtitle_text_streams = realloc(t->subtitle_text_streams, (t->num_subtitle_text_streams+1)*sizeof(*t->subtitle_text_streams)); memset(t->subtitle_text_streams + t->num_subtitle_text_streams, 0, sizeof(*t->subtitle_text_streams)); t->num_subtitle_text_streams++; return t->subtitle_text_streams + (t->num_subtitle_text_streams-1); } bg_edl_stream_t * bg_edl_add_subtitle_overlay_stream(bg_edl_track_t * t) { t->subtitle_overlay_streams = realloc(t->subtitle_overlay_streams, (t->num_subtitle_overlay_streams+1)*sizeof(*t->subtitle_overlay_streams)); memset(t->subtitle_overlay_streams + t->num_subtitle_overlay_streams, 0, sizeof(*t->subtitle_overlay_streams)); t->num_subtitle_overlay_streams++; return t->subtitle_overlay_streams + (t->num_subtitle_overlay_streams-1); } bg_edl_segment_t * bg_edl_add_segment(bg_edl_stream_t * s) { s->segments = realloc(s->segments, (s->num_segments+1)*sizeof(*s->segments)); memset(s->segments + s->num_segments, 0, sizeof(*s->segments)); s->num_segments++; return s->segments + (s->num_segments-1); } static bg_edl_segment_t * copy_segments(const bg_edl_segment_t * src, int len) { int i; bg_edl_segment_t * ret; ret = calloc(len, sizeof(*ret)); /* Copy integers */ memcpy(ret, src, len * sizeof(*ret)); for(i = 0; i < len; i++) { /* Copy pointers */ ret[i].url = bg_strdup(NULL, src[i].url); } return ret; } static bg_edl_stream_t * copy_streams(const bg_edl_stream_t * src, int len) { int i; bg_edl_stream_t * ret; ret = calloc(len, sizeof(*ret)); /* Copy integers */ memcpy(ret, src, len * sizeof(*ret)); for(i = 0; i < len; i++) { /* Copy pointers */ ret[i].segments = copy_segments(src[i].segments, src[i].num_segments); } return ret; } static bg_edl_track_t * copy_tracks(const bg_edl_track_t * src, int len) { int i; bg_edl_track_t * ret; ret = calloc(len, sizeof(*ret)); /* Copy integers */ memcpy(ret, src, len * sizeof(*ret)); for(i = 0; i < len; i++) { /* Copy pointers */ ret[i].name = bg_strdup(NULL, src[i].name); memset(&ret[i].metadata, 0, sizeof(ret[i].metadata)); gavl_metadata_copy(&ret[i].metadata, &src[i].metadata); ret[i].audio_streams = copy_streams(src[i].audio_streams, src[i].num_audio_streams); ret[i].video_streams = copy_streams(src[i].video_streams, src[i].num_video_streams); ret[i].subtitle_text_streams = copy_streams(src[i].subtitle_text_streams, src[i].num_subtitle_text_streams); ret[i].subtitle_overlay_streams = copy_streams(src[i].subtitle_overlay_streams, src[i].num_subtitle_overlay_streams); } return ret; } bg_edl_t * bg_edl_copy(const bg_edl_t * e) { bg_edl_t * ret; ret = calloc(1, sizeof(*ret)); /* Copy integers */ memcpy(ret, e, sizeof(*ret)); /* Copy pointers */ ret->tracks = copy_tracks(e->tracks, e->num_tracks); ret->url = bg_strdup(NULL, e->url); return ret; } static void free_segments(bg_edl_segment_t * s, int len) { int i; for(i = 0; i < len; i++) { if(s[i].url) free(s[i].url); } free(s); } static void free_streams(bg_edl_stream_t * s, int len) { int i; for(i = 0; i < len; i++) { if(s[i].segments) free_segments(s[i].segments, s[i].num_segments); } free(s); } static void free_tracks(bg_edl_track_t * s, int len) { int i; if(s->name) free(s->name); for(i = 0; i < len; i++) { gavl_metadata_free(&s[i].metadata); if(s[i].audio_streams) free_streams(s[i].audio_streams, s[i].num_audio_streams); if(s[i].video_streams) free_streams(s[i].video_streams, s[i].num_video_streams); if(s[i].subtitle_text_streams) free_streams(s[i].subtitle_text_streams, s[i].num_subtitle_text_streams); if(s[i].subtitle_overlay_streams) free_streams(s[i].subtitle_overlay_streams, s[i].num_subtitle_overlay_streams); } free(s); } void bg_edl_destroy(bg_edl_t * e) { if(e->tracks) free_tracks(e->tracks, e->num_tracks); if(e->url) free(e->url); free(e); } static void dump_stream(const bg_edl_stream_t* s) { int i; bg_edl_segment_t * seg; bg_diprintf(8, "Timescale: %d\n", s->timescale); bg_diprintf(8, "Segments: %d\n", s->num_segments); for(i = 0; i < s->num_segments; i++) { seg = &s->segments[i]; bg_diprintf(8, "Segment\n"); bg_diprintf(10, "URL: %s\n", (seg->url ? seg->url : "(null)")); bg_diprintf(10, "Track: %d\n", seg->track); bg_diprintf(10, "Stream index: %d\n", seg->stream); bg_diprintf(10, "Source timescale: %d\n", seg->timescale); bg_diprintf(10, "Source time: %" PRId64 "\n", seg->src_time); bg_diprintf(10, "Destination time: %" PRId64 "\n", seg->dst_time); bg_diprintf(10, "Destination duration: %" PRId64 "\n", seg->dst_duration); bg_diprintf(10, "Playback speed: %.3f [%d/%d]\n", (float)(seg->speed_num) / (float)(seg->speed_den), seg->speed_num, seg->speed_den); } } static void dump_track(const bg_edl_track_t * t) { int i; bg_diprintf(2, "Track: %s\n", t->name); bg_diprintf(4, "Audio streams: %d\n", t->num_audio_streams); for(i = 0; i < t->num_audio_streams; i++) { bg_diprintf(6, "Audio stream\n"); dump_stream(&t->audio_streams[i]); } bg_diprintf(4, "Video streams: %d\n", t->num_video_streams); for(i = 0; i < t->num_video_streams; i++) { bg_diprintf(6, "Video stream\n"); dump_stream(&t->video_streams[i]); } bg_diprintf(4, "Subtitle text streams: %d\n", t->num_subtitle_text_streams); for(i = 0; i < t->num_subtitle_text_streams; i++) { bg_diprintf(6, "Subtitle text stream\n"); dump_stream(&t->subtitle_text_streams[i]); } bg_diprintf(4, "Subtitle overlay streams: %d\n", t->num_subtitle_overlay_streams); for(i = 0; i < t->num_subtitle_overlay_streams; i++) { bg_diprintf(6, "Subtitle overlay stream\n"); dump_stream(&t->subtitle_overlay_streams[i]); } } void bg_edl_dump(const bg_edl_t * e) { int i; bg_dprintf("EDL\n"); bg_diprintf(2, "URL: %s\n", (e->url ? e->url : "(null)")); bg_diprintf(2, "Tracks: %d\n", e->num_tracks); for(i = 0; i < e->num_tracks; i++) { dump_track(&e->tracks[i]); } } void bg_edl_append_track_info(bg_edl_t * e, const bg_track_info_t * info, const char * url, int index, int total_tracks, const char * name) { bg_edl_track_t * t; bg_edl_stream_t * s; bg_edl_segment_t * seg; int i; t = bg_edl_add_track(e); if(name) t->name = bg_strdup(t->name, name); else if(info->name) t->name = bg_strdup(t->name, info->name); else t->name = bg_get_track_name_default(url, index, total_tracks); for(i = 0; i < info->num_audio_streams; i++) { s = bg_edl_add_audio_stream(t); seg = bg_edl_add_segment(s); s->timescale = info->audio_streams[i].format.samplerate; seg->timescale = s->timescale; if(info->audio_streams[i].duration) seg->dst_duration = info->audio_streams[i].duration; else seg->dst_duration = gavl_time_rescale(GAVL_TIME_SCALE, s->timescale, info->duration); seg->speed_num = 1; seg->speed_den = 1; seg->url = bg_strdup(NULL, url); seg->track = index; seg->stream = i; } for(i = 0; i < info->num_video_streams; i++) { s = bg_edl_add_video_stream(t); seg = bg_edl_add_segment(s); s->timescale = info->video_streams[i].format.timescale; seg->timescale = s->timescale; if(info->video_streams[i].duration) seg->dst_duration = info->video_streams[i].duration; else seg->dst_duration = gavl_time_rescale(GAVL_TIME_SCALE, s->timescale, info->duration); seg->speed_num = 1; seg->speed_den = 1; seg->url = bg_strdup(NULL, url); seg->track = index; seg->stream = i; } for(i = 0; i < info->num_subtitle_streams; i++) { if(info->subtitle_streams[i].is_text) s = bg_edl_add_subtitle_text_stream(t); else s = bg_edl_add_subtitle_overlay_stream(t); seg = bg_edl_add_segment(s); s->timescale = info->subtitle_streams[i].format.timescale; seg->timescale = s->timescale; if(info->subtitle_streams[i].duration) seg->dst_duration = info->subtitle_streams[i].duration; else seg->dst_duration = gavl_time_rescale(GAVL_TIME_SCALE, s->timescale, info->duration); seg->speed_num = 1; seg->speed_den = 1; seg->url = bg_strdup(NULL, url); seg->track = index; seg->stream = i; } } gmerlin-1.2.0~dfsg/lib/Makefile.in0000644000175000017500000011276611764363424016733 0ustar alessioalessio# Makefile.in generated by automake 1.11.1 from Makefile.am. # @configure_input@ # Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, # 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation, # Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ VPATH = @srcdir@ pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ bin_PROGRAMS = gmerlin_visualizer_slave$(EXEEXT) subdir = lib DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/m4/check_funcs.m4 \ $(top_srcdir)/m4/gavl_simd.m4 $(top_srcdir)/m4/gettext.m4 \ $(top_srcdir)/m4/iconv.m4 $(top_srcdir)/m4/lib-ld.m4 \ $(top_srcdir)/m4/lib-link.m4 $(top_srcdir)/m4/lib-prefix.m4 \ $(top_srcdir)/m4/lqt_opt_cflags.m4 $(top_srcdir)/m4/nls.m4 \ $(top_srcdir)/m4/po.m4 $(top_srcdir)/m4/progtest.m4 \ $(top_srcdir)/acinclude.m4 $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/include/config.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; am__vpath_adj = case $$p in \ $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ *) f=$$p;; \ esac; am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; am__install_max = 40 am__nobase_strip_setup = \ srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` am__nobase_strip = \ for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" am__nobase_list = $(am__nobase_strip_setup); \ for p in $$list; do echo "$$p $$p"; done | \ sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ if (++n[$$2] == $(am__install_max)) \ { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ END { for (dir in files) print dir, files[dir] }' am__base_list = \ sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' am__installdirs = "$(DESTDIR)$(libdir)" "$(DESTDIR)$(bindir)" LTLIBRARIES = $(lib_LTLIBRARIES) @HAVE_X11_TRUE@am__DEPENDENCIES_1 = x11/libx11.la am__DEPENDENCIES_2 = libgmerlin_la_DEPENDENCIES = $(am__DEPENDENCIES_1) \ $(am__DEPENDENCIES_2) am__libgmerlin_la_SOURCES_DIST = bglv.c uthread_sem.c accelerator.c \ album.c album_xml.c bggavl.c bgladspa.c bgfrei0r.c bgxml.c \ cfg_item.c cfg_registry.c cfg_section.c cfg_xml.c \ chapterlist.c chapterlist_xml.c charset.c cmdline.c \ converters.c device.c edl.c edldec.c edl_xml.c encoder.c \ fileformat.c filters.c formats.c hexdump.c language_table.c \ lcdproc.c log.c md5.c mediafiledevice.c metadata.c \ metadata_xml.c msgqueue.c ocr.c osd.c ov.c ovl2text.c \ parameter.c parameter_xml.c player.c player_input.c \ player_oa.c player_ov.c player_audio.c player_loop.c \ player_subtitle.c player_thread.c player_time.c player_video.c \ playercmd.c pluginfuncs.c pluginregistry.c pluginreg_xml.c \ preset.c preset_xml.c recorder.c recorder_audio.c \ recorder_video.c remote.c searchpath.c serialize.c singlepic.c \ socket.c streaminfo.c stringutils.c subprocess.c \ textrenderer.c threadpool.c thumbnail.c transcoder.c \ transcoder_pp.c transcoder_track.c transcoder_track_xml.c \ translation.c tree.c tree_xml.c urilist.c utf8.c visualize.c @HAVE_LV_TRUE@am__objects_1 = bglv.lo @HAVE_POSIX_SEMAPHORES_FALSE@am__objects_2 = uthread_sem.lo am_libgmerlin_la_OBJECTS = $(am__objects_1) $(am__objects_2) \ accelerator.lo album.lo album_xml.lo bggavl.lo bgladspa.lo \ bgfrei0r.lo bgxml.lo cfg_item.lo cfg_registry.lo \ cfg_section.lo cfg_xml.lo chapterlist.lo chapterlist_xml.lo \ charset.lo cmdline.lo converters.lo device.lo edl.lo edldec.lo \ edl_xml.lo encoder.lo fileformat.lo filters.lo formats.lo \ hexdump.lo language_table.lo lcdproc.lo log.lo md5.lo \ mediafiledevice.lo metadata.lo metadata_xml.lo msgqueue.lo \ ocr.lo osd.lo ov.lo ovl2text.lo parameter.lo parameter_xml.lo \ player.lo player_input.lo player_oa.lo player_ov.lo \ player_audio.lo player_loop.lo player_subtitle.lo \ player_thread.lo player_time.lo player_video.lo playercmd.lo \ pluginfuncs.lo pluginregistry.lo pluginreg_xml.lo preset.lo \ preset_xml.lo recorder.lo recorder_audio.lo recorder_video.lo \ remote.lo searchpath.lo serialize.lo singlepic.lo socket.lo \ streaminfo.lo stringutils.lo subprocess.lo textrenderer.lo \ threadpool.lo thumbnail.lo transcoder.lo transcoder_pp.lo \ transcoder_track.lo transcoder_track_xml.lo translation.lo \ tree.lo tree_xml.lo urilist.lo utf8.lo visualize.lo libgmerlin_la_OBJECTS = $(am_libgmerlin_la_OBJECTS) libgmerlin_la_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ $(libgmerlin_la_LDFLAGS) $(LDFLAGS) -o $@ PROGRAMS = $(bin_PROGRAMS) am_gmerlin_visualizer_slave_OBJECTS = visualize_slave.$(OBJEXT) gmerlin_visualizer_slave_OBJECTS = \ $(am_gmerlin_visualizer_slave_OBJECTS) gmerlin_visualizer_slave_DEPENDENCIES = libgmerlin.la DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)/include depcomp = $(SHELL) $(top_srcdir)/depcomp am__depfiles_maybe = depfiles am__mv = mv -f COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) LTCOMPILE = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \ --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) CCLD = $(CC) LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \ --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \ $(LDFLAGS) -o $@ SOURCES = $(libgmerlin_la_SOURCES) $(gmerlin_visualizer_slave_SOURCES) DIST_SOURCES = $(am__libgmerlin_la_SOURCES_DIST) \ $(gmerlin_visualizer_slave_SOURCES) RECURSIVE_TARGETS = all-recursive check-recursive dvi-recursive \ html-recursive info-recursive install-data-recursive \ install-dvi-recursive install-exec-recursive \ install-html-recursive install-info-recursive \ install-pdf-recursive install-ps-recursive install-recursive \ installcheck-recursive installdirs-recursive pdf-recursive \ ps-recursive uninstall-recursive RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive \ distclean-recursive maintainer-clean-recursive AM_RECURSIVE_TARGETS = $(RECURSIVE_TARGETS:-recursive=) \ $(RECURSIVE_CLEAN_TARGETS:-recursive=) tags TAGS ctags CTAGS \ distdir ETAGS = etags CTAGS = ctags DIST_SUBDIRS = x11 . gtk DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) am__relativize = \ dir0=`pwd`; \ sed_first='s,^\([^/]*\)/.*$$,\1,'; \ sed_rest='s,^[^/]*/*,,'; \ sed_last='s,^.*/\([^/]*\)$$,\1,'; \ sed_butlast='s,/*[^/]*$$,,'; \ while test -n "$$dir1"; do \ first=`echo "$$dir1" | sed -e "$$sed_first"`; \ if test "$$first" != "."; then \ if test "$$first" = ".."; then \ dir2=`echo "$$dir0" | sed -e "$$sed_last"`/"$$dir2"; \ dir0=`echo "$$dir0" | sed -e "$$sed_butlast"`; \ else \ first2=`echo "$$dir2" | sed -e "$$sed_first"`; \ if test "$$first2" = "$$first"; then \ dir2=`echo "$$dir2" | sed -e "$$sed_rest"`; \ else \ dir2="../$$dir2"; \ fi; \ dir0="$$dir0"/"$$first"; \ fi; \ fi; \ dir1=`echo "$$dir1" | sed -e "$$sed_rest"`; \ done; \ reldir="$$dir2" ACLOCAL = @ACLOCAL@ ALSA_CFLAGS = @ALSA_CFLAGS@ ALSA_LIBS = @ALSA_LIBS@ ALSA_REQUIRED = @ALSA_REQUIRED@ AMTAR = @AMTAR@ AR = @AR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ BG_VERSION = @BG_VERSION@ BG_VERSION_MAJOR = @BG_VERSION_MAJOR@ BG_VERSION_MICRO = @BG_VERSION_MICRO@ BG_VERSION_MINOR = @BG_VERSION_MINOR@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CDDB_CFLAGS = @CDDB_CFLAGS@ CDDB_LIBS = @CDDB_LIBS@ CDIO_CDDA_CFLAGS = @CDIO_CDDA_CFLAGS@ CDIO_CDDA_LIBS = @CDIO_CDDA_LIBS@ CDIO_CFLAGS = @CDIO_CFLAGS@ CDIO_LIBS = @CDIO_LIBS@ CDIO_PARANOIA_CFLAGS = @CDIO_PARANOIA_CFLAGS@ CDIO_PARANOIA_LIBS = @CDIO_PARANOIA_LIBS@ CDIO_REQUIRED = @CDIO_REQUIRED@ CFLAGS = @CFLAGS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CYGPATH_W = @CYGPATH_W@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DOXYGEN = @DOXYGEN@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ ESD_CFLAGS = @ESD_CFLAGS@ ESD_CONFIG = @ESD_CONFIG@ ESD_LIBS = @ESD_LIBS@ ESD_REQUIRED = @ESD_REQUIRED@ EXEEXT = @EXEEXT@ FGREP = @FGREP@ FONTCONFIG_CFLAGS = @FONTCONFIG_CFLAGS@ FONTCONFIG_LIBS = @FONTCONFIG_LIBS@ FREETYPE_CFLAGS = @FREETYPE_CFLAGS@ FREETYPE_LIBS = @FREETYPE_LIBS@ GAVL_CFLAGS = @GAVL_CFLAGS@ GAVL_LIBS = @GAVL_LIBS@ GAVL_REQUIRED = @GAVL_REQUIRED@ GLX_CFLAGS = @GLX_CFLAGS@ GLX_LIBS = @GLX_LIBS@ GL_CFLAGS = @GL_CFLAGS@ GL_LIBS = @GL_LIBS@ GMERLIN_DEP_LIBS = @GMERLIN_DEP_LIBS@ GMERLIN_PLUGIN_LDFLAGS = @GMERLIN_PLUGIN_LDFLAGS@ GMSGFMT = @GMSGFMT@ GMSGFMT_015 = @GMSGFMT_015@ GREP = @GREP@ GTK_CFLAGS = @GTK_CFLAGS@ GTK_LIBS = @GTK_LIBS@ GTK_REQUIRED = @GTK_REQUIRED@ ICONV_LIBS = @ICONV_LIBS@ INCLUDES = -I$(top_srcdir)/include INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ INTLLIBS = @INTLLIBS@ INTL_MACOSX_LIBS = @INTL_MACOSX_LIBS@ JACK_CFLAGS = @JACK_CFLAGS@ JACK_LIBS = @JACK_LIBS@ JACK_REQUIRED = @JACK_REQUIRED@ JPEG_CFLAGS = @JPEG_CFLAGS@ JPEG_LIBS = @JPEG_LIBS@ JPEG_REQUIRED = @JPEG_REQUIRED@ LD = @LD@ LDFLAGS = @LDFLAGS@ LIBCDDB_REQUIRED = @LIBCDDB_REQUIRED@ LIBEXIF_CFLAGS = @LIBEXIF_CFLAGS@ LIBEXIF_LIBS = @LIBEXIF_LIBS@ LIBICONV = @LIBICONV@ LIBINTL = @LIBINTL@ LIBM = @LIBM@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIPO = @LIPO@ LN_S = @LN_S@ LQT_CFLAGS = @LQT_CFLAGS@ LQT_LIBS = @LQT_LIBS@ LQT_REQUIRED = @LQT_REQUIRED@ LTLIBICONV = @LTLIBICONV@ LTLIBINTL = @LTLIBINTL@ LTLIBOBJS = @LTLIBOBJS@ LTVERSION_AGE = @LTVERSION_AGE@ LTVERSION_CURRENT = @LTVERSION_CURRENT@ LTVERSION_REVISION = @LTVERSION_REVISION@ LV_CFLAGS = @LV_CFLAGS@ LV_LIBS = @LV_LIBS@ LV_REQUIRED = @LV_REQUIRED@ MAKEINFO = @MAKEINFO@ MKDIR_P = @MKDIR_P@ MODULE_LIBADD = @MODULE_LIBADD@ MSGFMT = @MSGFMT@ MSGFMT_015 = @MSGFMT_015@ MSGMERGE = @MSGMERGE@ MUSICBRAINZ_CFLAGS = @MUSICBRAINZ_CFLAGS@ MUSICBRAINZ_LIBS = @MUSICBRAINZ_LIBS@ MUSICBRAINZ_REQUIRED = @MUSICBRAINZ_REQUIRED@ NM = @NM@ NMEDIT = @NMEDIT@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OTOOL = @OTOOL@ OTOOL64 = @OTOOL64@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PKG_CONFIG = @PKG_CONFIG@ PNG_CFLAGS = @PNG_CFLAGS@ PNG_LIBS = @PNG_LIBS@ PNG_REQUIRED = @PNG_REQUIRED@ POSUB = @POSUB@ PULSEAUDIO_CFLAGS = @PULSEAUDIO_CFLAGS@ PULSEAUDIO_LIBS = @PULSEAUDIO_LIBS@ PULSEAUDIO_REQUIRED = @PULSEAUDIO_REQUIRED@ RANLIB = @RANLIB@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ SQLITE3_LIBS = @SQLITE3_LIBS@ STRIP = @STRIP@ TEXINFO = @TEXINFO@ TIFF_CFLAGS = @TIFF_CFLAGS@ TIFF_LIBS = @TIFF_LIBS@ TIFF_REQUIRED = @TIFF_REQUIRED@ TOP_SRCDIR = @TOP_SRCDIR@ USE_NLS = @USE_NLS@ V4LCONVERT_CFLAGS = @V4LCONVERT_CFLAGS@ V4LCONVERT_LIBS = @V4LCONVERT_LIBS@ V4LCONVERT_REQUIRED = @V4LCONVERT_REQUIRED@ VERSION = @VERSION@ XDPMS_LIBS = @XDPMS_LIBS@ XFIXES_LIBS = @XFIXES_LIBS@ XGETTEXT = @XGETTEXT@ XGETTEXT_015 = @XGETTEXT_015@ XINERAMA_LIBS = @XINERAMA_LIBS@ XMKMF = @XMKMF@ XML2_CFLAGS = @XML2_CFLAGS@ XML2_LIBS = @XML2_LIBS@ XML2_REQUIRED = @XML2_REQUIRED@ XTEST_LIBS = @XTEST_LIBS@ XV_LIBS = @XV_LIBS@ X_CFLAGS = @X_CFLAGS@ X_LIBS = @X_LIBS@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_CC = @ac_ct_CC@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_vendor = @build_vendor@ builddir = @builddir@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ lt_ECHO = @lt_ECHO@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ plugindir = $(pkglibdir)/plugins @HAVE_X11_FALSE@x11_subdirs = @HAVE_X11_TRUE@x11_subdirs = x11 @HAVE_X11_FALSE@x11_libadd = @HAVE_X11_TRUE@x11_libadd = x11/libx11.la @HAVE_GTK_FALSE@gtk_subdirs = @HAVE_GTK_TRUE@gtk_subdirs = gtk @HAVE_LV_FALSE@lv_sources = @HAVE_LV_TRUE@lv_sources = bglv.c @HAVE_LV_FALSE@lv_cflags = @HAVE_LV_TRUE@lv_cflags = @LV_CFLAGS@ @HAVE_LV_FALSE@lv_libs = @HAVE_LV_TRUE@lv_libs = @LV_LIBS@ @HAVE_POSIX_SEMAPHORES_FALSE@sem_sources = uthread_sem.c @HAVE_POSIX_SEMAPHORES_TRUE@sem_sources = SUBDIRS = $(x11_subdirs) . $(gtk_subdirs) AM_CFLAGS = \ @FONTCONFIG_CFLAGS@ \ @FREETYPE_CFLAGS@ \ -DLOCALE_DIR=\"$(localedir)\" \ -DPLUGIN_DIR=\"$(plugindir)\" \ -DDOC_DIR=\"$(docdir)\" \ -DDATA_DIR=\"$(pkgdatadir)\" \ $(lv_cflags) libgmerlin_la_LDFLAGS = -version-info @LTVERSION_CURRENT@:@LTVERSION_REVISION@:@LTVERSION_AGE@ -export-symbols-regex ^bg_ libgmerlin_la_LIBADD = $(x11_libadd) @FONTCONFIG_LIBS@ @FREETYPE_LIBS@ @XML2_LIBS@ @ICONV_LIBS@ @LIBINTL@ $(lv_libs) -ldl -lpthread gmerlin_visualizer_slave_SOURCES = visualize_slave.c gmerlin_visualizer_slave_LDADD = libgmerlin.la lib_LTLIBRARIES = libgmerlin.la libgmerlin_la_SOURCES = \ $(lv_sources) \ $(sem_sources) \ accelerator.c \ album.c \ album_xml.c \ bggavl.c \ bgladspa.c \ bgfrei0r.c \ bgxml.c \ cfg_item.c \ cfg_registry.c \ cfg_section.c \ cfg_xml.c \ chapterlist.c \ chapterlist_xml.c \ charset.c \ cmdline.c \ converters.c \ device.c \ edl.c \ edldec.c \ edl_xml.c \ encoder.c \ fileformat.c \ filters.c \ formats.c \ hexdump.c \ language_table.c \ lcdproc.c \ log.c \ md5.c \ mediafiledevice.c \ metadata.c \ metadata_xml.c \ msgqueue.c \ ocr.c \ osd.c \ ov.c \ ovl2text.c \ parameter.c \ parameter_xml.c \ player.c \ player_input.c \ player_oa.c \ player_ov.c \ player_audio.c \ player_loop.c \ player_subtitle.c \ player_thread.c \ player_time.c \ player_video.c \ playercmd.c \ pluginfuncs.c \ pluginregistry.c \ pluginreg_xml.c \ preset.c \ preset_xml.c \ recorder.c \ recorder_audio.c \ recorder_video.c \ remote.c \ searchpath.c \ serialize.c \ singlepic.c \ socket.c \ streaminfo.c \ stringutils.c \ subprocess.c \ textrenderer.c \ threadpool.c \ thumbnail.c \ transcoder.c \ transcoder_pp.c \ transcoder_track.c \ transcoder_track_xml.c \ translation.c \ tree.c \ tree_xml.c \ urilist.c \ utf8.c \ visualize.c all: all-recursive .SUFFIXES: .SUFFIXES: .c .lo .o .obj $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ && { if test -f $@; then exit 0; else break; fi; }; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu lib/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --gnu lib/Makefile .PRECIOUS: Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): install-libLTLIBRARIES: $(lib_LTLIBRARIES) @$(NORMAL_INSTALL) test -z "$(libdir)" || $(MKDIR_P) "$(DESTDIR)$(libdir)" @list='$(lib_LTLIBRARIES)'; test -n "$(libdir)" || list=; \ list2=; for p in $$list; do \ if test -f $$p; then \ list2="$$list2 $$p"; \ else :; fi; \ done; \ test -z "$$list2" || { \ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(libdir)'"; \ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(libdir)"; \ } uninstall-libLTLIBRARIES: @$(NORMAL_UNINSTALL) @list='$(lib_LTLIBRARIES)'; test -n "$(libdir)" || list=; \ for p in $$list; do \ $(am__strip_dir) \ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(libdir)/$$f'"; \ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(libdir)/$$f"; \ done clean-libLTLIBRARIES: -test -z "$(lib_LTLIBRARIES)" || rm -f $(lib_LTLIBRARIES) @list='$(lib_LTLIBRARIES)'; for p in $$list; do \ dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \ test "$$dir" != "$$p" || dir=.; \ echo "rm -f \"$${dir}/so_locations\""; \ rm -f "$${dir}/so_locations"; \ done libgmerlin.la: $(libgmerlin_la_OBJECTS) $(libgmerlin_la_DEPENDENCIES) $(libgmerlin_la_LINK) -rpath $(libdir) $(libgmerlin_la_OBJECTS) $(libgmerlin_la_LIBADD) $(LIBS) install-binPROGRAMS: $(bin_PROGRAMS) @$(NORMAL_INSTALL) test -z "$(bindir)" || $(MKDIR_P) "$(DESTDIR)$(bindir)" @list='$(bin_PROGRAMS)'; test -n "$(bindir)" || list=; \ for p in $$list; do echo "$$p $$p"; done | \ sed 's/$(EXEEXT)$$//' | \ while read p p1; do if test -f $$p || test -f $$p1; \ then echo "$$p"; echo "$$p"; else :; fi; \ done | \ sed -e 'p;s,.*/,,;n;h' -e 's|.*|.|' \ -e 'p;x;s,.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/' | \ sed 'N;N;N;s,\n, ,g' | \ $(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1 } \ { d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \ if ($$2 == $$4) files[d] = files[d] " " $$1; \ else { print "f", $$3 "/" $$4, $$1; } } \ END { for (d in files) print "f", d, files[d] }' | \ while read type dir files; do \ if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \ test -z "$$files" || { \ echo " $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files '$(DESTDIR)$(bindir)$$dir'"; \ $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files "$(DESTDIR)$(bindir)$$dir" || exit $$?; \ } \ ; done uninstall-binPROGRAMS: @$(NORMAL_UNINSTALL) @list='$(bin_PROGRAMS)'; test -n "$(bindir)" || list=; \ files=`for p in $$list; do echo "$$p"; done | \ sed -e 'h;s,^.*/,,;s/$(EXEEXT)$$//;$(transform)' \ -e 's/$$/$(EXEEXT)/' `; \ test -n "$$list" || exit 0; \ echo " ( cd '$(DESTDIR)$(bindir)' && rm -f" $$files ")"; \ cd "$(DESTDIR)$(bindir)" && rm -f $$files clean-binPROGRAMS: @list='$(bin_PROGRAMS)'; test -n "$$list" || exit 0; \ echo " rm -f" $$list; \ rm -f $$list || exit $$?; \ test -n "$(EXEEXT)" || exit 0; \ list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ echo " rm -f" $$list; \ rm -f $$list gmerlin_visualizer_slave$(EXEEXT): $(gmerlin_visualizer_slave_OBJECTS) $(gmerlin_visualizer_slave_DEPENDENCIES) @rm -f gmerlin_visualizer_slave$(EXEEXT) $(LINK) $(gmerlin_visualizer_slave_OBJECTS) $(gmerlin_visualizer_slave_LDADD) $(LIBS) mostlyclean-compile: -rm -f *.$(OBJEXT) distclean-compile: -rm -f *.tab.c @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/accelerator.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/album.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/album_xml.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/bgfrei0r.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/bggavl.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/bgladspa.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/bglv.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/bgxml.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cfg_item.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cfg_registry.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cfg_section.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cfg_xml.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/chapterlist.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/chapterlist_xml.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/charset.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cmdline.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/converters.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/device.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/edl.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/edl_xml.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/edldec.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/encoder.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fileformat.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/filters.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/formats.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/hexdump.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/language_table.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lcdproc.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/log.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/md5.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mediafiledevice.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/metadata.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/metadata_xml.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/msgqueue.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ocr.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/osd.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ov.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ovl2text.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/parameter.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/parameter_xml.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/player.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/player_audio.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/player_input.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/player_loop.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/player_oa.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/player_ov.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/player_subtitle.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/player_thread.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/player_time.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/player_video.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/playercmd.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pluginfuncs.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pluginreg_xml.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pluginregistry.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/preset.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/preset_xml.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/recorder.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/recorder_audio.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/recorder_video.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/remote.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/searchpath.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/serialize.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/singlepic.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/socket.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/streaminfo.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/stringutils.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/subprocess.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/textrenderer.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/threadpool.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/thumbnail.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/transcoder.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/transcoder_pp.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/transcoder_track.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/transcoder_track_xml.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/translation.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tree.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tree_xml.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/urilist.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/utf8.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/uthread_sem.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/visualize.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/visualize_slave.Po@am__quote@ .c.o: @am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(COMPILE) -c $< .c.obj: @am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(COMPILE) -c `$(CYGPATH_W) '$<'` .c.lo: @am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(LTCOMPILE) -c -o $@ $< mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs # This directory's subdirectories are mostly independent; you can cd # into them and run `make' without going through this Makefile. # To change the values of `make' variables: instead of editing Makefiles, # (1) if the variable is set in `config.status', edit `config.status' # (which will cause the Makefiles to be regenerated when you run `make'); # (2) otherwise, pass the desired values on the `make' command line. $(RECURSIVE_TARGETS): @fail= failcom='exit 1'; \ for f in x $$MAKEFLAGS; do \ case $$f in \ *=* | --[!k]*);; \ *k*) failcom='fail=yes';; \ esac; \ done; \ dot_seen=no; \ target=`echo $@ | sed s/-recursive//`; \ list='$(SUBDIRS)'; for subdir in $$list; do \ echo "Making $$target in $$subdir"; \ if test "$$subdir" = "."; then \ dot_seen=yes; \ local_target="$$target-am"; \ else \ local_target="$$target"; \ fi; \ ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ || eval $$failcom; \ done; \ if test "$$dot_seen" = "no"; then \ $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \ fi; test -z "$$fail" $(RECURSIVE_CLEAN_TARGETS): @fail= failcom='exit 1'; \ for f in x $$MAKEFLAGS; do \ case $$f in \ *=* | --[!k]*);; \ *k*) failcom='fail=yes';; \ esac; \ done; \ dot_seen=no; \ case "$@" in \ distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \ *) list='$(SUBDIRS)' ;; \ esac; \ rev=''; for subdir in $$list; do \ if test "$$subdir" = "."; then :; else \ rev="$$subdir $$rev"; \ fi; \ done; \ rev="$$rev ."; \ target=`echo $@ | sed s/-recursive//`; \ for subdir in $$rev; do \ echo "Making $$target in $$subdir"; \ if test "$$subdir" = "."; then \ local_target="$$target-am"; \ else \ local_target="$$target"; \ fi; \ ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ || eval $$failcom; \ done && test -z "$$fail" tags-recursive: list='$(SUBDIRS)'; for subdir in $$list; do \ test "$$subdir" = . || ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) tags); \ done ctags-recursive: list='$(SUBDIRS)'; for subdir in $$list; do \ test "$$subdir" = . || ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) ctags); \ done ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | \ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in files) print i; }; }'`; \ mkid -fID $$unique tags: TAGS TAGS: tags-recursive $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ $(TAGS_FILES) $(LISP) set x; \ here=`pwd`; \ if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \ include_option=--etags-include; \ empty_fix=.; \ else \ include_option=--include; \ empty_fix=; \ fi; \ list='$(SUBDIRS)'; for subdir in $$list; do \ if test "$$subdir" = .; then :; else \ test ! -f $$subdir/TAGS || \ set "$$@" "$$include_option=$$here/$$subdir/TAGS"; \ fi; \ done; \ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | \ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in files) print i; }; }'`; \ shift; \ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ test -n "$$unique" || unique=$$empty_fix; \ if test $$# -gt 0; then \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ "$$@" $$unique; \ else \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ $$unique; \ fi; \ fi ctags: CTAGS CTAGS: ctags-recursive $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ $(TAGS_FILES) $(LISP) list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | \ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in files) print i; }; }'`; \ test -z "$(CTAGS_ARGS)$$unique" \ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ $$unique GTAGS: here=`$(am__cd) $(top_builddir) && pwd` \ && $(am__cd) $(top_srcdir) \ && gtags -i $(GTAGS_ARGS) "$$here" distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags distdir: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done @list='$(DIST_SUBDIRS)'; for subdir in $$list; do \ if test "$$subdir" = .; then :; else \ test -d "$(distdir)/$$subdir" \ || $(MKDIR_P) "$(distdir)/$$subdir" \ || exit 1; \ fi; \ done @list='$(DIST_SUBDIRS)'; for subdir in $$list; do \ if test "$$subdir" = .; then :; else \ dir1=$$subdir; dir2="$(distdir)/$$subdir"; \ $(am__relativize); \ new_distdir=$$reldir; \ dir1=$$subdir; dir2="$(top_distdir)"; \ $(am__relativize); \ new_top_distdir=$$reldir; \ echo " (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) top_distdir="$$new_top_distdir" distdir="$$new_distdir" \\"; \ echo " am__remove_distdir=: am__skip_length_check=: am__skip_mode_fix=: distdir)"; \ ($(am__cd) $$subdir && \ $(MAKE) $(AM_MAKEFLAGS) \ top_distdir="$$new_top_distdir" \ distdir="$$new_distdir" \ am__remove_distdir=: \ am__skip_length_check=: \ am__skip_mode_fix=: \ distdir) \ || exit 1; \ fi; \ done check-am: all-am check: check-recursive all-am: Makefile $(LTLIBRARIES) $(PROGRAMS) install-binPROGRAMS: install-libLTLIBRARIES installdirs: installdirs-recursive installdirs-am: for dir in "$(DESTDIR)$(libdir)" "$(DESTDIR)$(bindir)"; do \ test -z "$$dir" || $(MKDIR_P) "$$dir"; \ done install: install-recursive install-exec: install-exec-recursive install-data: install-data-recursive uninstall: uninstall-recursive install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-recursive install-strip: $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ `test -z '$(STRIP)' || \ echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install mostlyclean-generic: clean-generic: distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." clean: clean-recursive clean-am: clean-binPROGRAMS clean-generic clean-libLTLIBRARIES \ clean-libtool mostlyclean-am distclean: distclean-recursive -rm -rf ./$(DEPDIR) -rm -f Makefile distclean-am: clean-am distclean-compile distclean-generic \ distclean-tags dvi: dvi-recursive dvi-am: html: html-recursive html-am: info: info-recursive info-am: install-data-am: install-dvi: install-dvi-recursive install-dvi-am: install-exec-am: install-binPROGRAMS install-libLTLIBRARIES install-html: install-html-recursive install-html-am: install-info: install-info-recursive install-info-am: install-man: install-pdf: install-pdf-recursive install-pdf-am: install-ps: install-ps-recursive install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-recursive -rm -rf ./$(DEPDIR) -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-recursive mostlyclean-am: mostlyclean-compile mostlyclean-generic \ mostlyclean-libtool pdf: pdf-recursive pdf-am: ps: ps-recursive ps-am: uninstall-am: uninstall-binPROGRAMS uninstall-libLTLIBRARIES .MAKE: $(RECURSIVE_CLEAN_TARGETS) $(RECURSIVE_TARGETS) ctags-recursive \ install-am install-strip tags-recursive .PHONY: $(RECURSIVE_CLEAN_TARGETS) $(RECURSIVE_TARGETS) CTAGS GTAGS \ all all-am check check-am clean clean-binPROGRAMS \ clean-generic clean-libLTLIBRARIES clean-libtool ctags \ ctags-recursive distclean distclean-compile distclean-generic \ distclean-libtool distclean-tags distdir dvi dvi-am html \ html-am info info-am install install-am install-binPROGRAMS \ install-data install-data-am install-dvi install-dvi-am \ install-exec install-exec-am install-html install-html-am \ install-info install-info-am install-libLTLIBRARIES \ install-man install-pdf install-pdf-am install-ps \ install-ps-am install-strip installcheck installcheck-am \ installdirs installdirs-am maintainer-clean \ maintainer-clean-generic mostlyclean mostlyclean-compile \ mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ tags tags-recursive uninstall uninstall-am \ uninstall-binPROGRAMS uninstall-libLTLIBRARIES # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: gmerlin-1.2.0~dfsg/lib/edldec.c0000644000175000017500000013337311764363410016242 0ustar alessioalessio/***************************************************************** * gmerlin - a general purpose multimedia framework and applications * * Copyright (c) 2001 - 2011 Members of the Gmerlin project * gmerlin-general@lists.sourceforge.net * http://gmerlin.sourceforge.net * * 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 of the License, 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 this program. If not, see . * *****************************************************************/ #include #include #include #include #include #include #include #include #define LOG_DOMAIN "edldec" #define PTS_UNDEFINED 0x8000000000000000LL /* Sources */ typedef struct { bg_plugin_handle_t * handle; bg_input_plugin_t * plugin; const char * url; int track; int stream; bg_track_info_t * ti; int read_stream; void * read_data; } source_common_t; typedef struct { source_common_t com; bg_audio_converter_t * cnv; bg_read_audio_func_t read_func; gavl_audio_format_t * format; } audio_source_t; typedef struct { source_common_t com; bg_video_converter_t * cnv; bg_read_video_func_t read_func; gavl_video_format_t * format; } video_source_t; typedef struct { source_common_t com; /* Rest is only for overlays */ gavl_video_converter_t * cnv; gavl_overlay_t ovl; int (*read_func)(void * priv, gavl_overlay_t*ovl, int stream); gavl_video_format_t * format; } subtitle_source_t; /* Segments */ typedef struct { source_common_t * src; const bg_edl_segment_t * seg; int64_t mute_start; int64_t mute_duration; } segment_t; /* Streams */ typedef struct { int num_segments; segment_t * segments; int current_segment; int num_sources; audio_source_t * sources; gavl_audio_format_t * format; bg_stream_action_t action; int64_t out_time; int64_t segment_end_time; const bg_edl_stream_t * es; gavl_audio_frame_t * frame; } audio_stream_t; typedef struct { int num_segments; segment_t * segments; int current_segment; gavl_video_format_t * format; int num_sources; video_source_t * sources; bg_stream_action_t action; int64_t out_time; int64_t segment_end_time; const bg_edl_stream_t * es; } video_stream_t; typedef struct { int num_segments; segment_t * segments; int current_segment; int num_sources; subtitle_source_t * sources; gavl_video_format_t * format; bg_stream_action_t action; int64_t out_time; int64_t segment_end_time; int64_t time_offset; /* In output tics */ const bg_edl_stream_t * es; } subtitle_stream_t; typedef struct { audio_stream_t * audio_streams; video_stream_t * video_streams; subtitle_stream_t * subtitle_text_streams; subtitle_stream_t * subtitle_overlay_streams; } track_t; typedef struct { int current_track; track_t * tracks; bg_track_info_t * track_info; const bg_edl_t * edl; bg_plugin_registry_t * plugin_reg; bg_input_callbacks_t * callbacks; gavl_audio_options_t * a_opt; gavl_video_options_t * v_opt; } edl_dec_t; /* Timing functions */ /* |---------------------------------> out_time | |-----------------> in_time 0 dst_time */ static int64_t get_source_offset(const bg_edl_stream_t * st, segment_t * s, int64_t out_time, int64_t out_scale) { int64_t seg_offset; /* in out timescale */ int64_t source_offset; /* in out timescale */ seg_offset = out_time - gavl_time_rescale(st->timescale, out_scale, s->seg->dst_time); source_offset = gavl_time_rescale(s->seg->timescale, out_scale, s->seg->src_time); return source_offset + seg_offset; } static int seek_segment(const bg_edl_stream_t * st, segment_t * segs, int nsegs, int64_t out_time, int out_scale) { /* Rescale to edit granularity */ int64_t t = gavl_time_rescale(out_scale, st->timescale, out_time); int i; for(i = 0; i < nsegs; i++) { if(segs[i].src) { if((segs[i].seg->dst_time <= t) && (segs[i].seg->dst_time + segs[i].seg->dst_duration > t)) return i; } else { if((segs[i].mute_start <= t) && (segs[i].mute_start + segs[i].mute_duration > t)) return i; } } return -1; } /* Stream initialization */ static const bg_edl_segment_t * find_same_source(const bg_edl_segment_t * segments, const bg_edl_segment_t * seg) { while(segments < seg) { /* url mismatch */ if((!segments->url && seg->url) || (segments->url && !seg->url) || (segments->url && seg->url && strcmp(segments->url, seg->url))) { segments++; continue; } /* track/stream mismatch */ if((segments->track != seg->track) || (segments->stream != seg->stream)) { segments++; continue; } return segments; } return NULL; } static void add_audio_segment(edl_dec_t * dec, int track, int stream, const bg_edl_segment_t * seg) { int i; audio_source_t * source = NULL; const bg_edl_segment_t * same_source_seg; bg_audio_info_t * ai; audio_stream_t * s = &dec->tracks[track].audio_streams[stream]; segment_t * as; ai = &dec->track_info[track].audio_streams[stream]; if(seg->dst_time > ai->duration) { /* Insert mute segment */ s->segments = realloc(s->segments, sizeof(*s->segments) * (s->num_segments+2)); memset(s->segments + s->num_segments, 0, sizeof(*s->segments) * 2); s->num_segments += 2; as = s->segments + (s->num_segments-2); as->mute_start = ai->duration; as->mute_duration = seg->dst_time - ai->duration; as++; } else { s->segments = realloc(s->segments, sizeof(*s->segments) * (s->num_segments+1)); memset(s->segments + s->num_segments, 0, sizeof(*s->segments)); s->num_segments++; as = s->segments + (s->num_segments-1); } same_source_seg = find_same_source(dec->edl->tracks[track].audio_streams[stream].segments, seg); if(same_source_seg) { for(i = 0; i < s->num_segments; i++) { if(same_source_seg == s->segments[i].seg) { source = (audio_source_t*)s->segments[i].src; break; } } } else { source = s->sources + s->num_sources; s->num_sources++; source->com.url = seg->url ? seg->url : dec->edl->url; source->com.track = seg->track; source->com.stream = seg->stream; source->cnv = bg_audio_converter_create(dec->a_opt); } as->src = (source_common_t*)source; as->seg = seg; ai->duration = seg->dst_time + seg->dst_duration; } static int add_video_segment(edl_dec_t * dec, int track, int stream, const bg_edl_segment_t * seg) { int i; video_source_t * source = NULL; const bg_edl_segment_t * same_source_seg; bg_video_info_t * vi; video_stream_t * s = &dec->tracks[track].video_streams[stream]; segment_t * vs; vi = &dec->track_info[track].video_streams[stream]; if(seg->dst_time > vi->duration) { /* Insert mute segment */ s->segments = realloc(s->segments, sizeof(*s->segments) * (s->num_segments+2)); memset(s->segments + s->num_segments, 0, sizeof(*s->segments) * 2); s->num_segments += 2; vs = s->segments + (s->num_segments-2); vs->mute_start = vi->duration; vs->mute_duration = seg->dst_time - vi->duration; vs++; } else { s->segments = realloc(s->segments, sizeof(*s->segments) * (s->num_segments+1)); memset(s->segments + s->num_segments, 0, sizeof(*s->segments)); s->num_segments++; vs = s->segments + (s->num_segments-1); } same_source_seg = find_same_source(dec->edl->tracks[track].video_streams[stream].segments, seg); if(same_source_seg) { for(i = 0; i < s->num_segments; i++) { if(same_source_seg == s->segments[i].seg) { source = (video_source_t*)s->segments[i].src; break; } } } else { source = s->sources + s->num_sources; s->num_sources++; source->com.url = seg->url ? seg->url : dec->edl->url; source->com.track = seg->track; source->com.stream = seg->stream; source->cnv = bg_video_converter_create(dec->v_opt); } vs->src = (source_common_t*)source; vs->seg = seg; vi->duration = seg->dst_time + seg->dst_duration; return 1; } static int add_subtitle_overlay_segment(edl_dec_t * dec, int track, int stream, const bg_edl_segment_t * seg) { int i; subtitle_source_t * source = NULL; const bg_edl_segment_t * same_source_seg; bg_subtitle_info_t * vi; subtitle_stream_t * s = &dec->tracks[track].subtitle_overlay_streams[stream]; segment_t * vs; vi = &dec->track_info[track].subtitle_streams[stream + dec->edl->tracks[track].num_subtitle_text_streams]; s->segments = realloc(s->segments, sizeof(*s->segments) * (s->num_segments+1)); memset(s->segments + s->num_segments, 0, sizeof(*s->segments)); s->num_segments++; vs = s->segments + (s->num_segments-1); same_source_seg = find_same_source(dec->edl->tracks[track].subtitle_overlay_streams[stream].segments, seg); if(same_source_seg) { for(i = 0; i < s->num_segments; i++) { if(same_source_seg == s->segments[i].seg) { source = (subtitle_source_t*)s->segments[i].src; break; } } } else { source = s->sources + s->num_sources; s->num_sources++; source->com.url = seg->url ? seg->url : dec->edl->url; source->com.track = seg->track; source->com.stream = seg->stream; source->cnv = gavl_video_converter_create(); } vs->src = (source_common_t*)source; vs->seg = seg; vi->duration = seg->dst_time + seg->dst_duration; return 1; } static int add_subtitle_text_segment(edl_dec_t * dec, int track, int stream, const bg_edl_segment_t * seg) { int i; subtitle_source_t * source = NULL; const bg_edl_segment_t * same_source_seg; bg_subtitle_info_t * vi; subtitle_stream_t * s = &dec->tracks[track].subtitle_text_streams[stream]; segment_t * vs; vi = &dec->track_info[track].subtitle_streams[stream]; s->segments = realloc(s->segments, sizeof(*s->segments) * (s->num_segments+1)); memset(s->segments + s->num_segments, 0, sizeof(*s->segments)); s->num_segments++; vs = s->segments + (s->num_segments-1); same_source_seg = find_same_source(dec->edl->tracks[track].subtitle_text_streams[stream].segments, seg); if(same_source_seg) { for(i = 0; i < s->num_segments; i++) { if(same_source_seg == s->segments[i].seg) { source = (subtitle_source_t*)s->segments[i].src; break; } } } else { source = (subtitle_source_t*)s->sources + s->num_sources; s->num_sources++; source->com.url = seg->url ? seg->url : dec->edl->url; source->com.track = seg->track; source->com.stream = seg->stream; } vs->src = (source_common_t*)source; vs->seg = seg; vi->duration = seg->dst_time + seg->dst_duration; return 1; } /* Initialize segments for immediate playback. out_time must be set before */ static void init_audio_segment(audio_stream_t * as) { segment_t * seg; int64_t t; audio_source_t * src; seg = &as->segments[as->current_segment]; if(seg->seg) { as->segment_end_time = gavl_time_rescale(as->es->timescale, as->format->samplerate, seg->seg->dst_time + seg->seg->dst_duration); t = get_source_offset(as->es, seg, as->out_time, as->format->samplerate); seg->src->plugin->seek(seg->src->handle->priv, &t, as->format->samplerate); src = (audio_source_t *)(seg->src); if(src->cnv) bg_audio_converter_reset(src->cnv); } else as->segment_end_time = gavl_time_rescale(as->es->timescale, as->format->samplerate, seg->mute_start + seg->mute_duration); } static void init_video_segment(video_stream_t * vs) { segment_t * seg; int64_t t; video_source_t * src; seg = &vs->segments[vs->current_segment]; if(seg->seg) { vs->segment_end_time = gavl_time_rescale(vs->es->timescale, vs->format->timescale, seg->seg->dst_time + seg->seg->dst_duration); t = get_source_offset(vs->es, seg, vs->out_time, vs->format->timescale); seg->src->plugin->seek(seg->src->handle->priv, &t, vs->format->timescale); src = (video_source_t *)(seg->src); if(src->cnv) bg_video_converter_reset(src->cnv); } else { vs->segment_end_time = gavl_time_rescale(vs->es->timescale, vs->format->timescale, seg->mute_start + seg->mute_duration); } } static void init_subtitle_segment(subtitle_stream_t * vs) { segment_t * seg; int64_t t1, t2; seg = &vs->segments[vs->current_segment]; vs->segment_end_time = gavl_time_rescale(vs->es->timescale, vs->format->timescale, seg->seg->dst_time + seg->seg->dst_duration); /* * |---------------|------------------------|---------------> * 0 src_start/seg->timescale *time_1 / src_scale * | * |--|---------------|------------------------|---------------> * 0 ? dst_start/s->timescale *time_2 / dst_scale * */ t1 = gavl_time_rescale(seg->seg->timescale, vs->format->timescale, seg->seg->src_time); t2 = gavl_time_rescale(vs->es->timescale, vs->format->timescale, seg->seg->dst_time); vs->time_offset = t2 - t1; t1 = get_source_offset(vs->es, seg, vs->out_time, vs->format->timescale); seg->src->plugin->seek(seg->src->handle->priv, &t1, vs->format->timescale); } static void set_callbacks_edl(void * priv, bg_input_callbacks_t * callbacks) { edl_dec_t * dec; dec = (edl_dec_t*)priv; } static int get_num_tracks_edl(void * priv) { edl_dec_t * dec; dec = (edl_dec_t*)priv; return dec->edl->num_tracks; } static bg_track_info_t * get_track_info_edl(void * priv, int track) { edl_dec_t * dec; dec = (edl_dec_t*)priv; return &dec->track_info[track]; } static int set_track_edl(void * priv, int track) { edl_dec_t * dec; dec = (edl_dec_t*)priv; dec->current_track = track; return 1; } static int set_audio_stream_edl(void * priv, int stream, bg_stream_action_t action) { edl_dec_t * dec; dec = (edl_dec_t*)priv; dec->tracks[dec->current_track].audio_streams[stream].action = action; return 1; } static int set_video_stream_edl(void * priv, int stream, bg_stream_action_t action) { edl_dec_t * dec; dec = (edl_dec_t*)priv; dec->tracks[dec->current_track].video_streams[stream].action = action; return 1; } static int set_subtitle_stream_edl(void * priv, int stream, bg_stream_action_t action) { edl_dec_t * dec; dec = (edl_dec_t*)priv; if(stream >= dec->edl->tracks[dec->current_track].num_subtitle_text_streams) { dec->tracks[dec->current_track].subtitle_overlay_streams[stream - dec->edl->tracks[dec->current_track].num_subtitle_text_streams].action = action; } else { dec->tracks[dec->current_track].subtitle_text_streams[stream].action = action; } return 1; } /* Start streams */ static int init_source_common(edl_dec_t * dec, source_common_t * com) { if(!bg_input_plugin_load(dec->plugin_reg, com->url, NULL, &com->handle, dec->callbacks, 0)) return 0; com->plugin = (bg_input_plugin_t*)(com->handle->plugin); if(com->plugin->set_track && !com->plugin->set_track(com->handle->priv, com->track)) return 0; com->ti = com->plugin->get_track_info(com->handle->priv, com->track); if(!(com->ti->flags & BG_TRACK_SEEKABLE)) { bg_log(BG_LOG_ERROR, LOG_DOMAIN, "EDL only works with seekable sources"); return 0; } com->read_stream = com->stream; com->read_data = com->handle->priv; return 1; } static void cleanup_source_common(source_common_t * com) { if(com->handle) bg_plugin_unref(com->handle); } static int read_subtitle_overlay_convert(void * priv, gavl_overlay_t*ovl, int stream) { subtitle_source_t * sosrc; sosrc = (subtitle_source_t*)priv; if(!sosrc->ovl.frame) sosrc->ovl.frame = gavl_video_frame_create(sosrc->format); if(!sosrc->com.plugin->read_subtitle_overlay(sosrc->com.handle->priv, &sosrc->ovl, sosrc->com.stream)) return 0; gavl_video_convert(sosrc->cnv, sosrc->ovl.frame, ovl->frame); /* TODO: Scale coordinates if source- and destination sizes are different */ gavl_rectangle_i_copy(&ovl->ovl_rect, &sosrc->ovl.ovl_rect); ovl->dst_x = sosrc->ovl.dst_x; ovl->dst_y = sosrc->ovl.dst_y; /* Need to undo the timescale and duration scaling */ ovl->frame->timestamp = sosrc->ovl.frame->timestamp; ovl->frame->duration = sosrc->ovl.frame->duration; return 1; } static int start_edl(void * priv) { int i, j; edl_dec_t * dec; bg_track_info_t * ti; dec = (edl_dec_t*)priv; ti = &dec->track_info[dec->current_track]; for(i = 0; i < dec->edl->tracks[dec->current_track].num_audio_streams; i++) { audio_source_t * asrc; audio_stream_t * as; as = &dec->tracks[dec->current_track].audio_streams[i]; if(as->action != BG_STREAM_ACTION_DECODE) continue; /* Fire up the sources */ for(j = 0; j < as->num_sources; j++) { asrc = &as->sources[j]; if(!init_source_common(dec, &asrc->com)) return 0; if(asrc->com.plugin->set_audio_stream && !asrc->com.plugin->set_audio_stream(asrc->com.handle->priv, asrc->com.stream, BG_STREAM_ACTION_DECODE)) return 0; if(asrc->com.plugin->start && !asrc->com.plugin->start(asrc->com.handle->priv)) return 0; asrc->read_func = asrc->com.plugin->read_audio; asrc->format = &asrc->com.ti->audio_streams[asrc->com.stream].format; if(!j) { gavl_audio_format_copy(&ti->audio_streams[i].format, asrc->format); as->format = &ti->audio_streams[i].format; } else { if(bg_audio_converter_init(asrc->cnv, asrc->format, as->format)) { bg_audio_converter_connect_input(asrc->cnv, asrc->read_func, asrc->com.read_data, asrc->com.read_stream); asrc->read_func = bg_audio_converter_read; asrc->com.read_data = asrc->cnv; asrc->com.read_stream = 0; } } as->frame = gavl_audio_frame_create(as->format); } /* Initialize first segment */ as->current_segment = 0; init_audio_segment(as); } for(i = 0; i < dec->edl->tracks[dec->current_track].num_video_streams; i++) { video_stream_t * vs; video_source_t * vsrc; vs = &dec->tracks[dec->current_track].video_streams[i]; if(vs->action != BG_STREAM_ACTION_DECODE) continue; /* Fire up the sources */ for(j = 0; j < vs->num_sources; j++) { vsrc = &vs->sources[j]; if(!init_source_common(dec, &vs->sources[j].com)) return 0; if(vsrc->com.plugin->set_video_stream && !vsrc->com.plugin->set_video_stream(vsrc->com.handle->priv, vsrc->com.stream, BG_STREAM_ACTION_DECODE)) return 0; if(vsrc->com.plugin->start && !vsrc->com.plugin->start(vsrc->com.handle->priv)) return 0; vsrc->read_func = vsrc->com.plugin->read_video; vsrc->format = &vsrc->com.ti->video_streams[vsrc->com.stream].format; if(!j) { gavl_video_format_copy(&ti->video_streams[i].format, vsrc->format); vs->format = &ti->video_streams[i].format; } else { if(bg_video_converter_init(vsrc->cnv, vsrc->format, vs->format)) { bg_video_converter_connect_input(vsrc->cnv, vsrc->read_func, vsrc->com.read_data, vsrc->com.read_stream); vsrc->read_func = bg_video_converter_read; vsrc->com.read_data = vsrc->cnv; vsrc->com.read_stream = 0; } } } /* Initialize first segment */ vs->current_segment = 0; init_video_segment(vs); } for(i = 0; i < dec->edl->tracks[dec->current_track].num_subtitle_text_streams; i++) { subtitle_stream_t * sts; subtitle_source_t * stsrc; bg_subtitle_info_t * si; si = &ti->subtitle_streams[i]; sts = &dec->tracks[dec->current_track].subtitle_text_streams[i]; if(sts->action != BG_STREAM_ACTION_DECODE) continue; /* Fire up the sources */ for(j = 0; j < sts->num_sources; j++) { stsrc = &sts->sources[j]; if(!init_source_common(dec, &sts->sources[j].com)) return 0; if(stsrc->com.plugin->set_subtitle_stream && !stsrc->com.plugin->set_subtitle_stream(stsrc->com.handle->priv, stsrc->com.stream, BG_STREAM_ACTION_DECODE)) return 0; if(stsrc->com.plugin->start && !stsrc->com.plugin->start(stsrc->com.handle->priv)) return 0; stsrc->format = &stsrc->com.ti->subtitle_streams[stsrc->com.stream].format; if(!j) { gavl_video_format_copy(&si->format, stsrc->format); sts->format = &si->format; } } /* Initialize first segment */ sts->current_segment = 0; init_subtitle_segment(sts); } for(i = 0; i < dec->edl->tracks[dec->current_track].num_subtitle_overlay_streams; i++) { subtitle_stream_t * sos; subtitle_source_t * sosrc; bg_subtitle_info_t * si; sos = &dec->tracks[dec->current_track].subtitle_overlay_streams[i]; if(sos->action != BG_STREAM_ACTION_DECODE) continue; si = &ti->subtitle_streams[i + dec->edl->tracks[dec->current_track].num_subtitle_text_streams]; /* Fire up the sources */ for(j = 0; j < sos->num_sources; j++) { sosrc = &sos->sources[j]; if(!init_source_common(dec, &sos->sources[j].com)) return 0; if(sosrc->com.plugin->set_subtitle_stream && !sosrc->com.plugin->set_subtitle_stream(sosrc->com.handle->priv, sosrc->com.stream, BG_STREAM_ACTION_DECODE)) return 0; if(sosrc->com.plugin->start && !sosrc->com.plugin->start(sosrc->com.handle->priv)) return 0; sosrc->read_func = sosrc->com.plugin->read_subtitle_overlay; sosrc->format = &sosrc->com.ti->subtitle_streams[sosrc->com.stream].format; if(!j) { gavl_video_format_copy(&si->format, sosrc->format); sos->format = &si->format; } else { if(gavl_video_converter_init(sosrc->cnv, sosrc->format, sos->format)) { sosrc->read_func = read_subtitle_overlay_convert; sosrc->com.read_data = sosrc; // sosrc->com.read_stream must be unchanged } } } /* Initialize first segment */ sos->current_segment = 0; init_subtitle_segment(sos); } return 1; } static int read_audio_edl(void * priv, gavl_audio_frame_t* frame, int stream, int num_samples) { int samples_decoded = 0; edl_dec_t * dec; audio_stream_t * as; int num; segment_t * seg; audio_source_t * src; dec = (edl_dec_t*)priv; as = &dec->tracks[dec->current_track].audio_streams[stream]; if(as->current_segment >= as->num_segments) return 0; while(samples_decoded < num_samples) { num = as->format->samples_per_frame; /* Check for end of frame */ if(samples_decoded + num > num_samples) num = num_samples - samples_decoded; /* Check for end of segment */ if(as->out_time + samples_decoded + num > as->segment_end_time) num = as->segment_end_time - (as->out_time + samples_decoded); while(!num) { /* End of segment */ as->current_segment++; if(as->current_segment >= as->num_segments) { /* End of stream */ break; } else /* New segment (skip empty ones) */ { init_audio_segment(as); num = as->format->samples_per_frame; /* Check for end of frame */ if(samples_decoded + num > num_samples) num = num_samples - samples_decoded; /* Check for end of segment */ if(as->out_time + samples_decoded + num > as->segment_end_time) num = as->segment_end_time - (as->out_time + samples_decoded); } } if(!num) break; seg = &as->segments[as->current_segment]; if(!seg->src) { gavl_audio_frame_mute_samples(as->frame, as->format, num); } else { src = (audio_source_t *)(seg->src); if(!src->read_func(seg->src->read_data, as->frame, seg->src->read_stream, num)) return samples_decoded; } num = gavl_audio_frame_copy(as->format, frame, as->frame, samples_decoded /* dst_pos */, 0 /* src_pos */ , num_samples - samples_decoded, as->frame->valid_samples); samples_decoded += num; } frame->timestamp = as->out_time; frame->valid_samples = samples_decoded; as->out_time += samples_decoded; return samples_decoded; } static int read_video_edl(void * priv, gavl_video_frame_t* frame, int stream) { edl_dec_t * dec; video_stream_t * vs; segment_t * seg; video_source_t * src; dec = (edl_dec_t*)priv; vs = &dec->tracks[dec->current_track].video_streams[stream]; if(vs->current_segment >= vs->num_segments) return 0; while(vs->out_time >= vs->segment_end_time) { vs->current_segment++; if(vs->current_segment >= vs->num_segments) return 0; init_video_segment(vs); } seg = &vs->segments[vs->current_segment]; if(!seg->src) { gavl_video_frame_clear(frame, vs->format); frame->timestamp = vs->out_time; frame->duration = vs->format->frame_duration; vs->out_time += vs->format->frame_duration; } else { src = (video_source_t *)seg->src; if(!src->read_func(src->com.read_data, frame, src->com.read_stream)) { bg_log(BG_LOG_WARNING, LOG_DOMAIN, "Unexpected EOF, clearing frame"); gavl_video_frame_clear(frame, vs->format); } frame->timestamp = vs->out_time; // vs->out_time = frame->timestamp + frame->duration; vs->out_time += frame->duration; } return 1; } static int has_subtitle_edl(void * priv, int stream) { // edl_dec_t * dec; // dec = (edl_dec_t*)priv; return 1; } typedef struct { gavl_overlay_t * ovl; char ** text; int * text_alloc; int64_t * start_time; int64_t * duration; subtitle_stream_t * s; } decode_subtitle_data; static int decode_subtitle_text(decode_subtitle_data * d) { subtitle_source_t * src; src = (subtitle_source_t*)(d->s->segments[d->s->current_segment].src); return src->com.plugin->read_subtitle_text(src->com.handle->priv, d->text, d->text_alloc, d->start_time, d->duration, src->com.stream); } static int decode_subtitle_overlay(decode_subtitle_data * d) { subtitle_source_t * src; src = (subtitle_source_t*)(d->s->segments[d->s->current_segment].src); return src->read_func(src->com.read_data, d->ovl, src->com.stream); } /* Here, the actual magic happens */ static int decode_subtitle(int (*decode_func)(decode_subtitle_data*), decode_subtitle_data * d) { if(d->s->current_segment >= d->s->es->num_segments) return 0; while(1) { /* Check is segment is finished */ if(d->s->out_time >= d->s->segment_end_time) { d->s->current_segment++; if(d->s->current_segment >= d->s->es->num_segments) return 0; init_subtitle_segment(d->s); } /* Decode one subtitle */ if(!decode_func(d)) { d->s->current_segment++; if(d->s->current_segment >= d->s->es->num_segments) return 0; init_subtitle_segment(d->s); continue; } /* Correct timestamps */ *d->start_time = gavl_time_rescale(((subtitle_source_t*)(d->s->segments[d->s->current_segment].src))->format->timescale, d->s->format->timescale, *d->start_time) + d->s->time_offset; *d->duration = gavl_time_rescale(((subtitle_source_t*)(d->s->segments[d->s->current_segment].src))->format->timescale, d->s->format->timescale, *d->duration); /* Still inside the segment */ if(*d->start_time < d->s->segment_end_time) { if(*d->start_time + *d->duration > d->s->segment_end_time) *d->duration = d->s->segment_end_time - *d->start_time; d->s->out_time = *d->start_time + *d->duration; break; } /* Subtitle there but after segment */ else { d->s->out_time = d->s->segment_end_time; } } return 1; } static int read_subtitle_overlay_edl(void * priv, gavl_overlay_t*ovl, int stream) { edl_dec_t * dec; decode_subtitle_data d; dec = (edl_dec_t*)priv; d.ovl = ovl; d.start_time = &ovl->frame->timestamp; d.duration = &ovl->frame->duration; d.s = &dec->tracks[dec->current_track].subtitle_overlay_streams[stream - dec->edl->tracks[dec->current_track].num_subtitle_text_streams]; return decode_subtitle(decode_subtitle_overlay, &d); } static int read_subtitle_text_edl(void * priv, char ** text, int * text_alloc, int64_t * start_time, int64_t * duration, int stream) { edl_dec_t * dec; decode_subtitle_data d; dec = (edl_dec_t*)priv; d.text = text; d.text_alloc = text_alloc; d.start_time = start_time; d.duration = duration; d.s = &dec->tracks[dec->current_track].subtitle_text_streams[stream]; return decode_subtitle(decode_subtitle_text, &d); } static void seek_edl(void * priv, int64_t * time, int scale) { edl_dec_t * dec; int i; track_t * t; bg_edl_track_t * et; int64_t time_scaled; dec = (edl_dec_t*)priv; t = &dec->tracks[dec->current_track]; et = &dec->edl->tracks[dec->current_track]; for(i = 0; i < et->num_audio_streams; i++) { if(t->audio_streams[i].action != BG_STREAM_ACTION_DECODE) continue; time_scaled = gavl_time_rescale(scale, t->audio_streams[i].format->samplerate, *time); t->audio_streams[i].current_segment = seek_segment(t->audio_streams[i].es, t->audio_streams[i].segments, t->audio_streams[i].num_segments, time_scaled, t->audio_streams[i].format->samplerate); if(t->audio_streams[i].current_segment < 0) { bg_log(BG_LOG_ERROR, LOG_DOMAIN, "Seeked audio out of range"); return; } t->audio_streams[i].out_time = time_scaled; init_audio_segment(&t->audio_streams[i]); } for(i = 0; i < et->num_video_streams; i++) { if(t->video_streams[i].action != BG_STREAM_ACTION_DECODE) continue; time_scaled = gavl_time_rescale(scale, t->video_streams[i].format->timescale, *time); t->video_streams[i].current_segment = seek_segment(t->video_streams[i].es, t->video_streams[i].segments, t->video_streams[i].num_segments, time_scaled, t->video_streams[i].format->timescale); if(t->video_streams[i].current_segment < 0) { bg_log(BG_LOG_ERROR, LOG_DOMAIN, "Seeked video out of range"); return; } t->video_streams[i].out_time = time_scaled; init_video_segment(&t->video_streams[i]); } for(i = 0; i < et->num_subtitle_text_streams; i++) { if(t->subtitle_text_streams[i].action != BG_STREAM_ACTION_DECODE) continue; time_scaled = gavl_time_rescale(scale, t->subtitle_text_streams[i].format->timescale, *time); t->subtitle_text_streams[i].current_segment = seek_segment(t->subtitle_text_streams[i].es, t->subtitle_text_streams[i].segments, t->subtitle_text_streams[i].num_segments, time_scaled, t->subtitle_text_streams[i].format->timescale); if(t->subtitle_text_streams[i].current_segment < 0) { bg_log(BG_LOG_ERROR, LOG_DOMAIN, "Seeked text subtitles out of range"); return; } t->subtitle_text_streams[i].out_time = time_scaled; init_subtitle_segment(&t->subtitle_text_streams[i]); } for(i = 0; i < et->num_subtitle_overlay_streams; i++) { if(t->subtitle_overlay_streams[i].action != BG_STREAM_ACTION_DECODE) continue; time_scaled = gavl_time_rescale(scale, t->subtitle_overlay_streams[i].format->timescale, *time); t->subtitle_overlay_streams[i].current_segment = seek_segment(t->subtitle_overlay_streams[i].es, t->subtitle_overlay_streams[i].segments, t->subtitle_overlay_streams[i].num_segments, time_scaled, t->subtitle_overlay_streams[i].format->timescale); if(t->subtitle_overlay_streams[i].current_segment < 0) { bg_log(BG_LOG_ERROR, LOG_DOMAIN, "Seeked text subtitles out of range"); return; } t->subtitle_overlay_streams[i].out_time = time_scaled; init_subtitle_segment(&t->subtitle_overlay_streams[i]); } } static void close_edl(void * priv) { int i, j, k; edl_dec_t * dec; dec = (edl_dec_t*)priv; for(i = 0; i < dec->edl->num_tracks; i++) { for(j = 0; j < dec->edl->tracks[i].num_audio_streams; j++) { /* Close sources */ for(k = 0; k < dec->tracks[i].audio_streams[j].num_sources; k++) { cleanup_source_common(&dec->tracks[i].audio_streams[j].sources[k].com); if(dec->tracks[i].audio_streams[j].sources[k].cnv) bg_audio_converter_destroy(dec->tracks[i].audio_streams[j].sources[k].cnv); } if(dec->tracks[i].audio_streams[j].sources) free(dec->tracks[i].audio_streams[j].sources); if(dec->tracks[i].audio_streams[j].segments) free(dec->tracks[i].audio_streams[j].segments); if(dec->tracks[i].audio_streams[j].frame) gavl_audio_frame_destroy(dec->tracks[i].audio_streams[j].frame); } if(dec->tracks[i].audio_streams) free(dec->tracks[i].audio_streams); for(j = 0; j < dec->edl->tracks[i].num_video_streams; j++) { /* Close sources */ for(k = 0; k < dec->tracks[i].video_streams[j].num_sources; k++) { cleanup_source_common(&dec->tracks[i].video_streams[j].sources[k].com); if(dec->tracks[i].video_streams[j].sources[k].cnv) bg_video_converter_destroy(dec->tracks[i].video_streams[j].sources[k].cnv); } if(dec->tracks[i].video_streams[j].sources) free(dec->tracks[i].video_streams[j].sources); if(dec->tracks[i].video_streams[j].segments) free(dec->tracks[i].video_streams[j].segments); } if(dec->tracks[i].video_streams) free(dec->tracks[i].video_streams); for(j = 0; j < dec->edl->tracks[i].num_subtitle_text_streams; j++) { /* Close sources */ for(k = 0; k < dec->tracks[i].subtitle_text_streams[j].num_sources; k++) cleanup_source_common(&dec->tracks[i].subtitle_text_streams[j].sources[k].com); if(dec->tracks[i].subtitle_text_streams[j].sources) free(dec->tracks[i].subtitle_text_streams[j].sources); if(dec->tracks[i].subtitle_text_streams[j].segments) free(dec->tracks[i].subtitle_text_streams[j].segments); } if(dec->tracks[i].subtitle_text_streams) free(dec->tracks[i].subtitle_text_streams); for(j = 0; j < dec->edl->tracks[i].num_subtitle_overlay_streams; j++) { /* Close sources */ for(k = 0; k < dec->tracks[i].subtitle_overlay_streams[j].num_sources; k++) { cleanup_source_common(&dec->tracks[i].subtitle_overlay_streams[j].sources[k].com); if(dec->tracks[i].subtitle_overlay_streams[j].sources[k].cnv) gavl_video_converter_destroy(dec->tracks[i].subtitle_overlay_streams[j].sources[k].cnv); } if(dec->tracks[i].subtitle_overlay_streams[j].sources) free(dec->tracks[i].subtitle_overlay_streams[j].sources); if(dec->tracks[i].subtitle_overlay_streams[j].segments) free(dec->tracks[i].subtitle_overlay_streams[j].segments); } if(dec->tracks[i].subtitle_overlay_streams) free(dec->tracks[i].subtitle_overlay_streams); } if(dec->tracks) { free(dec->tracks); dec->tracks = NULL; } if(dec->track_info) { for(i = 0; i < dec->edl->num_tracks; i++) { bg_track_info_free(&dec->track_info[i]); } free(dec->track_info); dec->track_info = NULL; } } static void destroy_edl(void * priv) { edl_dec_t * dec; dec = (edl_dec_t*)priv; if(dec->tracks) close_edl(priv); gavl_audio_options_destroy(dec->a_opt); gavl_video_options_destroy(dec->v_opt); free(priv); } static const bg_input_plugin_t edl_plugin = { .common = { BG_LOCALE, .name = "i_edldec", .long_name = TRS("EDL decoder"), .description = TRS("This metaplugin decodes an EDL as if it was a single file."), .type = BG_PLUGIN_INPUT, .flags = 0, .priority = 1, .create = NULL, .destroy = destroy_edl, // .get_parameters = get_parameters_edl, // .set_parameter = set_parameter_edl }, // .open = open_input, .set_callbacks = set_callbacks_edl, .get_num_tracks = get_num_tracks_edl, .get_track_info = get_track_info_edl, .set_track = set_track_edl, /* Set streams */ .set_video_stream = set_video_stream_edl, .set_audio_stream = set_audio_stream_edl, .set_subtitle_stream = set_subtitle_stream_edl, /* * Start decoding. * Track info is the track, which should be played. * The plugin must take care of the "active" fields * in the stream infos to check out, which streams are to be decoded */ .start = start_edl, /* Read one video frame (returns FALSE on EOF) */ .read_video = read_video_edl, .read_audio = read_audio_edl, .has_subtitle = has_subtitle_edl, .read_subtitle_text = read_subtitle_text_edl, .read_subtitle_overlay = read_subtitle_overlay_edl, /* * Do percentage seeking (can be NULL) * Media streams are supposed to be seekable, if this * function is non-NULL AND the duration field of the track info * is > 0 */ .seek = seek_edl, /* Stop playback, close all decoders */ // .stop = stop_edl, .close = close_edl, }; bg_plugin_info_t * bg_edldec_get_info() { return bg_plugin_info_create(&edl_plugin.common); } int bg_input_plugin_load_edl(bg_plugin_registry_t * reg, const bg_edl_t * edl, const bg_plugin_info_t * info, bg_plugin_handle_t ** ret1, bg_input_callbacks_t * callbacks) { int i, j, k; const bg_edl_track_t * track; const bg_edl_stream_t * stream; bg_track_info_t * ti; track_t * t; edl_dec_t * priv; bg_plugin_handle_t * ret; gavl_time_t test_duration; if(*ret1) bg_plugin_unref(*ret1); ret = calloc(1, sizeof(*ret)); *ret1 = ret; // ret->plugin_reg = reg; ret->plugin = (bg_plugin_common_t*)(&edl_plugin); ret->info = info; pthread_mutex_init(&ret->mutex, NULL); priv = calloc(1, sizeof(*priv)); ret->priv = priv; ret->refcount = 1; priv->edl = edl; priv->plugin_reg = reg; priv->callbacks = callbacks; priv->track_info = calloc(edl->num_tracks, sizeof(*priv->track_info)); priv->tracks = calloc(edl->num_tracks, sizeof(*priv->tracks)); priv->a_opt = gavl_audio_options_create(); priv->v_opt = gavl_video_options_create(); for(i = 0; i < edl->num_tracks; i++) { track = &edl->tracks[i]; ti = &priv->track_info[i]; t = &priv->tracks[i]; ti->name = bg_strdup(ti->name, track->name); gavl_metadata_copy(&ti->metadata, &track->metadata); ti->flags |= (BG_TRACK_SEEKABLE|BG_TRACK_PAUSABLE); ti->num_audio_streams = track->num_audio_streams; ti->audio_streams = calloc(ti->num_audio_streams, sizeof(*ti->audio_streams)); t->audio_streams = calloc(ti->num_audio_streams, sizeof(*t->audio_streams)); /* Audio streams */ for(j = 0; j < track->num_audio_streams; j++) { stream = &track->audio_streams[j]; t->audio_streams[j].sources = calloc(stream->num_segments, sizeof(*t->audio_streams[j].sources)); t->audio_streams[j].es = stream; for(k = 0; k < stream->num_segments; k++) { add_audio_segment(priv, i, j, &stream->segments[k]); } test_duration = gavl_time_unscale(stream->timescale, ti->audio_streams[j].duration); if(ti->duration < test_duration) ti->duration = test_duration; } /* Video streams */ ti->num_video_streams = track->num_video_streams; ti->video_streams = calloc(ti->num_video_streams, sizeof(*ti->video_streams)); t->video_streams = calloc(ti->num_video_streams, sizeof(*t->video_streams)); for(j = 0; j < track->num_video_streams; j++) { stream = &track->video_streams[j]; t->video_streams[j].sources = calloc(stream->num_segments, sizeof(*t->video_streams[j].sources)); t->video_streams[j].es = stream; for(k = 0; k < stream->num_segments; k++) { add_video_segment(priv, i, j, &stream->segments[k]); } test_duration = gavl_time_unscale(stream->timescale, ti->video_streams[j].duration); if(ti->duration < test_duration) ti->duration = test_duration; } /* Subtitle text streams */ ti->num_subtitle_streams = track->num_subtitle_text_streams + track->num_subtitle_overlay_streams; ti->subtitle_streams = calloc(ti->num_subtitle_streams, sizeof(*ti->subtitle_streams)); t->subtitle_text_streams = calloc(track->num_subtitle_text_streams, sizeof(*t->subtitle_text_streams)); t->subtitle_overlay_streams = calloc(track->num_subtitle_overlay_streams, sizeof(*t->subtitle_overlay_streams)); for(j = 0; j < track->num_subtitle_text_streams; j++) { stream = &track->subtitle_text_streams[j]; t->subtitle_text_streams[j].sources = calloc(stream->num_segments, sizeof(*t->subtitle_text_streams[j].sources)); t->subtitle_text_streams[j].es = stream; for(k = 0; k < stream->num_segments; k++) { add_subtitle_text_segment(priv, i, j, &stream->segments[k]); } test_duration = gavl_time_unscale(stream->timescale, ti->subtitle_streams[j].duration); if(ti->duration < test_duration) ti->duration = test_duration; ti->subtitle_streams[j].is_text = 1; } /* Subtitle overlay streams */ for(j = 0; j < track->num_subtitle_overlay_streams; j++) { stream = &track->subtitle_overlay_streams[j]; t->subtitle_overlay_streams[j].sources = calloc(stream->num_segments, sizeof(*t->subtitle_overlay_streams[j].sources)); t->subtitle_overlay_streams[j].es = stream; for(k = 0; k < stream->num_segments; k++) { add_subtitle_overlay_segment(priv, i, j, &stream->segments[k]); } test_duration = gavl_time_unscale(stream->timescale, ti->subtitle_streams[j+track->num_subtitle_text_streams].duration); if(ti->duration < test_duration) ti->duration = test_duration; } } return 1; } gmerlin-1.2.0~dfsg/lib/tree.c0000644000175000017500000011655011764363410015757 0ustar alessioalessio/***************************************************************** * gmerlin - a general purpose multimedia framework and applications * * Copyright (c) 2001 - 2011 Members of the Gmerlin project * gmerlin-general@lists.sourceforge.net * http://gmerlin.sourceforge.net * * 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 of the License, 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 this program. If not, see . * *****************************************************************/ #include #include #include /* For stat/opendir */ #include #include #include #include #include /* Gmerlin includes */ #include #include #include #include #include #include #define LOG_DOMAIN "mediatree" #ifdef HAVE_INOTIFY #include #endif static int nth_in_list(bg_album_t * children, bg_album_t * child) { int ret; bg_album_t * tmp_album; ret = 0; tmp_album = children; while(tmp_album) { if(tmp_album == child) return ret; ret++; tmp_album = tmp_album->next; } return -1; } int * bg_media_tree_get_path(bg_media_tree_t * tree, bg_album_t * album) { bg_album_t * parent; bg_album_t * child; int depth; int * ret; int i; /* Get the depth of the album */ depth = 1; parent = album->parent; while(parent) { depth++; parent = parent->parent; } /* Fill indices */ ret = malloc((depth+1)* sizeof(int)); ret[depth] = -1; child = album; parent = child->parent; for(i = depth-1; i >= 1; i--) { ret[i] = nth_in_list(parent->children, child); parent = parent->parent; child = child->parent; } ret[0] = nth_in_list(tree->children, child); return ret; } static bg_album_t * append_album(bg_album_t * list, bg_album_t * new_album) { bg_album_t * a; if(!list) return new_album; a = list; while(a->next) a = a->next; a->next = new_album; return list; } static bg_album_t * remove_from_list(bg_album_t * list, bg_album_t * album) { bg_album_t * sibling_before; if(album == list) return album->next; else { sibling_before = list; while(sibling_before->next != album) sibling_before = sibling_before->next; sibling_before->next = album->next; return list; } } /* Insert new album into list */ static bg_album_t * insert_album_after(bg_album_t * list, bg_album_t * new_album, bg_album_t * sibling) { if(!list) { new_album->next = NULL; return new_album; } if(!sibling) { new_album->next = list; return new_album; } new_album->next = sibling->next; sibling->next = new_album; return list; } static bg_album_t * insert_album_before(bg_album_t * list, bg_album_t * new_album, bg_album_t * sibling) { bg_album_t * before; if(!list) { new_album->next = NULL; return new_album; } before = list; if(list == sibling) { new_album->next = list; return new_album; } while(before->next != sibling) before = before->next; return insert_album_after(list, new_album, before); } /* Functions used both by tree and album */ static int get_num_albums(bg_album_t * list) { int ret = 0; if(list) { ret++; while(list->next) { list = list->next; ret++; } } return ret; } static bg_album_t * get_album(bg_album_t * list, int index) { int i; for(i = 0; i < index; i++) list = list->next; return list; } /* For album */ int bg_album_get_num_children(bg_album_t * a) { return get_num_albums(a->children); } bg_album_t * bg_album_get_child(bg_album_t * a, int i) { return get_album(a->children, i); } /* For tree */ int bg_media_tree_get_num_albums(bg_media_tree_t * t) { return get_num_albums(t->children); } bg_album_t * bg_media_tree_get_album(bg_media_tree_t * t, int i) { return get_album(t->children, i); } bg_plugin_registry_t * bg_media_tree_get_plugin_registry(bg_media_tree_t * t) { return t->com.plugin_reg; } static void check_special(bg_media_tree_t * tree, bg_album_t * children) { bg_album_t * a; a = children; while(a) { if(a->type == BG_ALBUM_TYPE_INCOMING) { tree->incoming = a; bg_album_rename(a, TR("Incoming")); } else if(a->type == BG_ALBUM_TYPE_FAVOURITES) { tree->com.favourites = a; bg_album_rename(a, TR("Favourites")); } a = a->next; /* Check children */ if(a && a->children) check_special(tree, a->children); } } static int get_user_pass(void * data, const char * resource, char ** user, char ** pass) { bg_album_common_t * com = (bg_album_common_t *)data; if(!com->username && !com->password) { if(!com->userpass_callback) return 0; if(!com->userpass_callback(resource, user, pass, &com->save_auth, com->userpass_callback_data)) return 0; /* Store user and password in the common area so we can use it later on */ com->username = bg_strdup(com->username, *user); com->password = bg_strdup(com->password, *pass); } else { *user = bg_strdup(*user, com->username); *pass = bg_strdup(*pass, com->password); } return 1; } static bg_album_t * find_by_plugin(bg_album_t * albums, const char * plugin) { while(albums) { if(albums->plugin_info && !strcmp(albums->plugin_info->name, plugin)) return albums; albums = albums->next; } return NULL; } static bg_album_t * find_by_device(bg_album_t * albums, const char * device) { while(albums) { if(albums->device && !strcmp(albums->device, device)) return albums; albums = albums->next; } return NULL; } static void add_device_plugins(bg_media_tree_t * ret, bg_plugin_registry_t * plugin_reg, int flag, bg_album_type_t type) { bg_album_t * plugin_album; bg_album_t * device_album; int num_plugins, i, j; const bg_plugin_info_t * info; num_plugins = bg_plugin_registry_get_num_plugins(ret->com.plugin_reg, BG_PLUGIN_INPUT, flag); for(i = 0; i < num_plugins; i++) { info = bg_plugin_find_by_index(ret->com.plugin_reg, i, BG_PLUGIN_INPUT, flag); /* Add album for the plugin */ if(!(plugin_album = find_by_plugin(ret->children, info->name))) { plugin_album = bg_album_create(&ret->com, BG_ALBUM_TYPE_PLUGIN, NULL); bg_bindtextdomain(info->gettext_domain, info->gettext_directory); plugin_album->plugin_info = info; ret->children = append_album(ret->children, plugin_album); } plugin_album->name = bg_strdup(plugin_album->name, TRD(info->long_name, info->gettext_domain)); /* Now, get the number of devices */ if(info->devices && info->devices->device) { j = 0; while(info->devices[j].device) { if(!(device_album = find_by_device(plugin_album->children, info->devices[j].device))) { device_album = bg_album_create(&ret->com, type, plugin_album); device_album->device = bg_strdup(device_album->device, info->devices[j].device); if(info->devices[j].name) { device_album->name = bg_strdup(device_album->name, info->devices[j].name); } else { device_album->name = bg_strdup(device_album->name, info->devices[j].device); } device_album->plugin_info = info; plugin_album->children = append_album(plugin_album->children, device_album); } j++; } /* Device loop */ /* TODO: Remove albums, whose devices vanished */ } } /* Plugin loop */ } bg_media_tree_t * bg_media_tree_create(const char * filename, bg_plugin_registry_t * plugin_reg) { bg_media_tree_t * ret; const char * pos1; ret = calloc(1, sizeof(*ret)); ret->cfg_section = bg_cfg_section_create(NULL); ret->com.plugin_reg = plugin_reg; ret->com.set_current_callback = bg_media_tree_set_current; ret->com.set_current_callback_data = ret; ret->com.input_callbacks.user_pass = get_user_pass; ret->com.input_callbacks.data = &ret->com; #ifdef HAVE_INOTIFY ret->com.inotify_fd = inotify_init(); #endif ret->filename = bg_strdup(ret->filename, filename); pos1 = strrchr(ret->filename, '/'); ret->com.directory = bg_strndup(ret->com.directory, ret->filename, pos1); return ret; } void bg_media_tree_init(bg_media_tree_t * ret) { /* Load the entire tree */ bg_media_tree_load(ret); /* Create special albums if necessary */ check_special(ret, ret->children); if(!ret->incoming) { ret->incoming = bg_album_create(&ret->com, BG_ALBUM_TYPE_INCOMING, NULL); ret->incoming->name = bg_strdup(ret->incoming->name, TR("Incoming")); ret->incoming->xml_file = bg_strdup(ret->incoming->xml_file, "incoming.xml"); ret->children = append_album(ret->children, ret->incoming); } if(!ret->com.favourites) { ret->com.favourites = bg_album_create(&ret->com, BG_ALBUM_TYPE_FAVOURITES, NULL); ret->com.favourites->name = bg_strdup(ret->com.favourites->name, TR("Favourites")); ret->com.favourites->xml_file = bg_strdup(ret->com.favourites->xml_file, "favourites.xml"); ret->children = append_album(ret->children, ret->com.favourites); } /* Check for removable devices */ add_device_plugins(ret, ret->com.plugin_reg, BG_PLUGIN_TUNER, BG_ALBUM_TYPE_TUNER); add_device_plugins(ret, ret->com.plugin_reg, BG_PLUGIN_REMOVABLE, BG_ALBUM_TYPE_REMOVABLE); } void bg_media_tree_destroy(bg_media_tree_t * t) { bg_album_t * next_album; bg_media_tree_save(t); if(t->purge_directory) bg_media_tree_purge_directory(t); bg_cfg_section_destroy(t->cfg_section); while(t->children) { next_album = t->children->next; bg_album_destroy(t->children); t->children = next_album; } if(t->com.directory) free(t->com.directory); if(t->com.metadata_format) free(t->com.metadata_format); if(t->com.blacklist) free(t->com.blacklist); if(t->com.blacklist_files) free(t->com.blacklist_files); if(t->com.load_handle) bg_plugin_unref(t->com.load_handle); if(t->filename) free(t->filename); if(t->add_directory_path) free(t->add_directory_path); #ifdef HAVE_INOTIFY close(t->com.inotify_fd); #endif free(t); } bg_album_t * bg_media_tree_append_album(bg_media_tree_t * tree, bg_album_t * parent) { bg_album_t * album_before; bg_album_t * album_after; bg_album_t * new_album = bg_album_create(&tree->com, BG_ALBUM_TYPE_REGULAR, parent); if(parent) { bg_album_append_child(parent, new_album); } /* Top level album, take care of the system albums */ else { if(tree->children) { album_before = tree->children; /* Tree has only device albums */ if(album_before->type == BG_ALBUM_TYPE_PLUGIN) { new_album->next = tree->children; tree->children = new_album; } else { while(album_before->next && (album_before->next->type != BG_ALBUM_TYPE_PLUGIN)) album_before = album_before->next; album_after = album_before->next; album_before->next = new_album; new_album->next = album_after; } } else tree->children = new_album; } return new_album; } void bg_media_tree_remove_album(bg_media_tree_t * tree, bg_album_t * album) { char * tmp_path = NULL; if(album->parent) bg_album_remove_from_parent(album); else tree->children = remove_from_list(tree->children, album); /* Check if album file if present */ if(album->xml_file) tmp_path = bg_sprintf("%s/%s", tree->com.directory, album->xml_file); /* Schredder everything */ bg_album_destroy(album); if(tmp_path) { remove(tmp_path); free(tmp_path); } } /* Check if we can move an album */ static int check_move_common(bg_media_tree_t * t, bg_album_t * album, bg_album_t * sibling) { bg_album_t * parent; if(album == sibling) return 0; parent = sibling->parent; while(parent) { if(album == parent) return 0; parent = parent->parent; } return 1; } int bg_media_tree_check_move_album_before(bg_media_tree_t * t, bg_album_t * album, bg_album_t * after) { if(!check_move_common(t, album, after)) { return 0; } /* Never drop after removable albums */ switch(after->type) { case BG_ALBUM_TYPE_REMOVABLE: case BG_ALBUM_TYPE_PLUGIN: case BG_ALBUM_TYPE_TUNER: return 0; case BG_ALBUM_TYPE_INCOMING: case BG_ALBUM_TYPE_FAVOURITES: case BG_ALBUM_TYPE_REGULAR: return 1; } return 1; } int bg_media_tree_check_move_album_after(bg_media_tree_t * t, bg_album_t * album, bg_album_t * before) { if(!check_move_common(t, album, before)) { return 0; } /* Never drop after removable albums */ switch(before->type) { case BG_ALBUM_TYPE_REMOVABLE: case BG_ALBUM_TYPE_PLUGIN: case BG_ALBUM_TYPE_TUNER: return 0; case BG_ALBUM_TYPE_INCOMING: case BG_ALBUM_TYPE_FAVOURITES: case BG_ALBUM_TYPE_REGULAR: return 1; } return 1; } /* Move an album inside the tree */ void bg_media_tree_move_album_before(bg_media_tree_t * t, bg_album_t * album, bg_album_t * after) { if(!bg_media_tree_check_move_album_before(t, album, after)) return; /* Remove the album from the parent's children list */ if(album->parent) { album->parent->children = remove_from_list(album->parent->children, album); } else { t->children = remove_from_list(t->children, album); } /* Insert at new location */ if(after->parent) { after->parent->children = insert_album_before(after->parent->children, album, after); album->parent = after->parent; } else { t->children = insert_album_before(t->children, album, after); album->parent = NULL; } } void bg_media_tree_move_album_after(bg_media_tree_t * t, bg_album_t * album, bg_album_t * before) { if(!bg_media_tree_check_move_album_after(t, album, before)) return; /* Remove the album from the parent's children list */ if(album->parent) { album->parent->children = remove_from_list(album->parent->children, album); } else { t->children = remove_from_list(t->children, album); } /* Insert at new location */ if(before->parent) { before->parent->children = insert_album_after(before->parent->children, album, before); album->parent = before->parent; } else { t->children = insert_album_after(t->children, album, before); album->parent = NULL; } } int bg_media_tree_check_move_album(bg_media_tree_t * t, bg_album_t * album, bg_album_t * parent) { bg_album_t * test_album; /* Never move album into it's subalbum */ test_album = parent; while(test_album) { if(album == test_album) return 0; test_album = test_album->parent; } /* Never drop into removable albums */ switch(parent->type) { case BG_ALBUM_TYPE_REMOVABLE: case BG_ALBUM_TYPE_PLUGIN: case BG_ALBUM_TYPE_TUNER: return 0; case BG_ALBUM_TYPE_REGULAR: case BG_ALBUM_TYPE_INCOMING: case BG_ALBUM_TYPE_FAVOURITES: return 1; } return 1; } void bg_media_tree_move_album(bg_media_tree_t * t, bg_album_t * album, bg_album_t * parent) { if(!bg_media_tree_check_move_album(t, album, parent)) return; /* Remove the album from the parent's children list */ if(album->parent) { album->parent->children = remove_from_list(album->parent->children, album); } else { t->children = remove_from_list(t->children, album); } if(!parent) { t->children = insert_album_before(t->children, album, NULL); album->parent = NULL; } else { parent->children = insert_album_before(parent->children, album, NULL); album->parent = parent; } } /* Set and get entries for playback */ void bg_media_tree_set_current(void * data, bg_album_t * album, const bg_album_entry_t * entry) { bg_album_t * last_current_album; bg_media_tree_t * t = (bg_media_tree_t*)data; last_current_album = t->com.current_album; if((last_current_album != album) && t->com.shuffle_list && (t->last_shuffle_mode == BG_SHUFFLE_MODE_CURRENT)) { bg_shuffle_list_destroy(t->com.shuffle_list); t->com.shuffle_list = NULL; } t->com.current_album = album; if(t->com.current_album) { t->com.current_entry = t->com.current_album->entries; while(t->com.current_entry != entry) t->com.current_entry = t->com.current_entry->next; } else { t->com.current_entry = NULL; } if(last_current_album && (last_current_album != album)) bg_album_current_changed(last_current_album); if(album) bg_album_current_changed(album); if(t->change_callback) t->change_callback(t, t->change_callback_data); } /* Shuffle list stuff */ static bg_shuffle_list_t * get_shuffle_tracks(bg_album_t * album, bg_shuffle_list_t * list, bg_shuffle_list_t ** last_entry, int all_open) { bg_album_t * tmp_album; bg_album_entry_t * tmp_entry; if(bg_album_is_open(album)) { tmp_entry = album->entries; while(tmp_entry) { if(list) { (*last_entry)->next = calloc(1, sizeof(*((*last_entry)->next))); *last_entry = (*last_entry)->next; } else { list = calloc(1, sizeof(*list)); *last_entry = list; } (*last_entry)->album = album; (*last_entry)->entry = tmp_entry; tmp_entry = tmp_entry->next; } } /* Do the same for the children */ if(all_open) { tmp_album = album->children; while(tmp_album) { list = get_shuffle_tracks(tmp_album, list, last_entry, 1); tmp_album = tmp_album->next; } } return list; } static void create_shuffle_list(bg_media_tree_t * tree, bg_shuffle_mode_t shuffle_mode) { int rand_max; int64_t index; int i; bg_album_t * tmp; bg_shuffle_list_t * list, *tmp_entry; bg_shuffle_list_t ** array_1; bg_shuffle_list_t ** array_2; int num; /* 1. Create the list */ list = NULL; tmp_entry = NULL; if(shuffle_mode == BG_SHUFFLE_MODE_ALL) { tmp = tree->children; while(tmp) { list = get_shuffle_tracks(tmp, list, &tmp_entry, 1); tmp = tmp->next; } } else if(tree->com.current_album) list = get_shuffle_tracks(tree->com.current_album, list, &tmp_entry, 0); else return; /* 2. Count the entries */ num = 0; tmp_entry = list; while(tmp_entry) { num++; tmp_entry = tmp_entry->next; } /* 3. Create first array */ array_1 = malloc(num * sizeof(*array_1)); array_2 = malloc(num * sizeof(*array_2)); tmp_entry = list; for(i = 0; i < num; i++) { array_1[i] = tmp_entry; tmp_entry = tmp_entry->next; } /* 4. Shuffle */ for(i = 0; i < num - 1; i++) { rand_max = num - i - 1; index = ((int64_t)rand() * (int64_t)(rand_max-1)) / RAND_MAX; array_2[i] = array_1[index]; if(index < rand_max) array_1[index] = array_1[num - i - 1]; } array_2[num - 1] = array_1[0]; /* 5. Set the next pointers for the list */ for(i = 0; i < num - 1; i++) { array_2[i]->next = array_2[i+1]; array_2[i+1]->prev = array_2[i]; } array_2[0]->prev = NULL; array_2[num-1]->next = NULL; /* 6. Cleanup */ tree->com.shuffle_list = array_2[0]; tree->last_shuffle_mode = shuffle_mode; tree->shuffle_current = tree->com.shuffle_list; free(array_1); free(array_2); } static void check_shuffle_list(bg_media_tree_t * tree, bg_shuffle_mode_t shuffle_mode) { if(tree->com.shuffle_list && (tree->last_shuffle_mode != shuffle_mode)) { bg_shuffle_list_destroy(tree->com.shuffle_list); tree->com.shuffle_list = NULL; } if(!tree->com.shuffle_list) { create_shuffle_list(tree, shuffle_mode); } } /* Set the next and previous track */ int bg_media_tree_next(bg_media_tree_t * tree, int wrap, bg_shuffle_mode_t shuffle_mode) { if(shuffle_mode == BG_SHUFFLE_MODE_OFF) { if(tree->com.current_album) return bg_album_next(tree->com.current_album, wrap); else return 0; } else { check_shuffle_list(tree, shuffle_mode); if(!tree->com.shuffle_list) return 0; if(!tree->shuffle_current->next) { if(wrap) tree->shuffle_current = tree->com.shuffle_list; else return 0; } else tree->shuffle_current = tree->shuffle_current->next; bg_media_tree_set_current(tree, tree->shuffle_current->album, tree->shuffle_current->entry); return 1; } return 0; } int bg_media_tree_previous(bg_media_tree_t * tree, int wrap, bg_shuffle_mode_t shuffle_mode) { if(shuffle_mode == BG_SHUFFLE_MODE_OFF) { if(tree->com.current_album) return bg_album_previous(tree->com.current_album, wrap); else return 0; } else { check_shuffle_list(tree, shuffle_mode); if(!tree->shuffle_current->prev) { if(wrap) { while(tree->shuffle_current->next) tree->shuffle_current = tree->shuffle_current->next; } else return 0; } else tree->shuffle_current = tree->shuffle_current->prev; bg_media_tree_set_current(tree, tree->shuffle_current->album, tree->shuffle_current->entry); return 1; } return 0; } void bg_shuffle_list_destroy(bg_shuffle_list_t * l) { bg_shuffle_list_t * tmp; tmp = l; while(tmp) { tmp = l->next; free(l); l = tmp; } } void bg_media_tree_set_change_callback(bg_media_tree_t * tree, void (*change_callback)(bg_media_tree_t*, void*), void* change_callback_data) { tree->change_callback = change_callback; tree->change_callback_data = change_callback_data; } void bg_media_tree_set_play_callback(bg_media_tree_t * tree, void (*play_callback)(void*), void* play_callback_data) { tree->com.play_callback = play_callback; tree->com.play_callback_data = play_callback_data; } void bg_media_tree_set_userpass_callback(bg_media_tree_t * tree, int (*userpass_callback)(const char * resource, char ** user, char ** pass, int * save_password, void * data), void * userpass_callback_data) { tree->com.userpass_callback = userpass_callback; tree->com.userpass_callback_data = userpass_callback_data; } bg_plugin_handle_t * bg_media_tree_get_current_track(bg_media_tree_t * t, int * index) { bg_track_info_t * track_info; const bg_plugin_info_t * info; bg_input_plugin_t * input_plugin; bg_plugin_handle_t * ret = NULL; if(!t->com.current_entry || !t->com.current_album) { bg_log(BG_LOG_ERROR, LOG_DOMAIN, "Doubleclick on a track first"); goto fail; } if((t->com.current_album->type == BG_ALBUM_TYPE_REMOVABLE) || (t->com.current_album->type == BG_ALBUM_TYPE_TUNER)) { ret = t->com.current_album->handle; bg_plugin_ref(ret); input_plugin = (bg_input_plugin_t*)(ret->plugin); } else { if(t->com.current_entry->plugin) info = bg_plugin_find_by_name(t->com.plugin_reg, t->com.current_entry->plugin); else info = bg_plugin_find_by_filename(t->com.plugin_reg, t->com.current_entry->location, (BG_PLUGIN_INPUT)); #if 0 if(!info) { bg_log(BG_LOG_ERROR, LOG_DOMAIN, "Cannot open %s: no plugin found"); goto fail; } #endif bg_log(BG_LOG_INFO, LOG_DOMAIN, "Loading %s (plugin: %s)", (char*)t->com.current_entry->location, (info ? info->name : "auto")); bg_album_common_prepare_callbacks(&t->com, t->com.current_entry); if(!bg_input_plugin_load(t->com.plugin_reg, t->com.current_entry->location, info, &ret, &t->com.input_callbacks, !!(t->com.current_entry->flags & BG_ALBUM_ENTRY_EDL))) { bg_log(BG_LOG_ERROR, LOG_DOMAIN, "Loading %s failed", (char*)t->com.current_entry->location); goto fail; } input_plugin = (bg_input_plugin_t*)(ret->plugin); } track_info = input_plugin->get_track_info(ret->priv, t->com.current_entry->index); if(!track_info) { bg_log(BG_LOG_ERROR, LOG_DOMAIN, "Selecting track %d for %s failed", t->com.current_entry->index+1, (char*)t->com.current_entry->location); goto fail; } bg_album_update_entry(t->com.current_album, t->com.current_entry, track_info, 1, 0); bg_album_common_set_auth_info(&t->com, t->com.current_entry); // bg_album_changed(t->com.current_album); if(index) *index = t->com.current_entry->index; return ret; fail: bg_media_tree_mark_error(t, 1); return NULL; } bg_album_t * bg_media_tree_get_current_album(bg_media_tree_t * t) { return t->com.current_album; } const char * bg_media_tree_get_current_track_name(bg_media_tree_t * t) { if(!t->com.current_album || !t->com.current_entry) return NULL; return t->com.current_entry->name; } /* Parameter stuff */ static const bg_parameter_info_t parameters[] = { { .name = "use_metadata", .long_name = TRS("Use metadata for track names"), .type = BG_PARAMETER_CHECKBUTTON, .val_default = { .val_i = 1 }, .help_string = TRS("If disabled, track name will be taken from filename") }, { .name = "metadata_format", .long_name = TRS("Format for track names"), .type = BG_PARAMETER_STRING, .val_default = { .val_str = "%p - %t" }, .help_string = TRS("Format specifier for tracknames from\n\ metadata\n\ %p: Artist\n\ %a: Album\n\ %g: Genre\n\ %t: Track name\n\ %n: Track number with digits\n\ %y: Year\n\ %c: Comment"), }, { .name = "purge_directory", .long_name = TRS("Purge directory on exit"), .type = BG_PARAMETER_CHECKBUTTON, .val_default = { .val_i = 1 }, .help_string = TRS("Purge directory (i.e. delete\n\ unused album files) at program exit") }, { .name = "blacklist", .long_name = TRS("Blacklisted extensions"), .type = BG_PARAMETER_STRING, .val_default = { .val_str = "srt txt pdf nfo" }, .help_string = TRS("File extensions, which are never loaded automatically"), }, { .name = "blacklist_files", .long_name = TRS("Blacklisted filenames"), .type = BG_PARAMETER_STRING, .help_string = TRS("Filenames, which are never loaded automatically"), }, { .name = "add_directory_path", .type = BG_PARAMETER_STRING, .flags = BG_PARAMETER_HIDE_DIALOG, }, { /* End of parameters */ } }; const bg_parameter_info_t * bg_media_tree_get_parameters(bg_media_tree_t * tree) { return parameters; } int bg_media_tree_get_parameter(void * priv, const char * name, bg_parameter_value_t * val) { bg_media_tree_t * tree = priv; if(!name) return 0; if(!strcmp(name, "add_directory_path")) { val->val_str = bg_strdup(val->val_str, tree->add_directory_path); return 1; } return 9; } void bg_media_tree_set_parameter(void * priv, const char * name, const bg_parameter_value_t * val) { bg_media_tree_t * tree = priv; if(!name) return; if(!strcmp(name, "use_metadata")) { tree->com.use_metadata = val->val_i; } else if(!strcmp(name, "metadata_format")) { tree->com.metadata_format = bg_strdup(tree->com.metadata_format, val->val_str); } else if(!strcmp(name, "blacklist")) { tree->com.blacklist = bg_strdup(tree->com.blacklist, val->val_str); } else if(!strcmp(name, "blacklist_files")) { tree->com.blacklist_files = bg_strdup(tree->com.blacklist_files, val->val_str); } else if(!strcmp(name, "purge_directory")) { tree->purge_directory = val->val_i; } else if(!strcmp(name, "add_directory_path")) { tree->add_directory_path = bg_strdup(tree->add_directory_path, val->val_str); } } void bg_media_tree_mark_error(bg_media_tree_t * t, int err) { int err1; if(t->com.current_entry) { err1 = !!(t->com.current_entry->flags & BG_ALBUM_ENTRY_ERROR); err = !!err; if(err == err1) return; if(err) t->com.current_entry->flags |= BG_ALBUM_ENTRY_ERROR; else t->com.current_entry->flags &= ~BG_ALBUM_ENTRY_ERROR; } if(t->com.current_album && t->com.current_entry) bg_album_entry_changed(t->com.current_album, t->com.current_entry); } static void add_directory(bg_media_tree_t * t, bg_album_t * parent, const char * directory, int recursive, int subdirs_to_subalbums, int watch, const char * plugin, int prefer_edl, int depth) { char * tmp_string; DIR * dir; char filename[FILENAME_MAX]; struct { struct dirent d; char b[NAME_MAX]; /* Make sure there is enough memory */ } dent; struct dirent * dent_ptr; const char * pos1; struct stat stat_buf; char * urls[2]; bg_album_t * a; if(subdirs_to_subalbums || !depth) a = bg_media_tree_append_album(t, parent); else a = parent; if(parent) bg_album_set_expanded(parent, 1); bg_album_open(a); bg_album_set_expanded(a, 1); if(subdirs_to_subalbums || !depth) { pos1 = strrchr(directory, '/'); pos1++; tmp_string = bg_system_to_utf8(pos1, -1); bg_album_rename(a, tmp_string); free(tmp_string); } if(watch) bg_album_set_watch_dir(a, directory); /* Scan for regular files and directories */ dir = opendir(directory); if(!dir) return; urls[0] = filename; urls[1] = NULL; while(!readdir_r(dir, &dent.d, &dent_ptr)) { if(!dent_ptr) break; if(dent.d.d_name[0] == '.') /* Don't import hidden files */ continue; sprintf(filename, "%s/%s", directory, dent.d.d_name); if(stat(filename, &stat_buf)) { continue; } /* Add directory as subalbum */ if(recursive && S_ISDIR(stat_buf.st_mode)) { add_directory(t, a, filename, recursive, subdirs_to_subalbums, watch, plugin, prefer_edl, depth + 1); } else if(S_ISREG(stat_buf.st_mode)) { if(watch) bg_album_insert_file_before(a, filename, plugin, prefer_edl, NULL, stat_buf.st_mtime); else bg_album_insert_file_before(a, filename, plugin, prefer_edl, NULL, 0); } if(t->change_callback) t->change_callback(t, t->change_callback_data); } closedir(dir); bg_album_sort_entries(a); bg_album_sort_children(a); bg_album_close(a); if(t->change_callback) t->change_callback(t, t->change_callback_data); } /* Add an entire directory */ void bg_media_tree_add_directory(bg_media_tree_t * t, bg_album_t * parent, const char * directory, int recursive, int subdirs_to_subalbums, int watch, const char * plugin, int prefer_edl) { char * pos; add_directory(t, parent, directory, recursive, subdirs_to_subalbums, watch, plugin, prefer_edl, 0); t->add_directory_path = bg_strdup(t->add_directory_path, directory); pos = strrchr(t->add_directory_path, '/'); if(pos && (pos - t->add_directory_path < strlen(t->add_directory_path) - 1)) *pos = '\0'; } const char * bg_media_tree_get_add_directory_path(bg_media_tree_t * t) { return t->add_directory_path; } static int albums_have_file(bg_album_t * album, const char * filename) { bg_album_t * a; a = album; while(a) { if(a->xml_file && !strcmp(a->xml_file, filename)) return 1; else if(albums_have_file(a->children, filename)) return 1; a = a->next; } return 0; } void bg_media_tree_purge_directory(bg_media_tree_t * t) { DIR * dir; char filename[FILENAME_MAX]; struct dirent * dent_ptr; struct { struct dirent d; char b[NAME_MAX]; /* Make sure there is enough memory */ } dent; dir = opendir(t->com.directory); if(!dir) return; bg_log(BG_LOG_INFO, LOG_DOMAIN, "Purging %s", t->com.directory); while(!readdir_r(dir, &dent.d, &dent_ptr)) { if(!dent_ptr) break; if(!strcmp(dent.d.d_name, ".") || !strcmp(dent.d.d_name, "..") || !strcmp(dent.d.d_name, "tree.xml")) continue; if(!albums_have_file(t->children, dent.d.d_name)) { sprintf(filename, "%s/%s", t->com.directory, dent.d.d_name); bg_log(BG_LOG_INFO, LOG_DOMAIN, "Removing %s", filename); remove(filename); } } closedir(dir); } bg_album_t * bg_media_tree_get_incoming(bg_media_tree_t *t) { return t->incoming; } bg_cfg_section_t * bg_media_tree_get_cfg_section(bg_media_tree_t * t) { return t->cfg_section; } void bg_album_common_prepare_callbacks(bg_album_common_t * com, bg_album_entry_t * entry) { if(!entry) { if(com->username) { free(com->username); com->username = NULL; } if(com->password) { free(com->password); com->password = NULL; } com->save_auth = 0; } else { com->username = bg_strdup(com->username, entry->username); com->password = bg_strdup(com->password, entry->password); com->save_auth = !!(entry->flags & BG_ALBUM_ENTRY_SAVE_AUTH); } } void bg_album_common_set_auth_info(bg_album_common_t * com, bg_album_entry_t * entry) { if(!com->username || !com->password) return; entry->username = bg_strdup(entry->username, com->username); entry->password = bg_strdup(entry->password, com->password); if(com->save_auth) entry->flags |= BG_ALBUM_ENTRY_SAVE_AUTH; else entry->flags &= ~BG_ALBUM_ENTRY_SAVE_AUTH; } bg_album_t * bg_media_tree_get_device_album(bg_media_tree_t * t, const char * gml) { bg_album_t * ret = NULL; const bg_plugin_info_t * plugin_info; char * protocol = NULL; char * path = NULL; if(!bg_url_split(gml, &protocol, NULL, // user, NULL, // password, NULL, // hostname, NULL, // port, &path)) // path) return NULL; /* 1. Seek the plugin */ plugin_info = bg_plugin_find_by_protocol(t->com.plugin_reg, protocol); if(!plugin_info) goto fail; ret = t->children; while(ret && ((ret->type != BG_ALBUM_TYPE_PLUGIN) || strcmp(ret->plugin_info->name, plugin_info->name))) ret = ret->next; if(!ret) goto fail; /* Now, look for the device */ ret = ret->children; while(ret && strcmp(ret->device, path)) ret = ret->next; fail: if(path) free(path); if(protocol) free(protocol); return ret; } void bg_media_tree_copy_current_to_favourites(bg_media_tree_t * t) { int was_open; if(!t->com.current_entry) { bg_log(BG_LOG_WARNING, LOG_DOMAIN, "No current track for copying to favourites"); return; } if(!bg_album_is_open(t->com.favourites)) { bg_album_open(t->com.favourites); was_open = 0; } was_open = 1; bg_album_insert_entries_before(t->com.favourites, bg_album_entry_copy(t->com.current_album, t->com.current_entry), NULL); if(!was_open) bg_album_close(t->com.favourites); } #ifdef HAVE_INOTIFY #define EVENT_SIZE ( sizeof (struct inotify_event) ) #define BUF_LEN ( 1024 * ( EVENT_SIZE + 16 ) ) void bg_media_tree_check_sync(bg_media_tree_t * t) { int i, result; char buffer[BUF_LEN]; bg_album_t * a; struct timeval timeout; fd_set read_fds; /* Wait for event */ timeout.tv_sec = 0; timeout.tv_usec = 0; FD_ZERO(&read_fds); FD_SET(t->com.inotify_fd, &read_fds); if(!select(t->com.inotify_fd+1, &read_fds, NULL, NULL,&timeout)) return; result = read(t->com.inotify_fd, buffer, BUF_LEN); if(result < 0) return; i = 0; while ( i < result ) { struct inotify_event *event = ( struct inotify_event * ) &buffer[i]; a = t->children; while(a) { if(bg_album_inotify(a, (uint8_t*)(&buffer[ i ]))) break; a = a->next; } i += EVENT_SIZE + event->len; } } #else void bg_media_tree_check_sync(bg_media_tree_t * t) { } #endif gmerlin-1.2.0~dfsg/lib/recorder_video.c0000644000175000017500000006221211764363410020006 0ustar alessioalessio/***************************************************************** * gmerlin - a general purpose multimedia framework and applications * * Copyright (c) 2001 - 2011 Members of the Gmerlin project * gmerlin-general@lists.sourceforge.net * http://gmerlin.sourceforge.net * * 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 of the License, 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 this program. If not, see . * *****************************************************************/ #include #include #include #include // access() #include #include #include #include #include #define LOG_DOMAIN "recorder.video" #define FRAMERATE_INTERVAL 10 static int create_snapshot_cb(void * data, const char * filename) { bg_recorder_t * rec = data; bg_recorder_video_stream_t * vs = &rec->vs; int overwrite; pthread_mutex_lock(&rec->snapshot_mutex); overwrite = vs->flags & STREAM_SNAPSHOT_OVERWRITE; pthread_mutex_unlock(&rec->snapshot_mutex); if(!overwrite && !access(filename, R_OK)) { bg_log(BG_LOG_ERROR, LOG_DOMAIN, "Won't save snapshot %s (file exists)", filename); return 0; } bg_log(BG_LOG_INFO, LOG_DOMAIN, "Saving snapshot %s", filename); return 1; } static int ov_button_callback(void * data, int x, int y, int button, int mask) { bg_recorder_t * rec = data; bg_recorder_msg_button_press(rec, x, y, button, mask); return 1; } static int ov_button_release_callback(void * data, int x, int y, int button, int mask) { bg_recorder_t * rec = data; bg_recorder_msg_button_release(rec, x, y, button, mask); return 1; } static int ov_motion_callback(void * data, int x, int y, int mask) { bg_recorder_t * rec = data; bg_recorder_msg_motion(rec, x, y, mask); return 1; } void bg_recorder_create_video(bg_recorder_t * rec) { bg_recorder_video_stream_t * vs = &rec->vs; vs->monitor_cnv = gavl_video_converter_create(); vs->enc_cnv = gavl_video_converter_create(); vs->snapshot_cnv = gavl_video_converter_create(); bg_gavl_video_options_init(&vs->opt); vs->fc = bg_video_filter_chain_create(&vs->opt, rec->plugin_reg); vs->th = bg_player_thread_create(rec->tc); vs->timer = gavl_timer_create(); pthread_mutex_init(&vs->config_mutex, NULL); vs->snapshot_cb.create_output_file = create_snapshot_cb; vs->snapshot_cb.data = rec; vs->monitor_cb.button_callback = ov_button_callback; vs->monitor_cb.button_release_callback = ov_button_release_callback; vs->monitor_cb.motion_callback = ov_motion_callback; vs->monitor_cb.data = rec; pthread_mutex_init(&vs->eof_mutex, NULL); } void bg_recorder_video_set_eof(bg_recorder_video_stream_t * s, int eof) { pthread_mutex_lock(&s->eof_mutex); s->eof = eof; pthread_mutex_unlock(&s->eof_mutex); } int bg_recorder_video_get_eof(bg_recorder_video_stream_t * s) { int ret; pthread_mutex_lock(&s->eof_mutex); ret = s->eof; pthread_mutex_unlock(&s->eof_mutex); return ret; } void bg_recorder_destroy_video(bg_recorder_t * rec) { bg_recorder_video_stream_t * vs = &rec->vs; gavl_video_converter_destroy(vs->monitor_cnv); gavl_video_converter_destroy(vs->enc_cnv); gavl_video_converter_destroy(vs->snapshot_cnv); bg_video_filter_chain_destroy(vs->fc); bg_player_thread_destroy(vs->th); gavl_timer_destroy(vs->timer); pthread_mutex_destroy(&vs->config_mutex); if(vs->monitor_handle) bg_plugin_unref(vs->monitor_handle); if(vs->input_handle) bg_plugin_unref(vs->input_handle); if(vs->snapshot_handle) bg_plugin_unref(vs->snapshot_handle); bg_gavl_video_options_free(&vs->opt); pthread_mutex_destroy(&vs->eof_mutex); } static const bg_parameter_info_t parameters[] = { { .name = "do_video", .long_name = TRS("Record video"), .type = BG_PARAMETER_CHECKBUTTON, .val_default = { .val_i = 1 }, }, { .name = "plugin", .long_name = TRS("Plugin"), .type = BG_PARAMETER_MULTI_MENU, .flags = BG_PARAMETER_PLUGIN, }, { .name = "do_limit_fps", .long_name = TRS("Limit fps"), .type = BG_PARAMETER_CHECKBUTTON, .val_default = { .val_i = 1 }, .num_digits = 2, .help_string = TRS("Limit frames per second. " "By default, the maximum possible framerate will be used."), }, { .name = "limit_fps", .long_name = TRS("fps limit"), .type = BG_PARAMETER_FLOAT, .val_min = { .val_f = 1.0 }, .val_max = { .val_f = 100.0 }, .val_default = { .val_f = 25.0 }, .num_digits = 2, .help_string = TRS("Specify the maximum framerate for input plugins, which can \ capture images really fast"), }, { }, }; const bg_parameter_info_t * bg_recorder_get_video_parameters(bg_recorder_t * rec) { bg_recorder_video_stream_t * vs = &rec->vs; if(!vs->parameters) { vs->parameters = bg_parameter_info_copy_array(parameters); bg_plugin_registry_set_parameter_info(rec->plugin_reg, BG_PLUGIN_RECORDER_VIDEO, BG_PLUGIN_RECORDER, &vs->parameters[1]); } return vs->parameters; } void bg_recorder_set_video_parameter(void * data, const char * name, const bg_parameter_value_t * val) { bg_recorder_t * rec = data; bg_recorder_video_stream_t * vs = &rec->vs; if(!name) return; // if(name) // fprintf(stderr, "bg_recorder_set_video_parameter %s\n", name); if(!strcmp(name, "do_video")) { if((rec->flags & FLAG_RUNNING) && (!!(vs->flags & STREAM_ACTIVE) != val->val_i)) bg_recorder_interrupt(rec); if(val->val_i) vs->flags |= STREAM_ACTIVE; else vs->flags &= ~STREAM_ACTIVE; } else if(!strcmp(name, "plugin")) { const bg_plugin_info_t * info; if(vs->input_handle && !strcmp(vs->input_handle->info->name, val->val_str)) return; if(rec->flags & FLAG_RUNNING) bg_recorder_interrupt(rec); if(vs->input_handle) bg_plugin_unref(vs->input_handle); info = bg_plugin_find_by_name(rec->plugin_reg, val->val_str); vs->input_handle = bg_plugin_load(rec->plugin_reg, info); vs->input_plugin = (bg_recorder_plugin_t*)(vs->input_handle->plugin); if(vs->input_plugin->set_callbacks) vs->input_plugin->set_callbacks(vs->input_handle->priv, &rec->recorder_cb); } else if(!strcmp(name, "limit_fps")) { pthread_mutex_lock(&vs->config_mutex); vs->limit_timescale = (int)(val->val_f * 100.0); vs->limit_duration = 100; pthread_mutex_unlock(&vs->config_mutex); } else if(!strcmp(name, "do_limit_fps")) { pthread_mutex_lock(&vs->config_mutex); vs->do_limit_fps = val->val_i; pthread_mutex_unlock(&vs->config_mutex); } else if(vs->input_handle && vs->input_plugin->common.set_parameter) { vs->input_plugin->common.set_parameter(vs->input_handle->priv, name, val); } } /* Monitor */ static const bg_parameter_info_t monitor_parameters[] = { { .name = "do_monitor", .long_name = TRS("Enable monitor"), .type = BG_PARAMETER_CHECKBUTTON, .val_default = { .val_i = 1 }, }, { .name = "plugin", .long_name = TRS("Plugin"), .type = BG_PARAMETER_MULTI_MENU, .flags = BG_PARAMETER_PLUGIN, }, { }, }; const bg_parameter_info_t * bg_recorder_get_video_monitor_parameters(bg_recorder_t * rec) { bg_recorder_video_stream_t * vs = &rec->vs; if(!vs->monitor_parameters) { vs->monitor_parameters = bg_parameter_info_copy_array(monitor_parameters); bg_plugin_registry_set_parameter_info(rec->plugin_reg, BG_PLUGIN_OUTPUT_VIDEO, BG_PLUGIN_PLAYBACK, &vs->monitor_parameters[1]); } return vs->monitor_parameters; } void bg_recorder_set_video_monitor_parameter(void * data, const char * name, const bg_parameter_value_t * val) { bg_recorder_t * rec = data; bg_recorder_video_stream_t * vs = &rec->vs; if(!name) return; // if(name) // fprintf(stderr, "bg_recorder_set_video_monitor_parameter %s\n", name); if(!strcmp(name, "do_monitor")) { if(!!(vs->flags & STREAM_MONITOR) != val->val_i) bg_recorder_interrupt(rec); if(val->val_i) vs->flags |= STREAM_MONITOR; else vs->flags &= ~STREAM_MONITOR; } else if(!strcmp(name, "plugin")) { const bg_plugin_info_t * info; if(vs->monitor_handle && !strcmp(vs->monitor_handle->info->name, val->val_str)) return; bg_recorder_interrupt(rec); if(vs->monitor_handle) bg_plugin_unref(vs->monitor_handle); info = bg_plugin_find_by_name(rec->plugin_reg, val->val_str); vs->monitor_handle = bg_ov_plugin_load(rec->plugin_reg, info, rec->display_string); vs->monitor_plugin = (bg_ov_plugin_t*)(vs->monitor_handle->plugin); if(vs->monitor_plugin->set_callbacks) vs->monitor_plugin->set_callbacks(vs->monitor_handle->priv, &vs->monitor_cb); if(vs->monitor_plugin->show_window && rec->display_string) vs->monitor_plugin->show_window(vs->monitor_handle->priv, 1); } else if(vs->monitor_handle && vs->monitor_plugin->common.set_parameter) { vs->monitor_plugin->common.set_parameter(vs->monitor_handle->priv, name, val); } } static const bg_parameter_info_t snapshot_parameters[] = { { .name = "snapshot_auto", .long_name = TRS("Automatic"), .type = BG_PARAMETER_CHECKBUTTON, }, { .name = "snapshot_interval", .long_name = TRS("Snapshot interval"), .type = BG_PARAMETER_FLOAT, .val_default = { .val_f = 5.0 }, .val_min = { .val_f = 0.5 }, .val_max = { .val_f = 10000.0 }, .num_digits = 1, }, { .name = "snapshot_overwrite", .long_name = TRS("Overwrite existing files"), .type = BG_PARAMETER_CHECKBUTTON, }, { .name = "plugin", .long_name = TRS("Plugin"), .type = BG_PARAMETER_MULTI_MENU, }, { /* End */ } }; const bg_parameter_info_t * bg_recorder_get_video_snapshot_parameters(bg_recorder_t * rec) { bg_recorder_video_stream_t * vs = &rec->vs; if(!vs->snapshot_parameters) { vs->snapshot_parameters = bg_parameter_info_copy_array(snapshot_parameters); bg_plugin_registry_set_parameter_info(rec->plugin_reg, BG_PLUGIN_IMAGE_WRITER, BG_PLUGIN_FILE, &vs->snapshot_parameters[3]); } return vs->snapshot_parameters; } void bg_recorder_set_video_snapshot_parameter(void * data, const char * name, const bg_parameter_value_t * val) { bg_recorder_t * rec; bg_recorder_video_stream_t * vs; if(!name) return; rec = data; vs = &rec->vs; if(!strcmp(name, "snapshot_auto")) { pthread_mutex_lock(&rec->snapshot_mutex); if(val->val_i) vs->flags |= STREAM_SNAPSHOT_AUTO; else vs->flags &= ~STREAM_SNAPSHOT_AUTO; pthread_mutex_unlock(&rec->snapshot_mutex); } else if(!strcmp(name, "snapshot_overwrite")) { if(val->val_i) vs->flags |= STREAM_SNAPSHOT_OVERWRITE; else vs->flags &= ~STREAM_SNAPSHOT_OVERWRITE; } else if(!strcmp(name, "snapshot_interval")) vs->snapshot_interval = gavl_seconds_to_time(val->val_f); else if( !strcmp(name, "plugin")) { const bg_plugin_info_t * info; if(vs->snapshot_handle && !strcmp(vs->snapshot_handle->info->name, val->val_str)) return; bg_recorder_interrupt(rec); if(vs->snapshot_handle) bg_plugin_unref(vs->snapshot_handle); info = bg_plugin_find_by_name(rec->plugin_reg, val->val_str); vs->snapshot_handle = bg_plugin_load(rec->plugin_reg, info); vs->snapshot_plugin = (bg_image_writer_plugin_t*)(vs->snapshot_handle->plugin); if(vs->snapshot_plugin->set_callbacks) vs->snapshot_plugin->set_callbacks(vs->snapshot_handle->priv, &vs->snapshot_cb); } else { vs->snapshot_plugin->common.set_parameter(vs->snapshot_handle->priv, name, val); } } const bg_parameter_info_t * bg_recorder_get_video_filter_parameters(bg_recorder_t * rec) { bg_recorder_video_stream_t * vs = &rec->vs; return bg_video_filter_chain_get_parameters(vs->fc); } void bg_recorder_set_video_filter_parameter(void * data, const char * name, const bg_parameter_value_t * val) { int need_restart; bg_recorder_t * rec = data; bg_recorder_video_stream_t * vs = &rec->vs; if(!name) { bg_recorder_resume(rec); return; } bg_video_filter_chain_lock(vs->fc); bg_video_filter_chain_set_parameter(vs->fc, name, val); if(bg_video_filter_chain_need_restart(vs->fc)) need_restart = 1; else need_restart = 0; bg_video_filter_chain_unlock(vs->fc); if(need_restart) bg_recorder_interrupt(rec); } #define BUFFER_SIZE 256 static char * create_snapshot_filename(bg_recorder_t * rec, int * have_count) { char mask[16]; char buf[BUFFER_SIZE]; char * pos; char * end; char * filename; int have_time = 0; time_t t; struct tm time_date; filename = bg_sprintf("%s/", rec->snapshot_directory); pos = rec->snapshot_filename_mask; if(have_count) *have_count = 0; while(1) { end = pos; while((*end != '%') && (*end != '\0')) { end++; } if(end - pos) filename = bg_strncat(filename, pos, end); if(*end == '\0') break; pos = end; /* Insert frame count */ if(isdigit(pos[1]) && (pos[2] == 'n')) { mask[0] = '%'; mask[1] = '0'; mask[2] = pos[1]; mask[3] = 'd'; mask[4] = '\0'; sprintf(buf, mask, rec->vs.snapshot_counter); filename = bg_strcat(filename, buf); pos += 3; if(have_count) *have_count = 1; } /* Insert date */ else if(pos[1] == 'd') { if(!have_time) { time(&t); localtime_r(&t, &time_date); have_time = 1; } strftime(buf, BUFFER_SIZE, "%Y-%m-%d", &time_date); filename = bg_strcat(filename, buf); pos += 2; } /* Insert date */ else if(pos[1] == 't') { if(!have_time) { time(&t); localtime_r(&t, &time_date); have_time = 1; } strftime(buf, BUFFER_SIZE, "%H-%M-%S", &time_date); filename = bg_strcat(filename, buf); pos += 2; } else { filename = bg_strcat(filename, "%"); pos++; } } return filename; } static void check_snapshot(bg_recorder_t * rec) { int doit = 0; char * filename; gavl_time_t frame_time; bg_recorder_video_stream_t * vs = &rec->vs; frame_time = gavl_time_unscale(vs->pipe_format.timescale, vs->pipe_frame->timestamp); /* Check whether to make a snapshot */ pthread_mutex_lock(&rec->snapshot_mutex); if(rec->snapshot) { doit = 1; rec->snapshot = 0; } if(!doit && ((vs->flags & STREAM_SNAPSHOT_AUTO) && (!(vs->flags & STREAM_SNAPSHOT_INIT) || frame_time >= vs->last_snapshot_time + vs->snapshot_interval))) { doit = 1; } pthread_mutex_unlock(&rec->snapshot_mutex); if(!doit) return; filename = create_snapshot_filename(rec, NULL); /* Initialize snapshot plugin */ if(!(vs->flags & STREAM_SNAPSHOT_INIT)) gavl_video_format_copy(&vs->snapshot_format, &vs->pipe_format); if(!vs->snapshot_plugin->write_header(vs->snapshot_handle->priv, filename, &vs->snapshot_format, &rec->m)) return; if(!(vs->flags & STREAM_SNAPSHOT_INIT)) { vs->do_convert_snapshot = gavl_video_converter_init(vs->snapshot_cnv, &vs->pipe_format, &vs->snapshot_format); if(vs->do_convert_snapshot) vs->snapshot_frame = gavl_video_frame_create(&vs->snapshot_format); vs->flags |= STREAM_SNAPSHOT_INIT; } if(vs->do_convert_snapshot) { gavl_video_convert(vs->snapshot_cnv, vs->pipe_frame, vs->snapshot_frame); vs->snapshot_plugin->write_image(vs->snapshot_handle->priv, vs->snapshot_frame); } else { vs->snapshot_plugin->write_image(vs->snapshot_handle->priv, vs->pipe_frame); } vs->snapshot_counter++; vs->last_snapshot_time = frame_time; } void * bg_recorder_video_thread(void * data) { bg_recorder_t * rec = data; bg_recorder_video_stream_t * vs = &rec->vs; gavl_video_frame_t * monitor_frame = NULL; gavl_time_t idle_time = GAVL_TIME_SCALE / 100; // 10 ms bg_player_thread_wait_for_start(vs->th); gavl_timer_set(vs->timer, 0); gavl_timer_start(vs->timer); while(1) { if(!bg_player_thread_check(vs->th)) break; if(bg_recorder_video_get_eof(vs)) { gavl_time_delay(&idle_time); continue; } vs->pipe_frame = NULL; if(vs->flags & STREAM_MONITOR) { monitor_frame = vs->monitor_plugin->get_frame(vs->monitor_handle->priv); if(!vs->do_convert_monitor) vs->pipe_frame = monitor_frame; } if(!vs->pipe_frame) vs->pipe_frame = vs->pipe_frame_priv; if(!vs->in_func(vs->in_data, vs->pipe_frame, vs->in_stream)) { bg_log(BG_LOG_ERROR, LOG_DOMAIN, "Read failed (device unplugged?)"); bg_recorder_video_set_eof(vs, 1); continue; // Need to go to bg_player_thread_check to stop the thread cleanly } /* Check whether to make a snapshot */ check_snapshot(rec); /* Monitor */ if(vs->flags & STREAM_MONITOR) { if(vs->do_convert_monitor) gavl_video_convert(vs->monitor_cnv, vs->pipe_frame, monitor_frame); vs->monitor_plugin->put_video(vs->monitor_handle->priv, monitor_frame); } if(vs->monitor_plugin && vs->monitor_plugin->handle_events) vs->monitor_plugin->handle_events(vs->monitor_handle->priv); /* Encoding */ if(vs->flags & STREAM_ENCODE_OPEN) { bg_recorder_update_time(rec, gavl_time_unscale(vs->pipe_format.timescale, vs->pipe_frame->timestamp)); if(vs->do_convert_enc) { gavl_video_convert(vs->enc_cnv, vs->pipe_frame, vs->enc_frame); bg_encoder_write_video_frame(rec->enc, vs->enc_frame, vs->enc_index); } else bg_encoder_write_video_frame(rec->enc, vs->pipe_frame, vs->enc_index); } /* */ } gavl_timer_stop(vs->timer); return NULL; } static int read_video_internal(void * data, gavl_video_frame_t * frame, int stream) { gavl_time_t diff_time, time_after, cur_time, next_frame_time; int ret; bg_recorder_t * rec = data; bg_recorder_video_stream_t * vs = &rec->vs; /* Limit the captured framerate */ if(vs->frame_counter) { pthread_mutex_lock(&vs->config_mutex); if(vs->do_limit_fps) { next_frame_time = vs->last_frame_time + gavl_frames_to_time(vs->limit_timescale, vs->limit_duration, 1); pthread_mutex_unlock(&vs->config_mutex); cur_time = gavl_timer_get(vs->timer); diff_time = next_frame_time - cur_time - vs->last_capture_duration; if(diff_time > 0) gavl_time_delay(&diff_time); } else pthread_mutex_unlock(&vs->config_mutex); } cur_time = gavl_timer_get(vs->timer); ret = vs->input_plugin->read_video(vs->input_handle->priv, frame, 0); time_after = gavl_timer_get(vs->timer); vs->last_capture_duration = time_after - cur_time; vs->frame_counter++; /* Calculate actual framerate */ vs->fps_frame_counter++; if(vs->fps_frame_counter == FRAMERATE_INTERVAL) vs->fps_frame_counter = 0; if(!vs->fps_frame_counter) { bg_recorder_msg_framerate(rec, (double)(FRAMERATE_INTERVAL*GAVL_TIME_SCALE) / (double)(time_after - vs->fps_frame_time)); vs->fps_frame_time = time_after; } vs->last_frame_time = time_after; return ret; } int bg_recorder_video_init(bg_recorder_t * rec) { bg_recorder_video_stream_t * vs = &rec->vs; vs->frame_counter = 0; vs->fps_frame_time = 0; vs->fps_frame_counter = 0; /* Open input */ if(!vs->input_plugin->open(vs->input_handle->priv, NULL, &vs->input_format)) return 0; vs->flags |= STREAM_INPUT_OPEN; vs->in_func = read_video_internal; vs->in_stream = 0; vs->in_data = rec; /* Set up filter chain */ bg_video_filter_chain_connect_input(vs->fc, vs->in_func, vs->in_data, vs->in_stream); vs->in_func = bg_video_filter_chain_read; vs->in_data = vs->fc; vs->in_stream = 0; bg_video_filter_chain_init(vs->fc, &vs->input_format, &vs->pipe_format); /* Set up monitoring */ if(vs->flags & STREAM_MONITOR) { gavl_video_format_copy(&vs->monitor_format, &vs->pipe_format); vs->monitor_plugin->open(vs->monitor_handle->priv, &vs->monitor_format, 1); vs->do_convert_monitor = gavl_video_converter_init(vs->monitor_cnv, &vs->pipe_format, &vs->monitor_format); vs->flags |= STREAM_MONITOR_OPEN; if(vs->monitor_plugin->show_window && !rec->display_string) { vs->monitor_plugin->show_window(vs->monitor_handle->priv, 1); if(vs->monitor_plugin->set_window_title) vs->monitor_plugin->set_window_title(vs->monitor_handle->priv, "Gmerlin recorder "VERSION); } } else vs->do_convert_monitor = 0; /* Set up encoding */ if(vs->flags & STREAM_ENCODE) { vs->enc_index = bg_encoder_add_video_stream(rec->enc, NULL, &vs->pipe_format, 0); } /* Create frames */ #if 0 if(vs->flags & STREAM_MONITOR) { if(vs->monitor_plugin->create_frame) vs->monitor_frame = vs->monitor_plugin->create_frame(vs->monitor_handle->priv); else vs->monitor_frame = gavl_video_frame_create(&vs->monitor_format); } #endif if(vs->do_convert_monitor || !(vs->flags & STREAM_MONITOR)) vs->pipe_frame_priv = gavl_video_frame_create(&vs->pipe_format); /* Initialize snapshot counter */ return 1; } void bg_recorder_video_finalize_encode(bg_recorder_t * rec) { bg_recorder_video_stream_t * vs = &rec->vs; bg_encoder_get_video_format(rec->enc, vs->enc_index, &vs->enc_format); /* * The encoder might have changed the framerate. * This affects the pipe_format as well, but not the other formats */ vs->pipe_format.framerate_mode = vs->enc_format.framerate_mode; vs->pipe_format.timescale = vs->enc_format.timescale; vs->pipe_format.frame_duration = vs->enc_format.frame_duration; bg_video_filter_chain_set_out_format(vs->fc, &vs->pipe_format); vs->do_convert_enc = gavl_video_converter_init(vs->enc_cnv, &vs->pipe_format, &vs->enc_format); if(vs->do_convert_enc) vs->enc_frame = gavl_video_frame_create(&vs->enc_format); vs->flags |= STREAM_ENCODE_OPEN; } void bg_recorder_video_cleanup(bg_recorder_t * rec) { bg_recorder_video_stream_t * vs = &rec->vs; if(vs->flags & STREAM_INPUT_OPEN) vs->input_plugin->close(vs->input_handle->priv); if(vs->pipe_frame_priv) gavl_video_frame_destroy(vs->pipe_frame_priv); vs->pipe_frame_priv = NULL; if(vs->flags & STREAM_MONITOR_OPEN) vs->monitor_plugin->close(vs->monitor_handle->priv); if(vs->enc_frame) { gavl_video_frame_destroy(vs->enc_frame); vs->enc_frame = NULL; } vs->flags &= ~(STREAM_INPUT_OPEN | STREAM_ENCODE_OPEN | STREAM_MONITOR_OPEN | STREAM_SNAPSHOT_INIT); } gmerlin-1.2.0~dfsg/lib/metadata.c0000644000175000017500000002402011764363410016566 0ustar alessioalessio/***************************************************************** * gmerlin - a general purpose multimedia framework and applications * * Copyright (c) 2001 - 2011 Members of the Gmerlin project * gmerlin-general@lists.sourceforge.net * http://gmerlin.sourceforge.net * * 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 of the License, 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 this program. If not, see . * *****************************************************************/ #include #include #include #include #include #include #include #include #include #define PARAM_ARTIST \ { \ .name = "artist", \ .long_name = TRS("Artist"), \ .type = BG_PARAMETER_STRING, \ } #define PARAM_ALBUMARTIST \ { \ .name = "albumartist", \ .long_name = TRS("Album artist"), \ .type = BG_PARAMETER_STRING, \ } #define PARAM_TITLE \ { \ .name = "title", \ .long_name = TRS("Title"), \ .type = BG_PARAMETER_STRING, \ } #define PARAM_ALBUM \ { \ .name = "album", \ .long_name = TRS("Album"), \ .type = BG_PARAMETER_STRING, \ } #define PARAM_TRACK \ { \ .name = "track", \ .long_name = TRS("Track"), \ .type = BG_PARAMETER_INT, \ } #define PARAM_GENRE \ { \ .name = "genre", \ .long_name = TRS("Genre"), \ .type = BG_PARAMETER_STRING, \ } #define PARAM_AUTHOR \ { \ .name = "author", \ .long_name = TRS("Author"), \ .type = BG_PARAMETER_STRING, \ } #define PARAM_COPYRIGHT \ { \ .name = "copyright", \ .long_name = TRS("Copyright"), \ .type = BG_PARAMETER_STRING, \ } #define PARAM_DATE \ { \ .name = "date", \ .long_name = TRS("Year"), \ .type = BG_PARAMETER_STRING, \ } #define PARAM_COMMENT \ { \ .name = "comment", \ .long_name = TRS("Comment"), \ .type = BG_PARAMETER_STRING, \ } static const bg_parameter_info_t parameters[] = { PARAM_ARTIST, PARAM_TITLE, PARAM_ALBUM, PARAM_TRACK, PARAM_GENRE, PARAM_AUTHOR, PARAM_ALBUMARTIST, PARAM_COPYRIGHT, PARAM_DATE, PARAM_COMMENT, { /* End of parameters */ } }; static const bg_parameter_info_t parameters_common[] = { PARAM_ARTIST, PARAM_ALBUM, PARAM_GENRE, PARAM_AUTHOR, PARAM_ALBUMARTIST, PARAM_COPYRIGHT, PARAM_DATE, PARAM_COMMENT, { /* End of parameters */ } }; #define SP_STR(s, gavl_name) \ if(!strcmp(ret[i].name, s)) \ ret[i].val_default.val_str = \ bg_strdup(ret[i].val_default.val_str, \ gavl_metadata_get(m, gavl_name)) #define SP_INT(s, gavl_name) \ if(!strcmp(ret[i].name, s)) \ { \ if(gavl_metadata_get_int(m, gavl_name, &val_i)) \ ret[i].val_default.val_i = val_i; \ } static bg_parameter_info_t * get_parameters(gavl_metadata_t * m, int common) { int i, year; int val_i; bg_parameter_info_t * ret; ret = bg_parameter_info_copy_array(common ? parameters_common : parameters); if(!m) return ret; i = 0; while(ret[i].name) { SP_STR("artist", GAVL_META_ARTIST); SP_STR("albumartist", GAVL_META_ALBUMARTIST); SP_STR("title" , GAVL_META_TITLE); SP_STR("album", GAVL_META_ALBUM); SP_INT("track", GAVL_META_TRACKNUMBER); if(!strcmp(ret[i].name, "date")) { year = bg_metadata_get_year(m); if(year) ret[i].val_default.val_str = bg_sprintf("%d", year); } SP_STR("genre", GAVL_META_GENRE); SP_STR("comment", GAVL_META_COMMENT); SP_STR("author", GAVL_META_AUTHOR); SP_STR("copyright", GAVL_META_COPYRIGHT); i++; } return ret; } bg_parameter_info_t * bg_metadata_get_parameters(gavl_metadata_t * m) { return get_parameters(m, 0); } bg_parameter_info_t * bg_metadata_get_parameters_common(gavl_metadata_t * m) { return get_parameters(m, 1); } #undef SP_STR #undef SP_INT #define SP_STR(s, gavl_name) \ if(!strcmp(name, s)) \ { \ gavl_metadata_set(m, gavl_name, val->val_str); \ return; \ } #define SP_INT(s, gavl_name) \ if(!strcmp(name, s)) \ { \ gavl_metadata_set_int(m, gavl_name, val->val_i); \ return; \ } void bg_metadata_set_parameter(void * data, const char * name, const bg_parameter_value_t * val) { gavl_metadata_t * m = (gavl_metadata_t*)data; if(!name) return; SP_STR("artist", GAVL_META_ARTIST); SP_STR("albumartist", GAVL_META_ALBUMARTIST); SP_STR("title", GAVL_META_TITLE); SP_STR("album", GAVL_META_ALBUM); SP_INT("track", GAVL_META_TRACKNUMBER); SP_STR("date", GAVL_META_YEAR); SP_STR("genre", GAVL_META_GENRE); SP_STR("comment", GAVL_META_COMMENT); SP_STR("author", GAVL_META_AUTHOR); SP_STR("copyright", GAVL_META_COPYRIGHT); } #undef SP_STR #undef SP_INT /* Tries to get a 4 digit year from an arbitrary formatted date string. Return 0 is this wasn't possible. */ static int check_year(const char * pos1) { if(isdigit(pos1[0]) && isdigit(pos1[1]) && isdigit(pos1[2]) && isdigit(pos1[3])) { return (int)(pos1[0] -'0') * 1000 + (int)(pos1[1] -'0') * 100 + (int)(pos1[2] -'0') * 10 + (int)(pos1[3] -'0'); } return 0; } int bg_metadata_get_year(const gavl_metadata_t * m) { int result; const char * pos1; pos1 = gavl_metadata_get(m, GAVL_META_YEAR); if(pos1) return atoi(pos1); pos1 = gavl_metadata_get(m, GAVL_META_DATE); if(!pos1) return 0; while(1) { /* Skip nondigits */ while(!isdigit(*pos1) && (*pos1 != '\0')) pos1++; if(*pos1 == '\0') return 0; /* Check if we have a 4 digit number */ result = check_year(pos1); if(result) return result; /* Skip digits */ while(isdigit(*pos1) && (*pos1 != '\0')) pos1++; if(*pos1 == '\0') return 0; } return 0; } /* * %p: Artist * %a: Album * %g: Genre * %t: Track name * %n: Track number (d = number of digits, 1-9) * %y: Year * %c: Comment */ char * bg_create_track_name(const gavl_metadata_t * metadata, const char * format) { int tag_i; char * buf; const char * end; const char * f; const char * tag; char * ret = NULL; char track_format[5]; f = format; while(*f != '\0') { end = f; while((*end != '%') && (*end != '\0')) end++; if(end != f) ret = bg_strncat(ret, f, end); if(*end == '%') { end++; /* %p: Artist */ if(*end == 'p') { end++; tag = gavl_metadata_get(metadata, GAVL_META_ARTIST); if(tag) ret = bg_strcat(ret, tag); else goto fail; } /* %a: Album */ else if(*end == 'a') { end++; tag = gavl_metadata_get(metadata, GAVL_META_ALBUM); if(tag) ret = bg_strcat(ret, tag); else goto fail; } /* %g: Genre */ else if(*end == 'g') { end++; tag = gavl_metadata_get(metadata, GAVL_META_GENRE); if(tag) ret = bg_strcat(ret, tag); else goto fail; } /* %t: Track name */ else if(*end == 't') { end++; tag = gavl_metadata_get(metadata, GAVL_META_TITLE); if(tag) ret = bg_strcat(ret, tag); else goto fail; } /* %c: Comment */ else if(*end == 'c') { end++; tag = gavl_metadata_get(metadata, GAVL_META_COMMENT); if(tag) ret = bg_strcat(ret, tag); else goto fail; } /* %y: Year */ else if(*end == 'y') { end++; tag_i = bg_metadata_get_year(metadata); if(tag_i > 0) { buf = bg_sprintf("%d", tag_i); ret = bg_strcat(ret, buf); free(buf); } else goto fail; } /* %n: Track number (d = number of digits, 1-9) */ else if(isdigit(*end) && end[1] == 'n') { if(gavl_metadata_get_int(metadata, GAVL_META_TRACKNUMBER, &tag_i)) { track_format[0] = '%'; track_format[1] = '0'; track_format[2] = *end; track_format[3] = 'd'; track_format[4] = '\0'; buf = bg_sprintf(track_format, tag_i); ret = bg_strcat(ret, buf); free(buf); end+=2; } else goto fail; } else { ret = bg_strcat(ret, "%"); end++; } f = end; } } return ret; fail: if(ret) free(ret); return NULL; } #define META_STRCAT() ret = bg_strcat(ret, tmp); free(tmp) char * bg_metadata_to_string(const gavl_metadata_t * m, int use_tabs) { int i; char * ret = NULL; char * tmp; char * sep; if(use_tabs) sep = ":\t "; else sep = ": "; for(i = 0; i < m->num_tags; i++) { tmp = bg_sprintf(TR("%s%s%s\n"), m->tags[i].key, sep, m->tags[i].val); META_STRCAT(); } /* Remove trailing '\n' */ if(ret) ret[strlen(ret) - 1] = '\0'; return ret; } gmerlin-1.2.0~dfsg/lib/bgxml.c0000644000175000017500000000455611764363410016133 0ustar alessioalessio/***************************************************************** * gmerlin - a general purpose multimedia framework and applications * * Copyright (c) 2001 - 2011 Members of the Gmerlin project * gmerlin-general@lists.sourceforge.net * http://gmerlin.sourceforge.net * * 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 of the License, 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 this program. If not, see . * *****************************************************************/ #include #include #include #include #include #include #include #include #include #define BLOCK_SIZE 2048 #include #define LOG_DOMAIN "xmlutils" int bg_xml_write_callback(void * context, const char * buffer, int len) { bg_xml_output_mem_t * o = (bg_xml_output_mem_t*)context; if(o->bytes_allocated - o->bytes_written < len) { o->bytes_allocated += BLOCK_SIZE; while(o->bytes_allocated < o->bytes_written + len) o->bytes_allocated += BLOCK_SIZE; o->buffer = realloc(o->buffer, o->bytes_allocated); } memcpy(&o->buffer[o->bytes_written], buffer, len); o->bytes_written += len; return len; } int bg_xml_close_callback(void * context) { bg_xml_output_mem_t * o = (bg_xml_output_mem_t*)context; if(o->bytes_allocated == o->bytes_written) { o->bytes_allocated++; o->buffer = realloc(o->buffer, o->bytes_allocated); } o->buffer[o->bytes_written] = '\0'; return 0; } xmlDocPtr bg_xml_parse_file(const char * filename) { struct stat st; if(stat(filename, &st)) { bg_log(BG_LOG_ERROR, LOG_DOMAIN, "Cannot stat %s: %s", filename, strerror(errno)); return NULL; } /* Return silently */ if(!st.st_size) return NULL; return xmlParseFile(filename); } gmerlin-1.2.0~dfsg/lib/recorder.c0000644000175000017500000004554511764363410016632 0ustar alessioalessio/***************************************************************** * gmerlin - a general purpose multimedia framework and applications * * Copyright (c) 2001 - 2011 Members of the Gmerlin project * gmerlin-general@lists.sourceforge.net * http://gmerlin.sourceforge.net * * 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 of the License, 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 this program. If not, see . * *****************************************************************/ #include #include #include #include #include #include #include #include #include #include #include #define LOG_DOMAIN "recorder" const uint32_t bg_recorder_stream_mask = BG_STREAM_AUDIO | BG_STREAM_VIDEO; const uint32_t bg_recorder_plugin_mask = BG_PLUGIN_FILE | BG_PLUGIN_BROADCAST; static void metadata_changed_callback(void * priv, const char * name, const gavl_metadata_t * m) { bg_recorder_t * rec = priv; if(rec->metadata_mode != BG_RECORDER_METADATA_INPUT) return; bg_log(BG_LOG_INFO, LOG_DOMAIN, "New track: %s", name); if(rec->enc && rec->encoding_finalized) { bg_encoder_update_metadata(rec->enc, name, m); } else { gavl_metadata_copy(&rec->updated_metadata, m); rec->updated_name = bg_strdup(rec->updated_name, name); } } bg_recorder_t * bg_recorder_create(bg_plugin_registry_t * plugin_reg) { bg_recorder_t * ret = calloc(1, sizeof(*ret)); bg_plugin_registry_scan_devices(plugin_reg, BG_PLUGIN_RECORDER_AUDIO, BG_PLUGIN_RECORDER); bg_plugin_registry_scan_devices(plugin_reg, BG_PLUGIN_RECORDER_VIDEO, BG_PLUGIN_RECORDER); ret->plugin_reg = plugin_reg; ret->tc = bg_player_thread_common_create(); bg_recorder_create_audio(ret); bg_recorder_create_video(ret); ret->th[0] = ret->as.th; ret->th[1] = ret->vs.th; ret->msg_queues = bg_msg_queue_list_create(); pthread_mutex_init(&ret->time_mutex, NULL); pthread_mutex_init(&ret->snapshot_mutex, NULL); ret->recorder_cb.metadata_changed = metadata_changed_callback; ret->recorder_cb.data = ret; return ret; } void bg_recorder_destroy(bg_recorder_t * rec) { if(rec->flags & FLAG_RUNNING) bg_recorder_stop(rec); bg_recorder_destroy_audio(rec); bg_recorder_destroy_video(rec); bg_player_thread_common_destroy(rec->tc); free(rec->display_string); bg_msg_queue_list_destroy(rec->msg_queues); if(rec->encoder_parameters) bg_parameter_info_destroy_array(rec->encoder_parameters); if(rec->output_directory) free(rec->output_directory); if(rec->output_filename_mask) free(rec->output_filename_mask); if(rec->snapshot_directory) free(rec->snapshot_directory); if(rec->snapshot_filename_mask) free(rec->snapshot_filename_mask); gavl_metadata_free(&rec->m); gavl_metadata_free(&rec->updated_metadata); if(rec->updated_name) free(rec->updated_name); pthread_mutex_destroy(&rec->time_mutex); pthread_mutex_destroy(&rec->snapshot_mutex); free(rec); } void bg_recorder_add_message_queue(bg_recorder_t * rec, bg_msg_queue_t * q) { bg_msg_queue_list_add(rec->msg_queues, q); } void bg_recorder_remove_message_queue(bg_recorder_t * rec, bg_msg_queue_t * q) { bg_msg_queue_list_remove(rec->msg_queues, q); } static void init_encoding(bg_recorder_t * rec) { struct tm brokentime; time_t t; char time_string[512]; char * filename_base; const gavl_metadata_t * m; time(&t); localtime_r(&t, &brokentime); strftime(time_string, 511, rec->output_filename_mask, &brokentime); filename_base = bg_sprintf("%s/%s", rec->output_directory, time_string); rec->as.flags |= STREAM_ENCODE; rec->vs.flags |= STREAM_ENCODE; rec->enc = bg_encoder_create(rec->plugin_reg, rec->encoder_section, NULL, bg_recorder_stream_mask, bg_recorder_plugin_mask); if(rec->metadata_mode != BG_RECORDER_METADATA_STATIC) m = &rec->updated_metadata; else m = &rec->m; bg_encoder_open(rec->enc, filename_base, m, NULL); free(filename_base); } static int finalize_encoding(bg_recorder_t * rec) { if(!bg_encoder_start(rec->enc)) return 0; if(rec->as.flags & STREAM_ACTIVE) bg_recorder_audio_finalize_encode(rec); if(rec->vs.flags & STREAM_ACTIVE) bg_recorder_video_finalize_encode(rec); bg_encoder_update_metadata(rec->enc, rec->updated_name, &rec->updated_metadata); rec->encoding_finalized = 1; return 1; } int bg_recorder_run(bg_recorder_t * rec) { int do_audio = 0; int do_video = 0; rec->encoding_finalized = 0; if(rec->flags & FLAG_DO_RECORD) { init_encoding(rec); rec->recording_time = 0; rec->last_recording_time = - 2 * GAVL_TIME_SCALE; } else { rec->as.flags &= ~STREAM_ENCODE; rec->vs.flags &= ~STREAM_ENCODE; } if(rec->as.flags & STREAM_ACTIVE) { if(!bg_recorder_audio_init(rec)) rec->as.flags &= ~STREAM_ACTIVE; else do_audio = 1; } bg_recorder_audio_set_eof(&rec->as, !do_audio); if(rec->vs.flags & STREAM_ACTIVE) { if(!bg_recorder_video_init(rec)) rec->vs.flags &= ~STREAM_ACTIVE; else do_video = 1; } bg_recorder_video_set_eof(&rec->vs, !do_video); if(rec->flags & FLAG_DO_RECORD) { if(!finalize_encoding(rec)) { if(rec->as.flags & STREAM_ACTIVE) bg_recorder_audio_cleanup(rec); if(rec->vs.flags & STREAM_ACTIVE) bg_recorder_video_cleanup(rec); bg_recorder_msg_running(rec, 0, 0); return 0; } } if(rec->as.flags & STREAM_ACTIVE) bg_player_thread_set_func(rec->as.th, bg_recorder_audio_thread, rec); else bg_player_thread_set_func(rec->as.th, NULL, NULL); if(rec->vs.flags & STREAM_ACTIVE) bg_player_thread_set_func(rec->vs.th, bg_recorder_video_thread, rec); else bg_player_thread_set_func(rec->vs.th, NULL, NULL); if(rec->flags & FLAG_DO_RECORD) rec->flags &= FLAG_RECORDING; bg_player_threads_init(rec->th, NUM_THREADS); bg_player_threads_start(rec->th, NUM_THREADS); rec->flags |= FLAG_RUNNING; bg_recorder_msg_running(rec, do_audio, do_video); return 1; } /* Encoders */ const bg_parameter_info_t * bg_recorder_get_encoder_parameters(bg_recorder_t * rec) { if(!rec->encoder_parameters) rec->encoder_parameters = bg_plugin_registry_create_encoder_parameters(rec->plugin_reg, bg_recorder_stream_mask, bg_recorder_plugin_mask); return rec->encoder_parameters; } void bg_recorder_set_encoder_section(bg_recorder_t * rec, bg_cfg_section_t * s) { rec->encoder_section = s; } void bg_recorder_stop(bg_recorder_t * rec) { if(!(rec->flags & FLAG_RUNNING)) return; bg_player_threads_join(rec->th, NUM_THREADS); bg_recorder_audio_cleanup(rec); bg_recorder_video_cleanup(rec); if(rec->enc) { bg_encoder_destroy(rec->enc, 0); rec->enc = NULL; bg_recorder_msg_time(rec, GAVL_TIME_UNDEFINED); } rec->flags &= ~(FLAG_RECORDING | FLAG_RUNNING); } void bg_recorder_record(bg_recorder_t * rec, int record) { int was_running = !!(rec->flags & FLAG_RUNNING); if(was_running) bg_recorder_stop(rec); if(record) rec->flags |= FLAG_DO_RECORD; else rec->flags &= ~FLAG_DO_RECORD; if(was_running) bg_recorder_run(rec); } void bg_recorder_set_display_string(bg_recorder_t * rec, const char * str) { rec->display_string = bg_strdup(rec->display_string, str); } /* Message stuff */ static void msg_framerate(bg_msg_t * msg, const void * data) { const float * f = data; bg_msg_set_id(msg, BG_RECORDER_MSG_FRAMERATE); bg_msg_set_arg_float(msg, 0, *f); } void bg_recorder_msg_framerate(bg_recorder_t * rec, float framerate) { bg_msg_queue_list_send(rec->msg_queues, msg_framerate, &framerate); } typedef struct { double * l; int samples; } audiolevel_t; static void msg_audiolevel(bg_msg_t * msg, const void * data) { const audiolevel_t * d = data; bg_msg_set_id(msg, BG_RECORDER_MSG_AUDIOLEVEL); bg_msg_set_arg_float(msg, 0, d->l[0]); bg_msg_set_arg_float(msg, 1, d->l[1]); bg_msg_set_arg_int(msg, 2, d->samples); } void bg_recorder_msg_audiolevel(bg_recorder_t * rec, double * level, int samples) { audiolevel_t d; d.l = level; d.samples = samples; bg_msg_queue_list_send(rec->msg_queues, msg_audiolevel, &d); } static void msg_time(bg_msg_t * msg, const void * data) { const gavl_time_t * t = data; bg_msg_set_id(msg, BG_RECORDER_MSG_TIME); bg_msg_set_arg_time(msg, 0, *t); } void bg_recorder_msg_time(bg_recorder_t * rec, gavl_time_t t) { bg_msg_queue_list_send(rec->msg_queues, msg_time, &t); } typedef struct { int do_audio; int do_video; } running_t; static void msg_running(bg_msg_t * msg, const void * data) { const running_t * r = data; bg_msg_set_id(msg, BG_RECORDER_MSG_RUNNING); bg_msg_set_arg_int(msg, 0, r->do_audio); bg_msg_set_arg_int(msg, 1, r->do_video); } void bg_recorder_msg_running(bg_recorder_t * rec, int do_audio, int do_video) { running_t r; r.do_audio = do_audio; r.do_video = do_video; bg_msg_queue_list_send(rec->msg_queues, msg_running, &r); } typedef struct { int x; int y; int button; int mask; } button_t; static void msg_button_press(bg_msg_t * msg, const void * data) { const button_t * b = data; bg_msg_set_id(msg, BG_RECORDER_MSG_BUTTON_PRESS); bg_msg_set_arg_int(msg, 0, b->x); bg_msg_set_arg_int(msg, 1, b->y); bg_msg_set_arg_int(msg, 2, b->button); bg_msg_set_arg_int(msg, 3, b->mask); } void bg_recorder_msg_button_press(bg_recorder_t * rec, int x, int y, int button, int mask) { button_t b; b.x = x; b.y = y; b.button = button; b.mask = mask; bg_msg_queue_list_send(rec->msg_queues, msg_button_press, &b); } static void msg_button_release(bg_msg_t * msg, const void * data) { const button_t * b = data; bg_msg_set_id(msg, BG_RECORDER_MSG_BUTTON_RELEASE); bg_msg_set_arg_int(msg, 0, b->x); bg_msg_set_arg_int(msg, 1, b->y); bg_msg_set_arg_int(msg, 2, b->button); bg_msg_set_arg_int(msg, 3, b->mask); } void bg_recorder_msg_button_release(bg_recorder_t * rec, int x, int y, int button, int mask) { button_t b; b.x = x; b.y = y; b.button = button; b.mask = mask; bg_msg_queue_list_send(rec->msg_queues, msg_button_release, &b); } static void msg_motion(bg_msg_t * msg, const void * data) { const button_t * b = data; bg_msg_set_id(msg, BG_RECORDER_MSG_MOTION); bg_msg_set_arg_int(msg, 0, b->x); bg_msg_set_arg_int(msg, 1, b->y); bg_msg_set_arg_int(msg, 3, b->mask); } void bg_recorder_msg_motion(bg_recorder_t * rec, int x, int y, int mask) { button_t b; b.x = x; b.y = y; b.mask = mask; bg_msg_queue_list_send(rec->msg_queues, msg_motion, &b); } /* Parameter stuff */ static const bg_parameter_info_t output_parameters[] = { { .name = "output_directory", .long_name = TRS("Output directory"), .type = BG_PARAMETER_DIRECTORY, .val_default = { .val_str = "." }, }, { .name = "output_filename_mask", .long_name = TRS("Output filename mask"), .type = BG_PARAMETER_STRING, .val_default = { .val_str = "%Y-%m-%d-%H-%M-%S" }, .help_string = TRS("Extension is appended by the plugin\n\ For the date and time formatting, consult the documentation\n\ of the strftime(3) function"), }, { .name = "snapshot_directory", .long_name = TRS("Snapshot directory"), .type = BG_PARAMETER_DIRECTORY, .val_default = { .val_str = "." }, }, { .name = "snapshot_filename_mask", .long_name = TRS("Snapshot filename mask"), .type = BG_PARAMETER_STRING, .val_default = { .val_str = "shot_%5n" }, .help_string = TRS("Extension is appended by the plugin\n\ %t Inserts time\n\ %d Inserts date\n\ %n Inserts Frame number with digits") }, { /* End */ } }; const bg_parameter_info_t * bg_recorder_get_output_parameters(bg_recorder_t * rec) { return output_parameters; } void bg_recorder_set_output_parameter(void * data, const char * name, const bg_parameter_value_t * val) { bg_recorder_t * rec; if(!name) return; rec = data; if(!strcmp(name, "output_directory")) rec->output_directory = bg_strdup(rec->output_directory, val->val_str); else if(!strcmp(name, "output_filename_mask")) rec->output_filename_mask = bg_strdup(rec->output_filename_mask, val->val_str); else if(!strcmp(name, "snapshot_directory")) rec->snapshot_directory = bg_strdup(rec->snapshot_directory, val->val_str); else if(!strcmp(name, "snapshot_filename_mask")) rec->snapshot_filename_mask = bg_strdup(rec->snapshot_filename_mask, val->val_str); } static const bg_parameter_info_t common_metadata_parameters[] = { { .name = "metadata_mode", .long_name = TRS("Metadata mode"), .type = BG_PARAMETER_STRINGLIST, .val_default = { .val_str = "static" }, .multi_names = (char const *[]){ "static", "input", "player", NULL }, .multi_labels = (char const *[]){ TRS("Static"), TRS("From input"), TRS("From player"), NULL }, }, { /* End of parameters */ }, }; const bg_parameter_info_t * bg_recorder_get_metadata_parameters(bg_recorder_t * rec) { if(!rec->metadata_parameters) { bg_parameter_info_t * p; const bg_parameter_info_t * params[3]; p = bg_metadata_get_parameters(&rec->m); params[0] = common_metadata_parameters; params[1] = p; params[2] = NULL; rec->metadata_parameters = bg_parameter_info_concat_arrays(params); bg_parameter_info_destroy_array(p); } return rec->metadata_parameters; } void bg_recorder_set_metadata_parameter(void * data, const char * name, const bg_parameter_value_t * val) { bg_recorder_t * rec = data; if(name) { if(!strcmp(name, "metadata_mode")) { if(!strcmp(val->val_str, "static")) rec->metadata_mode = BG_RECORDER_METADATA_STATIC; else if(!strcmp(val->val_str, "input")) rec->metadata_mode = BG_RECORDER_METADATA_INPUT; else if(!strcmp(val->val_str, "player")) rec->metadata_mode = BG_RECORDER_METADATA_PLAYER; return; } } bg_metadata_set_parameter(&rec->m, name, val); } void bg_recorder_update_time(bg_recorder_t * rec, gavl_time_t t) { pthread_mutex_lock(&rec->time_mutex); if(rec->recording_time < t) rec->recording_time = t; if(rec->recording_time - rec->last_recording_time > GAVL_TIME_SCALE) { bg_recorder_msg_time(rec, rec->recording_time); rec->last_recording_time = rec->recording_time; } pthread_mutex_unlock(&rec->time_mutex); } void bg_recorder_interrupt(bg_recorder_t * rec) { if(rec->flags & FLAG_RUNNING) { bg_recorder_stop(rec); rec->flags |= FLAG_INTERRUPTED; } } void bg_recorder_resume(bg_recorder_t * rec) { if(rec->flags & FLAG_INTERRUPTED) { rec->flags &= ~FLAG_INTERRUPTED; bg_recorder_run(rec); } } void bg_recorder_snapshot(bg_recorder_t * rec) { pthread_mutex_lock(&rec->snapshot_mutex); rec->snapshot = 1; pthread_mutex_unlock(&rec->snapshot_mutex); // fprintf(stderr, "Snapshot\n"); } static const char * remote_command = "gmerlin_remote -get-name -get-metadata 2>> /dev/null"; #define CHECK_STRING(key, val) \ len = strlen(key); \ if(!strncmp(key, line, len)) \ val = bg_strdup(val, line + len) static void update_metadata(bg_recorder_t * rec) { bg_subprocess_t * sp; char * line = NULL; int line_alloc = 0; char * key; char * val; char * pos; gavl_metadata_t m; char * name = NULL; gavl_metadata_init(&m); sp = bg_subprocess_create(remote_command, 0, 1, 0); // fprintf(stderr, "Update metadata\n"); while(1) { if(!bg_subprocess_read_line(sp->stdout_fd, &line, &line_alloc, -1)) break; // fprintf(stderr, "Got remote line: %s\n", line); pos = strchr(line, ':'); if(!pos) continue; key = bg_strndup(NULL, line, pos); pos++; while(isspace(*pos)) pos++; val = pos; gavl_metadata_set(&m, key, val); free(key); } bg_subprocess_close(sp); if(!gavl_metadata_equal(&m, &rec->updated_metadata) || (!rec->updated_name && name) || (name && rec->updated_name && strcmp(name, rec->updated_name))) { /* Metadata changed */ if(rec->enc) bg_encoder_update_metadata(rec->enc, name, &m); if(rec->updated_name) free(rec->updated_name); rec->updated_name = name; gavl_metadata_free(&rec->updated_metadata); memcpy(&rec->updated_metadata, &m, sizeof(m)); if(name) bg_log(BG_LOG_INFO, LOG_DOMAIN, "New track %s", name); } else { free(name); gavl_metadata_free(&m); } } int bg_recorder_ping(bg_recorder_t * rec) { // fprintf(stderr, "bg_recorder_ping\n"); if(rec->metadata_mode == BG_RECORDER_METADATA_PLAYER) { update_metadata(rec); } if(bg_recorder_video_get_eof(&rec->vs) && bg_recorder_audio_get_eof(&rec->as)) return 0; return 1; } gmerlin-1.2.0~dfsg/lib/album_xml.c0000644000175000017500000004305011764363410016772 0ustar alessioalessio/***************************************************************** * gmerlin - a general purpose multimedia framework and applications * * Copyright (c) 2001 - 2011 Members of the Gmerlin project * gmerlin-general@lists.sourceforge.net * http://gmerlin.sourceforge.net * * 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 of the License, 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 this program. If not, see . * *****************************************************************/ #include #include /* Needed for chmod and mode_t */ #include #include #include #include #include #include #include #include #define LOG_DOMAIN "album" /* Load an entry from a node */ static bg_album_entry_t * load_entry(bg_album_t * album, xmlDocPtr xml_doc, xmlNodePtr node, int * current) { bg_album_entry_t * ret; char * tmp_string; ret = bg_album_entry_create(); ret->total_tracks = 1; if(current) *current = 0; if((tmp_string = BG_XML_GET_PROP(node, "current"))) { if(current) *current = 1; xmlFree(tmp_string); } if((tmp_string = BG_XML_GET_PROP(node, "error"))) { if(atoi(tmp_string)) ret->flags |= BG_ALBUM_ENTRY_ERROR; xmlFree(tmp_string); } if((tmp_string = BG_XML_GET_PROP(node, "edl"))) { if(atoi(tmp_string)) ret->flags |= BG_ALBUM_ENTRY_EDL; xmlFree(tmp_string); } if((tmp_string = BG_XML_GET_PROP(node, "save_auth"))) { if(atoi(tmp_string)) ret->flags |= BG_ALBUM_ENTRY_SAVE_AUTH; xmlFree(tmp_string); } node = node->children; while(node) { if(!node->name) { node = node->next; continue; } tmp_string = (char*)xmlNodeListGetString(xml_doc, node->children, 1); if(!BG_XML_STRCMP(node->name, "NAME")) { ret->name = bg_strdup(ret->name, tmp_string); } else if(!BG_XML_STRCMP(node->name, "LOCATION")) { ret->location = (void*)bg_uri_to_string(tmp_string, -1); } else if(!BG_XML_STRCMP(node->name, "USER")) { ret->username = bg_strdup(ret->username, tmp_string); } else if(!BG_XML_STRCMP(node->name, "PASS")) { ret->password = bg_descramble_string(tmp_string); } else if(!BG_XML_STRCMP(node->name, "PLUGIN")) { ret->plugin = (void*)bg_strdup(ret->plugin, tmp_string); } else if(!BG_XML_STRCMP(node->name, "DURATION")) { sscanf(tmp_string, "%" PRId64, &ret->duration); } else if(!BG_XML_STRCMP(node->name, "ASTREAMS")) { sscanf(tmp_string, "%d", &ret->num_audio_streams); } else if(!BG_XML_STRCMP(node->name, "STSTREAMS")) { sscanf(tmp_string, "%d", &ret->num_still_streams); } else if(!BG_XML_STRCMP(node->name, "VSTREAMS")) { sscanf(tmp_string, "%d", &ret->num_video_streams); } else if(!BG_XML_STRCMP(node->name, "INDEX")) { sscanf(tmp_string, "%d", &ret->index); } else if(!BG_XML_STRCMP(node->name, "TOTAL_TRACKS")) { sscanf(tmp_string, "%d", &ret->total_tracks); } else if(!BG_XML_STRCMP(node->name, "MTIME")) { int64_t mtime; sscanf(tmp_string, "%"PRId64"", &mtime); ret->mtime = mtime; } if(tmp_string) xmlFree(tmp_string); node = node->next; } return ret; } static bg_album_entry_t * xml_2_album(bg_album_t * album, xmlDocPtr xml_doc, bg_album_entry_t ** last, bg_album_entry_t ** current, int load_globals) { xmlNodePtr node; int is_current; bg_album_entry_t * ret = NULL; bg_album_entry_t * end_ptr = NULL; bg_album_entry_t * new_entry; if(current) *current = NULL; node = xml_doc->children; if(BG_XML_STRCMP(node->name, "ALBUM")) { xmlFreeDoc(xml_doc); return NULL; } node = node->children; while(node) { if(!node->name) { node = node->next; continue; } else if(!BG_XML_STRCMP(node->name, "CFG_SECTION") && load_globals) { bg_cfg_xml_2_section(xml_doc, node, album->cfg_section); } else if(!BG_XML_STRCMP(node->name, "ENTRY")) { new_entry = load_entry(album, xml_doc, node, &is_current); if(new_entry) { if(!ret) { ret = new_entry; end_ptr = ret; } else { end_ptr->next = new_entry; end_ptr = end_ptr->next; } if(is_current && current) { *current = new_entry; } } } node = node->next; } if(last) *last = end_ptr; return ret; } static bg_album_entry_t * load_album_file(bg_album_t * album, const char * filename, bg_album_entry_t ** last, bg_album_entry_t ** current, int load_globals) { bg_album_entry_t * ret; xmlDocPtr xml_doc; xml_doc = bg_xml_parse_file(filename); if(!xml_doc) { bg_log(BG_LOG_ERROR, LOG_DOMAIN, "Couldn't open album file %s", filename); return NULL; } ret = xml_2_album(album, xml_doc, last, current, load_globals); xmlFreeDoc(xml_doc); return ret; } static bg_album_entry_t * load_album_xml(bg_album_t * album, const char * string, bg_album_entry_t ** last, bg_album_entry_t ** current, int load_globals) { bg_album_entry_t * ret; xmlDocPtr xml_doc; xml_doc = xmlParseMemory(string, strlen(string)); ret = xml_2_album(album, xml_doc, last, current, load_globals); xmlFreeDoc(xml_doc); return ret; } bg_album_entry_t * bg_album_entries_new_from_xml(const char * xml_string) { bg_album_entry_t * ret; xmlDocPtr xml_doc; xml_doc = xmlParseMemory(xml_string, strlen(xml_string)); ret = xml_2_album(NULL, xml_doc, NULL, NULL, 0); xmlFreeDoc(xml_doc); return ret; } /* Inserts an xml-string */ void bg_album_insert_xml_after(bg_album_t * a, const char * xml_string, bg_album_entry_t * before) { bg_album_entry_t * new_entries; bg_album_entry_t * current_entry; new_entries = load_album_xml(a, xml_string, NULL, ¤t_entry, 0); bg_album_insert_entries_after(a, new_entries, before); if(current_entry) bg_album_set_current(a, current_entry); // bg_album_changed(a); return; } void bg_album_insert_xml_before(bg_album_t * a, const char * xml_string, bg_album_entry_t * after) { bg_album_entry_t * new_entries; bg_album_entry_t * current_entry; new_entries = load_album_xml(a, xml_string, NULL, ¤t_entry, 0); bg_album_insert_entries_before(a, new_entries, after); if(current_entry) bg_album_set_current(a, current_entry); // bg_album_changed(a); return; } static bg_album_entry_t * load_albums(bg_album_t * album, char ** filenames, bg_album_entry_t ** last, bg_album_entry_t ** current) { int i = 0; bg_album_entry_t * ret; bg_album_entry_t * end = NULL; bg_album_entry_t * tmp_end; ret = NULL; while(filenames[i]) { if(!ret) { ret = load_album_file(album, filenames[i], &tmp_end, current, 0); end = tmp_end; } else { end->next = load_album_file(album, filenames[i], &tmp_end, current, 0); end = tmp_end; } i++; } if(last) *last = end; return ret; } void bg_album_insert_albums_before(bg_album_t * a, char ** locations, bg_album_entry_t * after) { bg_album_entry_t * new_entries; new_entries = load_albums(a, locations, NULL, NULL); bg_album_insert_entries_before(a, new_entries, after); bg_album_changed(a); } void bg_album_insert_albums_after(bg_album_t * a, char ** locations, bg_album_entry_t * before) { bg_album_entry_t * new_entries; new_entries = load_albums(a, locations, NULL, NULL); bg_album_insert_entries_after(a, new_entries, before); bg_album_changed(a); } void bg_album_load(bg_album_t * a, const char * filename) { bg_album_entry_t * current; current = NULL; a->entries = load_album_file(a, filename, NULL, ¤t, 1); if(current) { bg_album_set_current(a, current); } } /* Save album */ static void save_entry(bg_album_t * a, bg_album_entry_t * entry, xmlNodePtr parent, int preserve_current) { xmlNodePtr xml_entry; xmlNodePtr node; char * c_tmp; xml_entry = xmlNewTextChild(parent, NULL, (xmlChar*)"ENTRY", NULL); if(a && bg_album_entry_is_current(a, entry) && preserve_current) { BG_XML_SET_PROP(xml_entry, "current", "1"); } if(entry->flags & BG_ALBUM_ENTRY_ERROR) { BG_XML_SET_PROP(xml_entry, "error", "1"); } if(entry->flags & BG_ALBUM_ENTRY_SAVE_AUTH) { BG_XML_SET_PROP(xml_entry, "save_auth", "1"); } if(entry->flags & BG_ALBUM_ENTRY_EDL) { BG_XML_SET_PROP(xml_entry, "edl", "1"); } xmlAddChild(xml_entry, BG_XML_NEW_TEXT("\n")); xmlAddChild(parent, BG_XML_NEW_TEXT("\n")); /* Name */ node = xmlNewTextChild(xml_entry, NULL, (xmlChar*)"NAME", NULL); xmlAddChild(node, BG_XML_NEW_TEXT(entry->name)); xmlAddChild(xml_entry, BG_XML_NEW_TEXT("\n")); /* Location */ if(entry->location) { node = xmlNewTextChild(xml_entry, NULL, (xmlChar*)"LOCATION", NULL); c_tmp = bg_string_to_uri((char*)(entry->location), -1); xmlAddChild(node, BG_XML_NEW_TEXT(c_tmp)); free(c_tmp); xmlAddChild(xml_entry, BG_XML_NEW_TEXT("\n")); } /* Mtime */ if(entry->mtime) { node = xmlNewTextChild(xml_entry, NULL, (xmlChar*)"MTIME", NULL); c_tmp = bg_sprintf("%"PRId64, (int64_t)(entry->mtime)); xmlAddChild(node, BG_XML_NEW_TEXT(c_tmp)); free(c_tmp); xmlAddChild(xml_entry, BG_XML_NEW_TEXT("\n")); } /* Authentication */ if((entry->flags & BG_ALBUM_ENTRY_SAVE_AUTH) && entry->username && entry->password) { /* Username */ node = xmlNewTextChild(xml_entry, NULL, (xmlChar*)"USER", NULL); xmlAddChild(node, BG_XML_NEW_TEXT(entry->username)); xmlAddChild(xml_entry, BG_XML_NEW_TEXT("\n")); /* Password */ c_tmp = bg_scramble_string(entry->password); node = xmlNewTextChild(xml_entry, NULL, (xmlChar*)"PASS", NULL); xmlAddChild(node, BG_XML_NEW_TEXT(c_tmp)); xmlAddChild(xml_entry, BG_XML_NEW_TEXT("\n")); free(c_tmp); } /* Plugin */ if(entry->plugin) { node = xmlNewTextChild(xml_entry, NULL, (xmlChar*)"PLUGIN", NULL); xmlAddChild(node, BG_XML_NEW_TEXT(entry->plugin)); xmlAddChild(xml_entry, BG_XML_NEW_TEXT("\n")); } /* Audio streams */ if(entry->num_audio_streams) { c_tmp = bg_sprintf("%d", entry->num_audio_streams); node = xmlNewTextChild(xml_entry, NULL, (xmlChar*)"ASTREAMS", NULL); xmlAddChild(node, BG_XML_NEW_TEXT(c_tmp)); xmlAddChild(xml_entry, BG_XML_NEW_TEXT("\n")); free(c_tmp); } /* Still streams */ if(entry->num_still_streams) { c_tmp = bg_sprintf("%d", entry->num_still_streams); node = xmlNewTextChild(xml_entry, NULL, (xmlChar*)"STSTREAMS", NULL); xmlAddChild(node, BG_XML_NEW_TEXT(c_tmp)); xmlAddChild(xml_entry, BG_XML_NEW_TEXT("\n")); free(c_tmp); } /* Video streams */ if(entry->num_video_streams) { c_tmp = bg_sprintf("%d", entry->num_video_streams); node = xmlNewTextChild(xml_entry, NULL, (xmlChar*)"VSTREAMS", NULL); xmlAddChild(node, BG_XML_NEW_TEXT(c_tmp)); free(c_tmp); xmlAddChild(xml_entry, BG_XML_NEW_TEXT("\n")); } /* Index */ if(entry->total_tracks > 1) { c_tmp = bg_sprintf("%d", entry->index); node = xmlNewTextChild(xml_entry, NULL, (xmlChar*)"INDEX", NULL); xmlAddChild(node, BG_XML_NEW_TEXT(c_tmp)); free(c_tmp); xmlAddChild(xml_entry, BG_XML_NEW_TEXT("\n")); c_tmp = bg_sprintf("%d", entry->total_tracks); node = xmlNewTextChild(xml_entry, NULL, (xmlChar*)"TOTAL_TRACKS", NULL); xmlAddChild(node, BG_XML_NEW_TEXT(c_tmp)); free(c_tmp); xmlAddChild(xml_entry, BG_XML_NEW_TEXT("\n")); } /* Duration */ c_tmp = bg_sprintf("%" PRId64, entry->duration); node = xmlNewTextChild(xml_entry, NULL, (xmlChar*)"DURATION", NULL); xmlAddChild(node, BG_XML_NEW_TEXT(c_tmp)); free(c_tmp); xmlAddChild(xml_entry, BG_XML_NEW_TEXT("\n")); } static xmlDocPtr album_2_xml(bg_album_t * a) { bg_album_entry_t * entry; xmlDocPtr xml_doc; xmlNodePtr xml_album; xmlNodePtr node; /* First step: Build the xml tree */ xml_doc = xmlNewDoc((xmlChar*)"1.0"); xml_album = xmlNewDocRawNode(xml_doc, NULL, (xmlChar*)"ALBUM", NULL); xmlDocSetRootElement(xml_doc, xml_album); xmlAddChild(xml_album, BG_XML_NEW_TEXT("\n")); /* Save config data */ if(a->cfg_section) { node = xmlNewTextChild(xml_album, NULL, (xmlChar*)"CFG_SECTION", NULL); bg_cfg_section_2_xml(a->cfg_section, node); xmlAddChild(xml_album, BG_XML_NEW_TEXT("\n")); } entry = a->entries; while(entry) { save_entry(a, entry, xml_album, 1); entry = entry->next; } return xml_doc; } static xmlDocPtr entries_2_xml(bg_album_t * a, int preserve_current, int selected) { bg_album_entry_t * entry; xmlDocPtr xml_doc; xmlNodePtr xml_album; /* First step: Build the xml tree */ xml_doc = xmlNewDoc((xmlChar*)"1.0"); xml_album = xmlNewDocRawNode(xml_doc, NULL, (xmlChar*)"ALBUM", NULL); xmlDocSetRootElement(xml_doc, xml_album); xmlAddChild(xml_album, BG_XML_NEW_TEXT("\n")); entry = a->entries; while(entry) { if((entry->flags & BG_ALBUM_ENTRY_SELECTED) || !selected) save_entry(a, entry, xml_album, preserve_current); entry = entry->next; } return xml_doc; } /* Output routines for writing to memory */ #if 0 typedef struct output_mem_s { int bytes_written; int bytes_allocated; char * buffer; } output_mem_t; #define BLOCK_SIZE 2048 static int xml_write_callback(void * context, const char * buffer, int len) { output_mem_t * o = (output_mem_t*)context; if(o->bytes_allocated - o->bytes_written < len) { o->bytes_allocated += BLOCK_SIZE; while(o->bytes_allocated < o->bytes_written + len) o->bytes_allocated += BLOCK_SIZE; o->buffer = realloc(o->buffer, o->bytes_allocated); } memcpy(&o->buffer[o->bytes_written], buffer, len); o->bytes_written += len; return len; } static int xml_close_callback(void * context) { output_mem_t * o = (output_mem_t*)context; if(o->bytes_allocated == o->bytes_written) { o->bytes_allocated++; o->buffer = realloc(o->buffer, o->bytes_allocated); } o->buffer[o->bytes_written] = '\0'; return 0; } #endif char * bg_album_save_to_memory(bg_album_t * a) { xmlDocPtr xml_doc; bg_xml_output_mem_t ctx; xmlOutputBufferPtr b; memset(&ctx, 0, sizeof(ctx)); xml_doc = album_2_xml(a); b = xmlOutputBufferCreateIO (bg_xml_write_callback, bg_xml_close_callback, &ctx, NULL); xmlSaveFileTo(b, xml_doc, NULL); xmlFreeDoc(xml_doc); return ctx.buffer; } char * bg_album_save_selected_to_memory(bg_album_t * a, int preserve_current) { xmlDocPtr xml_doc; bg_xml_output_mem_t ctx; xmlOutputBufferPtr b; memset(&ctx, 0, sizeof(ctx)); xml_doc = entries_2_xml(a, preserve_current, 1); b = xmlOutputBufferCreateIO(bg_xml_write_callback, bg_xml_close_callback, &ctx, NULL); xmlSaveFileTo(b, xml_doc, NULL); xmlFreeDoc(xml_doc); return ctx.buffer; } static void set_permissions(const char * filename) { chmod(filename, S_IRUSR | S_IWUSR); } void bg_album_save(bg_album_t * a, const char * filename) { char * tmp_filename; xmlDocPtr xml_doc; if((a->type == BG_ALBUM_TYPE_REMOVABLE) || (a->type == BG_ALBUM_TYPE_PLUGIN)) return; xml_doc = album_2_xml(a); /* Get the filename */ if(filename) { xmlSaveFile(filename, xml_doc); set_permissions(filename); } else { if(!a->xml_file) { bg_album_set_default_location(a); } tmp_filename = bg_sprintf("%s/%s", a->com->directory, a->xml_file); xmlSaveFile(tmp_filename, xml_doc); set_permissions(tmp_filename); free(tmp_filename); } xmlFreeDoc(xml_doc); } gmerlin-1.2.0~dfsg/lib/cfg_section.c0000644000175000017500000010447111764363410017302 0ustar alessioalessio/***************************************************************** * gmerlin - a general purpose multimedia framework and applications * * Copyright (c) 2001 - 2011 Members of the Gmerlin project * gmerlin-general@lists.sourceforge.net * http://gmerlin.sourceforge.net * * 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 of the License, 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 this program. If not, see . * *****************************************************************/ #include #include #include #include #include #include #include #include bg_cfg_section_t * bg_cfg_section_create(const char * name) { bg_cfg_section_t * ret = calloc(1, sizeof(*ret)); ret->name = bg_strdup(ret->name, name); return ret; } bg_cfg_section_t * bg_cfg_section_find_subsection(bg_cfg_section_t * s, const char * name) { int i; bg_cfg_section_t * prev_section; bg_cfg_section_t * section; /* Try references */ for(i = 0; i < s->num_refs; i++) { if(!strcmp(s->refs[i]->name, name)) return s->refs[i]; } section = s->children; prev_section = NULL; while(section) { if(!strcmp(section->name, name)) return section; prev_section = section; section = section->next; } if(prev_section) { prev_section->next = bg_cfg_section_create(name); return prev_section->next; } else { s->children = bg_cfg_section_create(name); return s->children; } } bg_cfg_section_t * bg_cfg_section_find_subsection_by_index(bg_cfg_section_t * s, int index) { int i; bg_cfg_section_t * section; section = s->children; for(i = 0; i < index; i++) { if(!section) return NULL; section = section->next; } return section; } static char * make_unique_name(bg_cfg_section_t * section, const char * template) { int i = 0; char * ret; while(1) { ret = bg_sprintf(template, i); if(!bg_cfg_section_has_subsection(section, ret)) break; free(ret); i++; } return ret; } bg_cfg_section_t * bg_cfg_section_create_subsection_at_pos(bg_cfg_section_t * section, int pos) { int i; char * name; bg_cfg_section_t * before = NULL; bg_cfg_section_t * tmp; bg_cfg_section_t * ret; if(pos) { before = section->children; for(i = 0; i < pos - 1; i++) { if(!before) return before; before = before->next; } } name = make_unique_name(section, "$pos%03d"); if(!before) { ret = bg_cfg_section_create(name); ret->next = section->children; section->children = ret; } else { tmp = before->next; before->next = bg_cfg_section_create(name);; before->next->next = tmp; ret = before->next; } free(name); return ret; } void bg_cfg_section_move_child(bg_cfg_section_t * s, bg_cfg_section_t * child, int pos) { int i; bg_cfg_section_t * prev; bg_cfg_section_t * tmp; /* Remove child from the list */ if(child == s->children) s->children = s->children->next; else { prev = s->children; while(prev) { if(prev->next == child) break; prev = prev->next; } if(!prev) return; prev->next = child->next; } /* Insert child as the desired position */ if(!pos) { child->next = s->children; s->children = child; } else { prev = s->children; for(i = 0; i < pos - 1; i++) { prev = prev->next; if(!prev) return; } tmp = prev->next; prev->next = child; child->next = tmp; } } int bg_cfg_section_has_subsection(bg_cfg_section_t * s, const char * name) { bg_cfg_section_t * section; section = s->children; while(section) { if(!strcmp(section->name, name)) return 1; section = section->next; } return 0; } bg_cfg_item_t * bg_cfg_section_find_item(bg_cfg_section_t * section, const bg_parameter_info_t * info) { bg_cfg_item_t * prev; bg_cfg_item_t * ret; if(!section->items) { section->items = bg_cfg_item_create(info, NULL); return section->items; } ret = section->items; prev = NULL; while(ret) { if(!strcmp(ret->name, info->name)) return ret; prev = ret; ret = ret->next; } prev->next = bg_cfg_item_create(info, NULL); return prev->next; } static bg_cfg_item_t * find_item_nocreate(bg_cfg_section_t * section, const bg_parameter_info_t * info) { bg_cfg_item_t * ret; ret = section->items; while(ret) { if(!strcmp(ret->name, info->name)) return ret; ret = ret->next; } return NULL; } /* * Get/Set values */ static void value_2_item(const bg_parameter_value_t * value, bg_cfg_item_t * item) { switch(item->type) { case BG_CFG_INT: item->value.val_i = value->val_i; break; case BG_CFG_TIME: item->value.val_time = value->val_time; break; case BG_CFG_FLOAT: item->value.val_f = value->val_f; break; case BG_CFG_STRING: case BG_CFG_STRING_HIDDEN: item->value.val_str = bg_strdup(item->value.val_str, value->val_str); break; case BG_CFG_COLOR: item->value.val_color[0] = value->val_color[0]; item->value.val_color[1] = value->val_color[1]; item->value.val_color[2] = value->val_color[2]; item->value.val_color[3] = value->val_color[3]; break; case BG_CFG_POSITION: item->value.val_pos[0] = value->val_pos[0]; item->value.val_pos[1] = value->val_pos[1]; break; } } void bg_cfg_section_set_parameter(bg_cfg_section_t * section, const bg_parameter_info_t * info, const bg_parameter_value_t * value) { bg_cfg_item_t * item; if(!value) return; item = bg_cfg_section_find_item(section, info); if(!item) return; value_2_item(value, item); } static char * parse_string(const char * str, int * len_ret) { const char * end_c; char cpy_str[2]; char * ret = NULL; end_c = str; cpy_str[1] = '\0'; while(*end_c != '\0') { if(*end_c == '\\') { if((*(end_c+1) == ':') || (*(end_c+1) == '{') || (*(end_c+1) == '}')) { end_c++; cpy_str[0] = *end_c; ret = bg_strcat(ret, cpy_str); } else { cpy_str[0] = *end_c; ret = bg_strcat(ret, cpy_str); } } else if((*end_c == ':') || (*end_c == '{') || (*end_c == '}')) { break; } else { cpy_str[0] = *end_c; ret = bg_strcat(ret, cpy_str); } end_c++; } *len_ret = end_c - str; return ret; } static const bg_parameter_info_t * find_parameter(const bg_parameter_info_t * info, const char * str, int * len, char ** subsection_name) { FILE * out = stderr; int i; const char * end; *subsection_name = NULL; /* Get the options name */ end = str; while((*end != '=') && (*end != '\0')) end++; if(*end == '\0') return NULL; /* Now, find the parameter info */ i = 0; while(info[i].name) { if((info[i].type == BG_PARAMETER_SECTION) && (info[i].flags & BG_PARAMETER_OWN_SECTION)) *subsection_name = info[i].name; if(!info[i].opt) { if((strlen(info[i].name) == (end - str)) && !strncmp(info[i].name, str, end - str)) break; } else { if((strlen(info[i].opt) == (end - str)) && !strncmp(info[i].opt, str, end - str)) break; } i++; } if(!info[i].name) { fprintf(out, "No such option "); fwrite(str, 1, end - str, out); fprintf(out, "\n"); return NULL; } *len = (end - str + 1); // Skip '=' as well return &info[i]; } static int check_option(const bg_parameter_info_t * info, char * name) { int i = 0; FILE * out = stderr; while(info->multi_names[i]) { if(!strcmp(info->multi_names[i], name)) return 1; i++; } fprintf(out, "Unsupported option: %s\n", name); return 0; } /* Returns characters read or 0 */ int bg_cfg_section_set_parameters_from_string(bg_cfg_section_t * sec, const bg_parameter_info_t * parameters, const char * str_start) { FILE * out = stderr; char * end; const char * end_c; bg_cfg_item_t * item; int len = 0, i, index; const bg_parameter_info_t * info; char * real_section_name; bg_cfg_section_t * real_section; bg_cfg_section_t * subsection; char * tmp_string; const char * str = str_start; while(1) { if((*str == '\0') || (*str == '}')) return str - str_start; info = find_parameter(parameters, str, &len, &real_section_name); if(real_section_name) real_section = bg_cfg_section_find_subsection(sec, real_section_name); else real_section = sec; if(!info || (info->type == BG_PARAMETER_SECTION) || (info->type == BG_PARAMETER_BUTTON)) { fprintf(out, "Unsupported parameter "); fwrite(str, 1, len, out); fprintf(out, "\n"); goto fail; } item = bg_cfg_section_find_item(real_section, info); str += len; switch(info->type) { case BG_PARAMETER_CHECKBUTTON: case BG_PARAMETER_INT: case BG_PARAMETER_SLIDER_INT: item->value.val_i = strtol(str, &end, 10); if(str == end) goto fail; str = end; break; case BG_PARAMETER_TIME: end_c = str; if(*end_c == '{') end_c++; end_c += gavl_time_parse(end_c, &item->value.val_time); if(*end_c == '}') end_c++; str = end_c; break; case BG_PARAMETER_FLOAT: case BG_PARAMETER_SLIDER_FLOAT: item->value.val_f = strtod(str, &end); if(str == end) goto fail; str = end; break; case BG_PARAMETER_FILE: case BG_PARAMETER_DIRECTORY: case BG_PARAMETER_DEVICE: case BG_PARAMETER_FONT: case BG_PARAMETER_STRING: case BG_PARAMETER_STRINGLIST: case BG_PARAMETER_STRING_HIDDEN: if(item->value.val_str) { free(item->value.val_str); item->value.val_str = NULL; } item->value.val_str = parse_string(str, &len); /* Check if the string is in the options */ if(info->type == BG_PARAMETER_STRINGLIST) { if(!check_option(info, item->value.val_str)) goto fail; } str += len; break; case BG_PARAMETER_MULTI_LIST: case BG_PARAMETER_MULTI_CHAIN: if(item->value.val_str) { free(item->value.val_str); item->value.val_str = NULL; } if(*str != '{') { fprintf(out, "%s must be in form {option[{suboptions}][:option[{suboption}]]}...\n", info->name); goto fail; } str++; /* If this is a chain, we delete all subsections and recreate them afterwards */ if(info->type == BG_PARAMETER_MULTI_CHAIN) { while(real_section->children) bg_cfg_section_delete_subsection(real_section, real_section->children); } index = 0; while(1) { /* Loop over options */ tmp_string = parse_string(str, &len); if(!check_option(info, tmp_string)) goto fail; str += len; if(item->value.val_str) item->value.val_str = bg_strcat(item->value.val_str, ","); item->value.val_str = bg_strcat(item->value.val_str, tmp_string); /* Suboptions */ if(*str == '{') { str++; subsection = bg_cfg_section_find_subsection(real_section, info->name); if(info->type == BG_PARAMETER_MULTI_LIST) subsection = bg_cfg_section_find_subsection(subsection, tmp_string); else subsection = bg_cfg_section_create_subsection_at_pos(subsection, index); i = 0; while(info->multi_names[i]) { if(!strcmp(info->multi_names[i], tmp_string)) break; i++; } if(!info->multi_names[i]) return 0; // Already checked by check_option above str += bg_cfg_section_set_parameters_from_string(subsection, info->multi_parameters[i], str); if(*str != '}') goto fail; str++; } if(*str == '}') { str++; break; } else if(*str != ':') goto fail; str++; free(tmp_string); index++; } break; case BG_PARAMETER_MULTI_MENU: if(item->value.val_str) { free(item->value.val_str); item->value.val_str = NULL; } item->value.val_str = parse_string(str, &len); if(!check_option(info, item->value.val_str)) goto fail; str += len; /* Parse sub parameters */ if(*str == '{') { str++; subsection = bg_cfg_section_find_subsection(real_section, info->name); subsection = bg_cfg_section_find_subsection(subsection, item->value.val_str); i = 0; while(info->multi_names[i]) { if(!strcmp(info->multi_names[i], item->value.val_str)) break; i++; } if(!info->multi_names[i]) return 0; str += bg_cfg_section_set_parameters_from_string(subsection, info->multi_parameters[i], str); if(*str != '}') goto fail; str++; } break; case BG_PARAMETER_COLOR_RGB: case BG_PARAMETER_COLOR_RGBA: if(*str == '\0') goto fail; item->value.val_color[0] = strtod(str, &end); str = end; if(*str == '\0') goto fail; str++; // , item->value.val_color[1] = strtod(str, &end); str = end; if(*str == '\0') goto fail; str++; // , item->value.val_color[2] = strtod(str, &end); if(str == end) goto fail; if(info->type == BG_PARAMETER_COLOR_RGBA) { str = end; if(*str == '\0') goto fail; str++; // , item->value.val_color[3] = strtod(str, &end); if(str == end) goto fail; } str = end; break; case BG_PARAMETER_POSITION: if(*str == '\0') goto fail; item->value.val_pos[0] = strtod(str, &end); str = end; if(*str == '\0') goto fail; str++; // , item->value.val_pos[1] = strtod(str, &end); str = end; break; case BG_PARAMETER_SECTION: case BG_PARAMETER_BUTTON: break; } if(*str == ':') str++; else if(*str == '}') break; else if(*str == '\0') break; else goto fail; } return str - str_start; fail: fprintf(out, "Error parsing option\n"); fprintf(out, "%s\n", str_start); for(i = 0; i < (int)(str - str_start); i++) fprintf(out, " "); fprintf(out, "^\n"); return 0; } void bg_cfg_section_get_parameter(bg_cfg_section_t * section, const bg_parameter_info_t * info, bg_parameter_value_t * value) { bg_cfg_item_t * item; item = bg_cfg_section_find_item(section, info); if(!value || !item) return; switch(item->type) { case BG_CFG_INT: value->val_i = item->value.val_i; break; case BG_CFG_TIME: value->val_time = item->value.val_time; break; case BG_CFG_FLOAT: value->val_f = item->value.val_f; break; case BG_CFG_STRING: case BG_CFG_STRING_HIDDEN: value->val_str = bg_strdup(value->val_str, item->value.val_str); break; case BG_CFG_COLOR: value->val_color[0] = item->value.val_color[0]; value->val_color[1] = item->value.val_color[1]; value->val_color[2] = item->value.val_color[2]; value->val_color[3] = item->value.val_color[3]; break; case BG_CFG_POSITION: value->val_pos[0] = item->value.val_pos[0]; value->val_pos[1] = item->value.val_pos[1]; break; } } static void free_contents(bg_cfg_section_t * s) { bg_cfg_item_t * next_item; bg_cfg_section_t * next_section; while(s->items) { next_item = s->items->next; bg_cfg_destroy_item(s->items); s->items = next_item; } while(s->children) { next_section = s->children->next; bg_cfg_section_destroy(s->children); s->children = next_section; } } void bg_cfg_section_destroy(bg_cfg_section_t * s) { free_contents(s); free(s->name); if(s->gettext_domain) free(s->gettext_domain); if(s->gettext_directory) free(s->gettext_directory); if(s->refs) free(s->refs); free(s); } static void do_apply(bg_cfg_section_t * section, const bg_parameter_info_t * infos, bg_set_parameter_func_t func, void * callback_data, const char * prefix, int terminate) { int num, selected, i; bg_cfg_item_t * item; bg_cfg_section_t * subsection; bg_cfg_section_t * subsubsection; char * tmp_string; char ** chain_elements; num = 0; while(infos[num].name) { item = bg_cfg_section_find_item(section, &infos[num]); if(!item) { num++; continue; } if(prefix) { tmp_string = bg_sprintf("%s.%s", prefix, item->name); func(callback_data, tmp_string, &item->value); free(tmp_string); } else func(callback_data, item->name, &item->value); /* If this was a menu, apply children */ if(infos[num].multi_names && infos[num].multi_parameters) { if(infos[num].type == BG_PARAMETER_MULTI_MENU) { if(item->value.val_str) { selected = 0; while(infos[num].multi_names[selected] && strcmp(infos[num].multi_names[selected], item->value.val_str)) selected++; if(infos[num].multi_names[selected] && infos[num].multi_parameters[selected]) { subsection = bg_cfg_section_find_subsection(section, infos[num].name); subsubsection = bg_cfg_section_find_subsection(subsection, item->value.val_str); do_apply(subsubsection, infos[num].multi_parameters[selected], func, callback_data, NULL, terminate); } } } else if(infos[num].type == BG_PARAMETER_MULTI_LIST) { selected = 0; /* Apply child parameters for all possible options */ while(infos[num].multi_names[selected]) { subsection = bg_cfg_section_find_subsection(section, infos[num].name); if(infos[num].multi_parameters[selected]) { subsubsection = bg_cfg_section_find_subsection(subsection, infos[num].multi_names[selected]); if(prefix) tmp_string = bg_sprintf("%s.%s.%s", prefix, infos[num].name, infos[num].multi_names[selected]); else tmp_string = bg_sprintf("%s.%s", infos[num].name, infos[num].multi_names[selected]); do_apply(subsubsection, infos[num].multi_parameters[selected], func, callback_data, tmp_string, terminate); free(tmp_string); } selected++; } } else if(infos[num].type == BG_PARAMETER_MULTI_CHAIN) { chain_elements = bg_strbreak(item->value.val_str, ','); selected = 0; subsection = bg_cfg_section_find_subsection(section, infos[num].name); if(chain_elements) { while(chain_elements[selected]) { /* Find parameter info */ i = 0; while(strcmp(infos[num].multi_names[i], chain_elements[selected])) i++; if(infos[num].multi_parameters[i]) { /* Find section */ subsubsection = bg_cfg_section_find_subsection_by_index(subsection, selected); if(!subsubsection) subsubsection = bg_cfg_section_create_subsection_at_pos(subsection, selected); if(prefix) tmp_string = bg_sprintf("%s.%s.%d", prefix, infos[num].name, selected); else tmp_string = bg_sprintf("%s.%d", infos[num].name, selected); do_apply(subsubsection, infos[num].multi_parameters[i], func, callback_data, tmp_string, terminate); free(tmp_string); } selected++; } bg_strbreak_free(chain_elements); } } } num++; } if(terminate) func(callback_data, NULL, NULL); } void bg_cfg_section_apply(bg_cfg_section_t * section, const bg_parameter_info_t * infos, bg_set_parameter_func_t func, void * callback_data) { do_apply(section, infos, func, callback_data, NULL, 1); } void bg_cfg_section_apply_noterminate(bg_cfg_section_t * section, const bg_parameter_info_t * infos, bg_set_parameter_func_t func, void * callback_data) { do_apply(section, infos, func, callback_data, NULL, 0); } void bg_cfg_section_get(bg_cfg_section_t * section, const bg_parameter_info_t * infos, bg_get_parameter_func_t func, void * callback_data) { int num; bg_cfg_item_t * item; if(!func) return; num = 0; while(infos[num].name) { item = bg_cfg_section_find_item(section, &infos[num]); if(item) func(callback_data, item->name, &item->value); num++; } } static bg_cfg_item_t * find_item_by_name(bg_cfg_section_t * section, const char * name, int create_item) { bg_cfg_item_t * prev; bg_cfg_item_t * ret; if(!section->items) { if(create_item) section->items = bg_cfg_item_create_empty(name); return section->items; } ret = section->items; prev = NULL; while(ret) { if(!strcmp(ret->name, name)) return ret; prev = ret; ret = ret->next; } if(create_item) { prev->next = bg_cfg_item_create_empty(name); return prev->next; } return NULL; } void bg_cfg_section_set_parameter_int(bg_cfg_section_t * section, const char * name, int value) { bg_cfg_item_t * item; item = find_item_by_name(section, name, 1); item->type = BG_CFG_INT; item->value.val_i = value; } void bg_cfg_section_set_parameter_float(bg_cfg_section_t * section, const char * name, float value) { bg_cfg_item_t * item; item = find_item_by_name(section, name, 1); item->type = BG_CFG_FLOAT; item->value.val_f = value; } void bg_cfg_section_set_parameter_string(bg_cfg_section_t * section, const char * name, const char * value) { bg_cfg_item_t * item; item = find_item_by_name(section, name, 1); item->type = BG_CFG_STRING; item->value.val_str = bg_strdup(item->value.val_str, value); } void bg_cfg_section_set_parameter_time(bg_cfg_section_t * section, const char * name, gavl_time_t value) { bg_cfg_item_t * item; item = find_item_by_name(section, name, 1); item->type = BG_CFG_TIME; item->value.val_time = value; } /* Get parameter values, return 0 if no such entry */ int bg_cfg_section_get_parameter_int(bg_cfg_section_t * section, const char * name, int * value) { bg_cfg_item_t * item; item = find_item_by_name(section, name, 0); if(!item) return 0; *value = item->value.val_i; return 1; } int bg_cfg_section_get_parameter_float(bg_cfg_section_t * section, const char * name, float * value) { bg_cfg_item_t * item; item = find_item_by_name(section, name, 0); if(!item) return 0; *value = item->value.val_f; return 1; } int bg_cfg_section_get_parameter_string(bg_cfg_section_t * section, const char * name, const char ** value) { bg_cfg_item_t * item; item = find_item_by_name(section, name, 0); if(!item) return 0; *value = item->value.val_str; return 1; } int bg_cfg_section_get_parameter_time(bg_cfg_section_t * section, const char * name, gavl_time_t * value) { bg_cfg_item_t * item; item = find_item_by_name(section, name, 0); if(!item) return 0; *value = item->value.val_time; return 1; } static void copy_contents(const bg_cfg_section_t * src, bg_cfg_section_t * ret) { bg_cfg_item_t * src_item; bg_cfg_item_t * end_item = NULL; bg_cfg_section_t * src_child; bg_cfg_section_t * end_child = NULL; /* Copy items */ src_item = src->items; while(src_item) { if(!ret->items) { ret->items = bg_cfg_item_copy(src_item); end_item = ret->items; } else { end_item->next = bg_cfg_item_copy(src_item); end_item = end_item->next; } src_item = src_item->next; } /* Copy children */ src_child = src->children; while(src_child) { if(!ret->children) { ret->children = bg_cfg_section_copy(src_child); end_child = ret->children; } else { end_child->next = bg_cfg_section_copy(src_child); end_child = end_child->next; } src_child = src_child->next; } } static void copy_refs(const bg_cfg_section_t * src, bg_cfg_section_t * ret) { bg_cfg_section_t * end_child, *new_child; int i; if(src->num_refs) return; end_child = ret->children; if(ret->children) { end_child = ret->children; while(end_child->next) end_child = end_child->next; } for(i = 0; i < src->num_refs; i++) { new_child = bg_cfg_section_copy(src->refs[i]); if(ret->children) { end_child->next = new_child; end_child = end_child->next; } else { ret->children = new_child; end_child = new_child; } } } /* Copy one config section to another */ bg_cfg_section_t * bg_cfg_section_copy(const bg_cfg_section_t * src) { bg_cfg_section_t * ret; ret = calloc(1, sizeof(*ret)); ret->name = bg_strdup(ret->name, src->name); copy_contents(src, ret); copy_refs(src, ret); return ret; } void bg_cfg_section_transfer_children(bg_cfg_section_t * src, bg_cfg_section_t * dst) { bg_cfg_section_t * src_child; bg_cfg_section_t * dst_child; src_child = src->children; while(src_child) { dst_child = bg_cfg_section_find_subsection(dst, src_child->name); bg_cfg_section_transfer(src_child, dst_child); src_child = src_child->next; } } void bg_cfg_section_transfer(bg_cfg_section_t * src, bg_cfg_section_t * dst) { bg_cfg_item_t * src_item; bg_parameter_info_t info; /* Copy items */ src_item = src->items; while(src_item) { bg_cfg_item_to_parameter(src_item, &info); bg_cfg_section_set_parameter(dst, &info, &src_item->value); src_item = src_item->next; } /* Copy children */ bg_cfg_section_transfer_children(src, dst); } const char * bg_cfg_section_get_name(bg_cfg_section_t * s) { if(!s) return NULL; return s->name; } char * bg_cfg_section_get_name_translated(bg_cfg_section_t * s) { if(!s) return NULL; if(s->gettext_domain && s->gettext_directory) { bg_bindtextdomain(s->gettext_domain, s->gettext_directory); return bg_strdup(NULL, dgettext(s->gettext_domain, s->name)); } else return bg_strdup(NULL, s->name); } void bg_cfg_section_set_name(bg_cfg_section_t * s, const char * name, const char * gettext_domain, const char * gettext_directory) { s->name = bg_strdup(s->name, name); s->gettext_domain = bg_strdup(s->gettext_domain, gettext_domain); s->gettext_directory = bg_strdup(s->gettext_directory, gettext_directory); } bg_cfg_section_t * bg_cfg_section_create_from_parameters(const char * name, const bg_parameter_info_t * parameters) { bg_cfg_section_t * ret; ret = bg_cfg_section_create(name); bg_cfg_section_create_items(ret, parameters); return ret; } static void create_items(bg_cfg_section_t * section, const bg_parameter_info_t * info, int stop_at_section) { int i; int j; bg_cfg_section_t * subsection; bg_cfg_section_t * subsubsection; i = 0; // if(section->name && !strcmp(section->name, "e_mpeg")) // fprintf(stderr, "e_mpeg\n"); while(info[i].name) { if((info[i].type == BG_PARAMETER_SECTION) && stop_at_section) return; if(info[i].flags & BG_PARAMETER_OWN_SECTION) { subsection = bg_cfg_section_find_subsection(section, info[i].name); i++; create_items(subsection, &info[i], 1); /* Skip what we read so far */ while(info[i].type != BG_PARAMETER_SECTION) { if(!info[i].name) return; i++; } } else { // fprintf(stderr, "Section: %s, parameter: %s\n", // section->name, info[i].name); bg_cfg_section_find_item(section, &info[i]); if(info[i].multi_parameters) { j = 0; subsection = bg_cfg_section_find_subsection(section, info[i].name); while(info[i].multi_names[j]) { if(info[i].multi_parameters[j]) { subsubsection = bg_cfg_section_find_subsection(subsection, info[i].multi_names[j]); bg_cfg_section_create_items(subsubsection, info[i].multi_parameters[j]); } j++; } } i++; } } } void bg_cfg_section_create_items(bg_cfg_section_t * section, const bg_parameter_info_t * info) { create_items(section, info, 0); } void bg_cfg_section_delete_subsection(bg_cfg_section_t * section, bg_cfg_section_t * subsection) { bg_cfg_section_t * before; if(!section->children) return; if(section->children == subsection) { section->children = section->children->next; bg_cfg_section_destroy(subsection); } else { before = section->children; while(before->next) { if(before->next == subsection) break; before = before->next; } if(before->next) { before->next = before->next->next; bg_cfg_section_destroy(subsection); } } } void bg_cfg_section_delete_subsections(bg_cfg_section_t * section) { bg_cfg_section_t * tmp; while(section->children) { tmp = section->children->next; bg_cfg_section_destroy(section->children); section->children = tmp; } } void bg_cfg_section_add_ref(bg_cfg_section_t * s, bg_cfg_section_t * ref) { int i; /* Add refs only once */ for(i = 0; i < s->num_refs; i++) { if(!strcmp(ref->name, s->refs[i]->name)) return; } s->refs = realloc(s->refs, (s->num_refs+1)*sizeof(*s->refs)); s->refs[s->num_refs] = ref; s->num_refs++; } void bg_cfg_section_restore_defaults(bg_cfg_section_t * s, const bg_parameter_info_t * info) { bg_cfg_item_t * item; int i; bg_cfg_section_t * subsection; bg_cfg_section_t * subsubsection; while(info->name) { if(info->flags & BG_PARAMETER_HIDE_DIALOG) { info++; continue; } item = find_item_nocreate(s, info); if(!item) { info++; continue; } value_2_item(&info->val_default, item); if(info->multi_parameters && bg_cfg_section_has_subsection(s, info->name)) { subsection = bg_cfg_section_find_subsection(s, info->name); i = 0; while(info->multi_names[i]) { if(info->multi_parameters[i] && bg_cfg_section_has_subsection(subsection, info->multi_names[i])) { subsubsection = bg_cfg_section_find_subsection(subsection, info->multi_names[i]); bg_cfg_section_restore_defaults(subsubsection, info->multi_parameters[i]); } i++; } } info++; } } gmerlin-1.2.0~dfsg/lib/urilist.c0000644000175000017500000001142011764363410016501 0ustar alessioalessio/***************************************************************** * gmerlin - a general purpose multimedia framework and applications * * Copyright (c) 2001 - 2011 Members of the Gmerlin project * gmerlin-general@lists.sourceforge.net * http://gmerlin.sourceforge.net * * 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 of the License, 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 this program. If not, see . * *****************************************************************/ #include #include #include #include #include #include #define HOSTNAME_MAX_LEN 512 static int do_substitute(uint8_t c) { if(!isalnum(c) && (c != '-') && (c != '_') && (c != '~') && (c != ':') && (c != '/') && (c != '.')) return 1; if((c <= 32) || (c >= 127)) return 1; return 0; } char * bg_string_to_uri(const char * _pos, int len) { char * ret; char * dst; int i; int num_substitutions; int prepend_file = 0; const uint8_t * pos; if(!_pos) return NULL; pos = (const uint8_t *)_pos; num_substitutions = 0; if(len < 0) len = strlen((char*)pos); for(i = 0; i < len; i++) { if(do_substitute(pos[i])) num_substitutions++; } if(_pos[0] == '/') prepend_file = 1; ret = calloc(1, len + num_substitutions * 2 + 1 + prepend_file * 7 /* file:// */ ); dst = ret; if(prepend_file) { sprintf(dst, "file://"); dst += 7; } for(i = 0; i < len; i++) { if(do_substitute(pos[i])) { sprintf(dst, "%%%02X", pos[i]); dst += 3; } else { *dst = pos[i]; dst++; } } return ret; } char * bg_uri_to_string(const char * pos1, int len) { const char * start; int real_char; char * ret; char * ret_pos; char hostname[HOSTNAME_MAX_LEN]; int hostname_len; if(!pos1) return NULL; if(len < 0) len = strlen(pos1); if(!strncmp(pos1, "file:/", 6)) { if(pos1[6] != '/') { /* KDE Case */ start = &pos1[5]; } else if(pos1[7] != '/') /* RFC .... (text/uri-list) */ { gethostname(hostname, HOSTNAME_MAX_LEN); hostname_len = strlen(hostname); if((len - 7) < hostname_len) return NULL; if(strncmp(&pos1[7], hostname, strlen(hostname))) return NULL; start = &pos1[7+hostname_len]; } else /* Gnome Case */ start = &pos1[7]; } else start = pos1; /* Allocate return value and decode */ ret = calloc(len - (start - pos1) + 1, sizeof(char)); ret_pos = ret; while(start - pos1 < len) { if(*start == '%') { if((len - (start - pos1) < 3) || (!sscanf(&start[1], "%02x", &real_char))) { free(ret); return NULL; } start += 3; *ret_pos = real_char; } else { *ret_pos = *start; start++; } ret_pos++; } *ret_pos = '\0'; return ret; } char ** bg_urilist_decode(const char * str, int len) { char ** ret; const char * pos1; const char * pos2; int end; int num_uris; int num_added; pos1 = str; /* Count the URIs */ end = 0; num_uris = 0; while(1) { /* Skip spaces */ while(((pos1 - str) < len) && isspace(*pos1)) pos1++; if(isspace(*pos1) || (*pos1 == '\0')) break; num_uris++; /* Skip non-spaces */ while(((pos1 - str) < len) && !isspace(*pos1)) pos1++; if(!isspace(*pos1)) break; } /* Set up the array and decode URLS */ num_added = 0; end = 0; pos1 = str; ret = calloc(num_uris+1, sizeof(char*)); while(1) { while(((pos1 - str) < len) && isspace(*pos1)) pos1++; pos2 = pos1; while(((pos2 - str) < len) && !isspace(*pos2)) pos2++; if(!isspace(*pos2) || (pos1 == pos2)) { end = 1; if(*pos2 != '\0') pos2++; } if(pos2 == pos1) break; if((ret[num_added] = bg_uri_to_string(pos1, pos2-pos1))) { num_added++; } pos1 = pos2; } return ret; } void bg_urilist_free(char ** uri_list) { int i; i = 0; while(uri_list[i]) { free(uri_list[i]); i++; } free(uri_list); } gmerlin-1.2.0~dfsg/lib/player_loop.c0000644000175000017500000010654211764363410017345 0ustar alessioalessio/***************************************************************** * gmerlin - a general purpose multimedia framework and applications * * Copyright (c) 2001 - 2011 Members of the Gmerlin project * gmerlin-general@lists.sourceforge.net * http://gmerlin.sourceforge.net * * 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 of the License, 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 this program. If not, see . * *****************************************************************/ #include #include #include #include #include #include #define LOG_DOMAIN "player" /* Metadata */ static void msg_metadata(bg_msg_t * msg, const void * data) { gavl_metadata_t * m = (gavl_metadata_t *)data; bg_msg_set_id(msg, BG_PLAYER_MSG_METADATA); bg_msg_set_arg_metadata(msg, 0, m); } static void msg_time(bg_msg_t * msg, const void * data) { bg_msg_set_id(msg, BG_PLAYER_MSG_TIME_CHANGED); bg_msg_set_arg_time(msg, 0, *((const gavl_time_t*)data)); } static void msg_cleanup(bg_msg_t * msg, const void * data) { bg_msg_set_id(msg, BG_PLAYER_MSG_CLEANUP); } static void msg_interrupt(bg_msg_t * msg, const void * data) { bg_msg_set_id(msg, BG_PLAYER_MSG_INTERRUPT); } static void msg_interrupt_resume(bg_msg_t * msg, const void * data) { bg_msg_set_id(msg, BG_PLAYER_MSG_INTERRUPT_RESUME); } static void msg_volume_changed(bg_msg_t * msg, const void * data) { bg_msg_set_id(msg, BG_PLAYER_MSG_VOLUME_CHANGED); bg_msg_set_arg_float(msg, 0, *((float*)data)); } static void msg_audio_stream(bg_msg_t * msg, const void * data) { const bg_player_t * player; player = (const bg_player_t*)data; bg_msg_set_id(msg, BG_PLAYER_MSG_AUDIO_STREAM); bg_msg_set_arg_int(msg, 0, player->current_audio_stream); bg_msg_set_arg_audio_format(msg, 1, &player->audio_stream.input_format); bg_msg_set_arg_audio_format(msg, 2, &player->audio_stream.output_format); } static void msg_video_stream(bg_msg_t * msg, const void * data) { bg_player_t * player; player = (bg_player_t*)data; bg_msg_set_id(msg, BG_PLAYER_MSG_VIDEO_STREAM); bg_msg_set_arg_int(msg, 0, player->current_video_stream); bg_msg_set_arg_video_format(msg, 1, &player->video_stream.input_format); bg_msg_set_arg_video_format(msg, 2, &player->video_stream.output_format); } static void msg_subtitle_stream(bg_msg_t * msg, const void * data) { bg_player_t * player; player = (bg_player_t*)data; bg_msg_set_id(msg, BG_PLAYER_MSG_SUBTITLE_STREAM); bg_msg_set_arg_int(msg, 0, player->current_subtitle_stream); bg_msg_set_arg_int(msg, 1, !!DO_SUBTITLE_TEXT(player->flags)); bg_msg_set_arg_video_format(msg, 2, &player->subtitle_stream.input_format); bg_msg_set_arg_video_format(msg, 3, &player->subtitle_stream.output_format); } static void msg_num_streams(bg_msg_t * msg, const void * data) { bg_track_info_t * info; info = (bg_track_info_t *)data; bg_msg_set_id(msg, BG_PLAYER_MSG_TRACK_NUM_STREAMS); bg_msg_set_arg_int(msg, 0, info->num_audio_streams); bg_msg_set_arg_int(msg, 1, info->num_video_streams); bg_msg_set_arg_int(msg, 2, info->num_subtitle_streams); } struct stream_info_s { bg_track_info_t * track; int index; }; static void msg_audio_stream_info(bg_msg_t * msg, const void * data) { const struct stream_info_s * si; si = (const struct stream_info_s*)data; bg_msg_set_id(msg, BG_PLAYER_MSG_AUDIO_STREAM_INFO); bg_msg_set_arg_int(msg, 0, si->index); bg_msg_set_arg_metadata(msg, 1, &si->track->audio_streams[si->index].m); } static void msg_video_stream_info(bg_msg_t * msg, const void * data) { const struct stream_info_s * si; si = (const struct stream_info_s*)data; bg_msg_set_id(msg, BG_PLAYER_MSG_VIDEO_STREAM_INFO); bg_msg_set_arg_int(msg, 0, si->index); bg_msg_set_arg_metadata(msg, 1, &si->track->video_streams[si->index].m); } static void msg_subtitle_stream_info(bg_msg_t * msg, const void * data) { const struct stream_info_s * si; si = (const struct stream_info_s*)data; bg_msg_set_id(msg, BG_PLAYER_MSG_SUBTITLE_STREAM_INFO); bg_msg_set_arg_int(msg, 0, si->index); bg_msg_set_arg_metadata(msg, 1, &si->track->subtitle_streams[si->index].m); } static void msg_mute(bg_msg_t * msg, const void * data) { bg_msg_set_id(msg, BG_PLAYER_MSG_MUTE); bg_msg_set_arg_int(msg, 0, *((int*)data)); } #if 0 static void msg_subpicture_description(bg_msg_t * msg, const void * data) { bg_msg_set_id(msg, BG_PLAYER_MSG_SUBPICTURE_DESCRIPTION); bg_msg_set_arg_string(msg, 0, (char*)data); } #endif static void msg_num_chapters(bg_msg_t * msg, const void * data) { bg_chapter_list_t * l; l = (bg_chapter_list_t *)data; bg_msg_set_id(msg, BG_PLAYER_MSG_NUM_CHAPTERS); if(l) { bg_msg_set_arg_int(msg, 0, l->num_chapters); bg_msg_set_arg_int(msg, 1, l->timescale); } else { bg_msg_set_arg_int(msg, 0, 0); bg_msg_set_arg_int(msg, 1, 0); } } struct chapter_info_s { bg_chapter_list_t * l; int index; }; static void msg_chapter_info(bg_msg_t * msg, const void * data) { struct chapter_info_s * d = (struct chapter_info_s*)data; bg_msg_set_id(msg, BG_PLAYER_MSG_CHAPTER_INFO); bg_msg_set_arg_int(msg, 0, d->index); bg_msg_set_arg_string(msg, 1, d->l->chapters[d->index].name); bg_msg_set_arg_time(msg, 2, d->l->chapters[d->index].time); } static void msg_chapter_changed(bg_msg_t * msg, const void * data) { bg_msg_set_id(msg, BG_PLAYER_MSG_CHAPTER_CHANGED); bg_msg_set_arg_int(msg, 0, *((int*)data)); } /* * Interrupt playback so all plugin threads are waiting inside * keep_going(); * * Called for pause and seeking */ static void interrupt_cmd(bg_player_t * p, int new_state) { int old_state; /* Get the old state */ old_state = bg_player_get_state(p); /* Set the new state */ bg_player_set_state(p, new_state, NULL, NULL); if(old_state == BG_PLAYER_STATE_PAUSED) return; bg_player_threads_pause(p->threads, PLAYER_MAX_THREADS); bg_player_time_stop(p); if(DO_AUDIO(p->flags)) bg_player_oa_stop(&p->audio_stream); if(DO_VIDEO(p->flags)) p->flags |= PLAYER_FREEZE_FRAME; if(DO_VISUALIZE(p->flags)) p->flags |= PLAYER_FREEZE_VIS; } /* Preload fifos */ static void preload(bg_player_t * p) { /* TODO */ } /* Start playback */ static void start_playback(bg_player_t * p) { bg_player_set_state(p, BG_PLAYER_STATE_PLAYING, &p->can_pause, NULL); /* Start timer */ bg_player_time_start(p); if(DO_AUDIO(p->flags)) bg_player_oa_start(&p->audio_stream); p->flags &= ~(PLAYER_FREEZE_FRAME|PLAYER_FREEZE_VIS); bg_player_threads_start(p->threads, PLAYER_MAX_THREADS); } /* Pause command */ static void pause_cmd(bg_player_t * p) { int state; if(!p->can_pause) { bg_log(BG_LOG_ERROR, LOG_DOMAIN, "Cannot pause live stream"); return; } state = bg_player_get_state(p); if(state == BG_PLAYER_STATE_PLAYING) { interrupt_cmd(p, BG_PLAYER_STATE_PAUSED); if(DO_VIDEO(p->flags)) bg_player_ov_update_still(p); } else if(state == BG_PLAYER_STATE_PAUSED) { preload(p); start_playback(p); } } static int init_audio_stream(bg_player_t * p) { if(!bg_player_audio_init(p, p->current_audio_stream)) { bg_player_set_state(p, BG_PLAYER_STATE_ERROR, NULL, NULL); return 0; } return 1; } static int init_video_stream(bg_player_t * p) { if(!bg_player_video_init(p, p->current_video_stream)) { bg_player_set_state(p, BG_PLAYER_STATE_ERROR, NULL, NULL); return 0; } return 1; } static int init_subtitle_stream(bg_player_t * p) { if(!bg_player_subtitle_init(p, p->current_subtitle_stream)) { bg_player_set_state(p, BG_PLAYER_STATE_ERROR, NULL, NULL); return 0; } return 1; } /* Initialize playback pipelines */ static int init_streams(bg_player_t * p) { if(DO_SUBTITLE_ONLY(p->flags)) { if(!init_audio_stream(p) || !init_subtitle_stream(p) || !init_video_stream(p)) return 0; } else { if(!init_audio_stream(p) || !init_video_stream(p) || !init_subtitle_stream(p)) return 0; } return 1; } /* Cleanup everything */ static void cleanup_streams(bg_player_t * player) { if(DO_AUDIO(player->flags)) bg_player_oa_cleanup(&player->audio_stream); if(DO_VIDEO(player->flags)) bg_player_ov_cleanup(&player->video_stream); bg_player_time_stop(player); /* Subtitles must be cleaned up as long as the ov plugin is still open */ bg_player_subtitle_cleanup(player); bg_player_video_cleanup(player); bg_player_audio_cleanup(player); bg_player_time_reset(player); } static void player_cleanup(bg_player_t * player) { gavl_time_t t = 0; bg_player_input_cleanup(player); cleanup_streams(player); bg_msg_queue_list_send(player->message_queues, msg_time, &t); } /* Initialize playback (called when playback starts or after streams have changed) */ static void init_playback(bg_player_t * p, gavl_time_t time, int flags) { int i; struct stream_info_s si; struct chapter_info_s ci; bg_player_set_state(p, BG_PLAYER_STATE_STARTING, NULL, NULL); /* Close previous visualization before we init the streams because it might close the ov_plugin as well */ if(DO_VISUALIZE(p->old_flags) && !DO_VISUALIZE(p->flags)) bg_visualizer_close(p->visualizer); /* Initialize audio and video streams */ if(!init_streams(p)) return; /* Set up visualizations */ if(DO_VISUALIZE(p->flags)) { if(!DO_VISUALIZE(p->old_flags) || bg_visualizer_need_restart(p->visualizer)) { if(DO_VISUALIZE(p->old_flags)) bg_visualizer_close(p->visualizer); /* Initialize visualizer */ bg_visualizer_open_plugin(p->visualizer, &p->audio_stream.fifo_format, bg_ov_get_plugin(p->video_stream.ov)); } else { /* Update audio format */ bg_visualizer_set_audio_format(p->visualizer, &p->audio_stream.fifo_format); } } /* Send input messages */ bg_player_input_send_messages(p); /* Send metadata */ bg_msg_queue_list_send(p->message_queues, msg_metadata, &p->track_info->metadata); bg_player_set_duration(p, p->track_info->duration, p->can_seek); bg_msg_queue_list_send(p->message_queues, msg_num_streams, p->track_info); /* Send chapter info */ bg_msg_queue_list_send(p->message_queues, msg_num_chapters, p->track_info->chapter_list); ci.l = p->track_info->chapter_list; if(ci.l) { for(ci.index = 0; ci.index < ci.l->num_chapters; ci.index++) { bg_msg_queue_list_send(p->message_queues, msg_chapter_info, &ci); } p->current_chapter = 0; bg_msg_queue_list_send(p->message_queues, msg_chapter_changed, &p->current_chapter); } /* Send infos about the streams we have */ si.track = p->track_info; for(i = 0; i < p->track_info->num_audio_streams; i++) { si.index = i; bg_msg_queue_list_send(p->message_queues, msg_audio_stream_info, &si); } for(i = 0; i < p->track_info->num_video_streams; i++) { si.index = i; bg_msg_queue_list_send(p->message_queues, msg_video_stream_info, &si); } for(i = 0; i < p->track_info->num_subtitle_streams; i++) { si.index = i; bg_msg_queue_list_send(p->message_queues, msg_subtitle_stream_info, &si); } /* Send messages about formats */ if(DO_AUDIO(p->flags)) { bg_msg_queue_list_send(p->message_queues, msg_audio_stream, p); } if(DO_VIDEO(p->flags)) { bg_msg_queue_list_send(p->message_queues, msg_video_stream, p); } else if(!DO_VISUALIZE(p->flags)) bg_player_ov_standby(&p->video_stream); if(DO_SUBTITLE(p->flags)) { bg_msg_queue_list_send(p->message_queues, msg_subtitle_stream, p); } /* Count the threads */ if(DO_AUDIO(p->flags)) { bg_player_thread_set_func(p->audio_stream.th, bg_player_oa_thread, p); } else { bg_player_thread_set_func(p->audio_stream.th, NULL, NULL); } if(DO_VIDEO(p->flags)) { bg_player_thread_set_func(p->video_stream.th, bg_player_ov_thread, p); } else { bg_player_thread_set_func(p->video_stream.th, NULL, NULL); } bg_player_time_init(p); if((time > 0) && (p->can_seek)) { bg_player_input_seek(p, &time, GAVL_TIME_SCALE); bg_player_time_set(p, time); } else { if(DO_AUDIO(p->flags)) bg_audio_filter_chain_reset(p->audio_stream.fc); if(DO_VIDEO(p->flags)) bg_video_filter_chain_reset(p->video_stream.fc); } bg_player_threads_init(p->threads, PLAYER_MAX_THREADS); preload(p); if(flags & BG_PLAY_FLAG_INIT_THEN_PAUSE) { bg_player_set_state(p, BG_PLAYER_STATE_PAUSED, NULL, NULL); if(DO_VIDEO(p->flags)) { bg_player_ov_reset(p); bg_player_ov_update_still(p); p->flags |= PLAYER_FREEZE_FRAME; } } else start_playback(p); /* Set start time to zero */ bg_msg_queue_list_send(p->message_queues, msg_time, &time); } /* Play a file. This must be called ONLY if the player is in a defined stopped state */ static void play_cmd(bg_player_t * p, bg_plugin_handle_t * handle, int track_index, char * track_name, int flags) { /* Shut down from last playback if necessary */ if(p->input_handle) player_cleanup(p); bg_player_set_track_name(p, track_name); p->input_handle = handle; if(!bg_player_input_init(p, handle, track_index)) { bg_player_set_state(p, BG_PLAYER_STATE_ERROR, NULL, NULL); bg_player_ov_standby(&p->video_stream); return; } init_playback(p, 0, flags); } static void cleanup_playback(bg_player_t * player, int old_state, int new_state, int want_new, int stop_input) { if(old_state == BG_PLAYER_STATE_STOPPED) return; if(new_state == BG_PLAYER_STATE_CHANGING) bg_player_set_state(player, new_state, &want_new, NULL); else bg_player_set_state(player, new_state, NULL, NULL); switch(old_state) { case BG_PLAYER_STATE_CHANGING: break; case BG_PLAYER_STATE_STARTING: case BG_PLAYER_STATE_PAUSED: case BG_PLAYER_STATE_SEEKING: case BG_PLAYER_STATE_BUFFERING: case BG_PLAYER_STATE_PLAYING: bg_player_threads_join(player->threads, PLAYER_MAX_THREADS); if(DO_AUDIO(player->flags)) bg_player_oa_stop(&player->audio_stream); default: break; } if(new_state == BG_PLAYER_STATE_STOPPED) { if(DO_VISUALIZE(player->flags)) { /* Must clear this here */ player->flags &= ~PLAYER_DO_VISUALIZE; bg_visualizer_close(player->visualizer); } bg_player_ov_standby(&player->video_stream); } return; } static void stop_cmd(bg_player_t * player, int new_state, int want_new) { int old_state; old_state = bg_player_get_state(player); cleanup_playback(player, old_state, new_state, want_new, 1); if((old_state == BG_PLAYER_STATE_PLAYING) || (old_state == BG_PLAYER_STATE_PAUSED)) { if((new_state == BG_PLAYER_STATE_STOPPED) || (new_state == BG_PLAYER_STATE_CHANGING)) player_cleanup(player); } player->old_flags = player->flags; player->flags &= 0xFFFF0000; } static void stream_change_init(bg_player_t * player) { int old_state; old_state = bg_player_get_state(player); if((old_state == BG_PLAYER_STATE_STOPPED) || (old_state == BG_PLAYER_STATE_CHANGING) || (old_state == BG_PLAYER_STATE_ERROR)) player->saved_state.playing = 0; else player->saved_state.playing = 1; if(player->saved_state.playing) { bg_player_time_get(player, 1, &player->saved_state.time); /* Interrupt and pretend we are seeking */ cleanup_playback(player, old_state, BG_PLAYER_STATE_CHANGING, 0, 1); cleanup_streams(player); bg_player_input_stop(player); player->old_flags = player->flags; } } static int stream_change_done(bg_player_t * player) { gavl_time_t t = 0; if(player->saved_state.playing) { if(!bg_player_input_set_track(player)) { bg_player_set_state(player, BG_PLAYER_STATE_ERROR, NULL, NULL); goto fail; } bg_player_input_select_streams(player); if(!bg_player_input_start(player)) { bg_player_set_state(player, BG_PLAYER_STATE_ERROR, NULL, NULL); goto fail; } init_playback(player, player->saved_state.time, 0); } return 1; fail: bg_player_ov_standby(&player->video_stream); bg_player_time_reset(player); bg_player_input_cleanup(player); bg_msg_queue_list_send(player->message_queues, msg_time, &t); return 0; } static void set_ov_plugin_cmd(bg_player_t * player, bg_plugin_handle_t * handle) { stream_change_init(player); bg_player_ov_set_plugin(player, handle); bg_player_ov_standby(&player->video_stream); stream_change_done(player); } static void set_oa_plugin_cmd(bg_player_t * player, bg_plugin_handle_t * handle) { stream_change_init(player); bg_player_oa_set_plugin(player, handle); stream_change_done(player); } static void seek_cmd(bg_player_t * player, gavl_time_t t, int scale) { int new_chapter; gavl_time_t sync_time = t; int old_state; old_state = bg_player_get_state(player); // gavl_video_frame_t * vf; interrupt_cmd(player, BG_PLAYER_STATE_SEEKING); if(player->can_seek) bg_player_input_seek(player, &sync_time, scale); /* Clear fifos and filter chains */ if(DO_AUDIO(player->flags)) bg_audio_filter_chain_reset(player->audio_stream.fc); if(DO_VIDEO(player->flags)) bg_video_filter_chain_reset(player->video_stream.fc); #if 0 if(DO_SUBTITLE(player->flags)) { } #endif /* Resync */ preload(player); if(player->can_seek) bg_player_time_set(player, sync_time); else bg_player_time_set(player, 0); if(DO_VIDEO(player->flags)) bg_player_ov_reset(player); /* Update position in chapter list */ if(player->track_info->chapter_list) { new_chapter = bg_chapter_list_get_current(player->track_info->chapter_list, sync_time); if(new_chapter != player->current_chapter) { player->current_chapter = new_chapter; bg_msg_queue_list_send(player->message_queues, msg_chapter_changed, &player->current_chapter); } } if(old_state == BG_PLAYER_STATE_PAUSED) { bg_player_set_state(player, BG_PLAYER_STATE_PAUSED, NULL, NULL); /* Need to update slider and time for seeking case */ bg_msg_queue_list_send(player->message_queues, msg_time, &sync_time); if(DO_VIDEO(player->flags)) bg_player_ov_update_still(player); // if(p->do_bypass) // bg_player_input_bypass_set_pause(p->input_context, 1); } else start_playback(player); } static void set_audio_stream_cmd(bg_player_t * player, int stream) { if(stream == player->current_audio_stream) return; stream_change_init(player); player->current_audio_stream = stream; stream_change_done(player); } static void set_video_stream_cmd(bg_player_t * player, int stream) { if(stream == player->current_video_stream) return; stream_change_init(player); player->current_video_stream = stream; stream_change_done(player); } static void set_subtitle_stream_cmd(bg_player_t * player, int stream) { if(stream == player->current_subtitle_stream) return; stream_change_init(player); player->current_subtitle_stream = stream; stream_change_done(player); } static void chapter_cmd(bg_player_t * player, int chapter) { int state; if(!player->can_seek) return; state = bg_player_get_state(player); if((state != BG_PLAYER_STATE_PLAYING) && (state != BG_PLAYER_STATE_PAUSED)) return; if(!player->track_info->chapter_list || (chapter < 0) || (chapter >= player->track_info->chapter_list->num_chapters)) return; seek_cmd(player, player->track_info->chapter_list->chapters[chapter].time, player->track_info->chapter_list->timescale); } /* Process command, return FALSE if thread should be ended */ static int process_commands(bg_player_t * player) { int play_flags; int arg_i1; float arg_f1; int state; void * arg_ptr1; char * arg_str1; gavl_time_t time; gavl_time_t current_time; bg_msg_t * command; int queue_locked = 0; uint32_t id; while(1) { command = bg_msg_queue_try_lock_read(player->command_queue); if(!command) return 1; /* Process commands */ queue_locked = 1; switch(bg_msg_get_id(command)) { case BG_PLAYER_CMD_QUIT: state = bg_player_get_state(player); switch(state) { case BG_PLAYER_STATE_PLAYING: case BG_PLAYER_STATE_CHANGING: case BG_PLAYER_STATE_PAUSED: stop_cmd(player, BG_PLAYER_STATE_STOPPED, 0); break; } bg_msg_queue_unlock_read(player->command_queue); queue_locked = 0; return 0; break; case BG_PLAYER_CMD_PLAY: play_flags = bg_msg_get_arg_int(command, 2); state = bg_player_get_state(player); arg_ptr1 = bg_msg_get_arg_ptr_nocopy(command, 0); if(play_flags) { if((state == BG_PLAYER_STATE_PLAYING) && (play_flags & BG_PLAY_FLAG_IGNORE_IF_PLAYING)) { if(arg_ptr1) bg_plugin_unref((bg_plugin_handle_t*)arg_ptr1); break; } else if((state == BG_PLAYER_STATE_STOPPED) && (play_flags & BG_PLAY_FLAG_IGNORE_IF_STOPPED)) { if(arg_ptr1) bg_plugin_unref((bg_plugin_handle_t*)arg_ptr1); break; } } if(state == BG_PLAYER_STATE_PAUSED) { if(play_flags & BG_PLAY_FLAG_RESUME) { pause_cmd(player); if(arg_ptr1) bg_plugin_unref((bg_plugin_handle_t*)arg_ptr1); break; } else play_flags |= BG_PLAY_FLAG_INIT_THEN_PAUSE; } arg_i1 = bg_msg_get_arg_int(command, 1); arg_str1 = bg_msg_get_arg_string(command, 3); if((state == BG_PLAYER_STATE_PLAYING) || (state == BG_PLAYER_STATE_PAUSED)) { stop_cmd(player, BG_PLAYER_STATE_CHANGING, 0); } if(!arg_ptr1) { bg_player_set_state(player, BG_PLAYER_STATE_ERROR, "No Track selected", NULL); } else play_cmd(player, arg_ptr1, arg_i1, arg_str1, play_flags); if(arg_str1) free(arg_str1); break; case BG_PLAYER_CMD_STOP: state = bg_player_get_state(player); switch(state) { case BG_PLAYER_STATE_PLAYING: case BG_PLAYER_STATE_PAUSED: case BG_PLAYER_STATE_CHANGING: case BG_PLAYER_STATE_EOF: stop_cmd(player, BG_PLAYER_STATE_STOPPED, 0); break; } break; case BG_PLAYER_CMD_CHANGE: state = bg_player_get_state(player); arg_i1 = bg_msg_get_arg_int(command, 0); switch(state) { case BG_PLAYER_STATE_PLAYING: case BG_PLAYER_STATE_PAUSED: case BG_PLAYER_STATE_SEEKING: if(!(arg_i1 & BG_PLAY_FLAG_IGNORE_IF_PLAYING)) stop_cmd(player, BG_PLAYER_STATE_CHANGING, 0); break; case BG_PLAYER_STATE_STOPPED: if(!(arg_i1 & BG_PLAY_FLAG_IGNORE_IF_STOPPED)) stop_cmd(player, BG_PLAYER_STATE_CHANGING, 0); break; case BG_PLAYER_STATE_CHANGING: stop_cmd(player, BG_PLAYER_STATE_CHANGING, 0); break; } bg_msg_queue_list_send(player->message_queues, msg_cleanup, &player); break; case BG_PLAYER_CMD_SEEK: { int scale; if(!player->can_seek) break; state = bg_player_get_state(player); if((state != BG_PLAYER_STATE_PLAYING) && (state != BG_PLAYER_STATE_PAUSED)) break; time = bg_msg_get_arg_time(command, 0); scale = bg_msg_get_arg_time(command, 1); bg_msg_queue_unlock_read(player->command_queue); queue_locked = 0; /* Check if there are more messages */ while(bg_msg_queue_peek(player->command_queue, &id) && (id == BG_PLAYER_CMD_SEEK)) { command = bg_msg_queue_lock_read(player->command_queue); queue_locked = 1; time = bg_msg_get_arg_time(command, 0); scale = bg_msg_get_arg_time(command, 1); bg_msg_queue_unlock_read(player->command_queue); queue_locked = 0; } seek_cmd(player, time, scale); } break; case BG_PLAYER_CMD_SET_CHAPTER: arg_i1 = bg_msg_get_arg_int(command, 0); chapter_cmd(player, arg_i1); break; case BG_PLAYER_CMD_NEXT_CHAPTER: chapter_cmd(player, player->current_chapter + 1); break; case BG_PLAYER_CMD_PREV_CHAPTER: chapter_cmd(player, player->current_chapter - 1); break; case BG_PLAYER_CMD_SEEK_REL: if(!player->can_seek) break; state = bg_player_get_state(player); if((state != BG_PLAYER_STATE_PLAYING) && (state != BG_PLAYER_STATE_PAUSED)) break; time = bg_msg_get_arg_time(command, 0); bg_msg_queue_unlock_read(player->command_queue); queue_locked = 0; /* Check if there are more messages */ while(bg_msg_queue_peek(player->command_queue, &id) && (id == BG_PLAYER_CMD_SEEK_REL)) { command = bg_msg_queue_lock_read(player->command_queue); queue_locked = 1; time += bg_msg_get_arg_time(command, 0); bg_msg_queue_unlock_read(player->command_queue); queue_locked = 0; } bg_player_time_get(player, 1, ¤t_time); time += current_time; if(time < 0) time = 0; else if(time > player->track_info->duration) { /* Seeked beyond end -> finish track */ stop_cmd(player, BG_PLAYER_STATE_CHANGING, 1); break; } else seek_cmd(player, time, GAVL_TIME_SCALE); break; case BG_PLAYER_CMD_SET_VOLUME: arg_f1 = bg_msg_get_arg_float(command, 0); player->volume = arg_f1; bg_player_oa_set_volume(&player->audio_stream, player->volume); bg_msg_queue_list_send(player->message_queues, msg_volume_changed, &player->volume); break; case BG_PLAYER_CMD_SET_VOLUME_REL: arg_f1 = bg_msg_get_arg_float(command, 0); player->volume += arg_f1; if(player->volume > 1.0) player->volume = 1.0; if(player->volume < BG_PLAYER_VOLUME_MIN) player->volume = BG_PLAYER_VOLUME_MIN; bg_player_oa_set_volume(&player->audio_stream, player->volume); bg_msg_queue_list_send(player->message_queues, msg_volume_changed, &player->volume); break; case BG_PLAYER_CMD_SETSTATE: arg_i1 = bg_msg_get_arg_int(command, 0); switch(arg_i1) { case BG_PLAYER_STATE_EOF: if(player->finish_mode == BG_PLAYER_FINISH_CHANGE) { bg_log(BG_LOG_INFO, LOG_DOMAIN, "Detected EOF"); bg_player_threads_join(player->threads, PLAYER_MAX_THREADS); player_cleanup(player); bg_player_set_state(player, BG_PLAYER_STATE_EOF, NULL, NULL); } else { interrupt_cmd(player, BG_PLAYER_STATE_PAUSED); if(DO_AUDIO(player->flags)) bg_player_oa_stop(&player->audio_stream); if(DO_VIDEO(player->flags)) bg_player_ov_update_still(player); } break; #if 0 case BG_PLAYER_STATE_FINISHING_PAUSE: bg_player_set_state(player, BG_PLAYER_STATE_FINISHING_PAUSE, NULL, NULL); pthread_mutex_lock(&player->stop_mutex); pthread_cond_wait(&player->stop_cond, &player->stop_mutex); pthread_mutex_unlock(&player->stop_mutex); bg_player_time_stop(player); if(DO_AUDIO(player->flags)) bg_player_oa_stop(&player->audio_stream); bg_player_set_state(player, BG_PLAYER_STATE_PAUSED, NULL, NULL); break; #endif case BG_PLAYER_STATE_ERROR: stop_cmd(player, BG_PLAYER_STATE_STOPPED, 0); bg_player_set_state(player, BG_PLAYER_STATE_ERROR, NULL, NULL); } break; case BG_PLAYER_CMD_SET_OA_PLUGIN: arg_ptr1 = bg_msg_get_arg_ptr_nocopy(command, 0); set_oa_plugin_cmd(player, arg_ptr1); break; case BG_PLAYER_CMD_SET_OV_PLUGIN: arg_ptr1 = bg_msg_get_arg_ptr_nocopy(command, 0); set_ov_plugin_cmd(player, arg_ptr1); break; case BG_PLAYER_CMD_SET_AUDIO_STREAM: arg_i1 = bg_msg_get_arg_int(command, 0); set_audio_stream_cmd(player, arg_i1); break; case BG_PLAYER_CMD_SET_VIDEO_STREAM: arg_i1 = bg_msg_get_arg_int(command, 0); set_video_stream_cmd(player, arg_i1); break; case BG_PLAYER_CMD_SET_SUBTITLE_STREAM: arg_i1 = bg_msg_get_arg_int(command, 0); set_subtitle_stream_cmd(player, arg_i1); break; case BG_PLAYER_CMD_PAUSE: pause_cmd(player); break; case BG_PLAYER_CMD_INTERRUPT: /* Interrupt playback and restart */ stream_change_init(player); bg_msg_queue_list_send(player->message_queues, msg_interrupt, &player); bg_msg_queue_unlock_read(player->command_queue); queue_locked = 0; while(1) { command = bg_msg_queue_lock_read(player->command_queue); queue_locked = 1; if(bg_msg_get_id(command) != BG_PLAYER_CMD_INTERRUPT_RESUME) bg_log(BG_LOG_WARNING, LOG_DOMAIN, "Ignoring command while playback is interrupted"); else break; bg_msg_queue_unlock_read(player->command_queue); queue_locked = 0; } stream_change_done(player); bg_msg_queue_list_send(player->message_queues, msg_interrupt_resume, &player); break; case BG_PLAYER_CMD_TOGGLE_MUTE: pthread_mutex_lock(&player->audio_stream.mute_mutex); player->audio_stream.mute = !player->audio_stream.mute; bg_msg_queue_list_send(player->message_queues, msg_mute, &player->audio_stream.mute); pthread_mutex_unlock(&player->audio_stream.mute_mutex); break; } if(queue_locked) bg_msg_queue_unlock_read(player->command_queue); } return 1; } static void * player_thread(void * data) { bg_player_t * player; int old_seconds = -1; int seconds; int do_exit; int state; gavl_time_t time; player = (bg_player_t*)data; bg_player_set_state(player, BG_PLAYER_STATE_STOPPED, NULL, NULL); do_exit = 0; while(1) { /* Process commands */ if(!process_commands(player)) do_exit = 1; if(do_exit) break; if(player->flags & PLAYER_FREEZE_FRAME) bg_player_ov_handle_events(&player->video_stream); if(player->flags & PLAYER_FREEZE_VIS) bg_visualizer_update(player->visualizer, NULL); state = bg_player_get_state(player); switch(state) { case BG_PLAYER_STATE_PLAYING: if(player->time_update_mode == TIME_UPDATE_SECOND) { bg_player_time_get(player, 1, &time); seconds = time / GAVL_TIME_SCALE; if(seconds != old_seconds) { old_seconds = seconds; bg_msg_queue_list_send(player->message_queues, msg_time, &time); } } if(player->track_info->chapter_list && bg_chapter_list_changed(player->track_info->chapter_list, time, &player->current_chapter)) { bg_msg_queue_list_send(player->message_queues, msg_chapter_changed, &player->current_chapter); } break; } gavl_time_delay(&player->wait_time); } return NULL; } void bg_player_broadcast_time(bg_player_t * player, gavl_time_t time) { bg_msg_queue_list_send(player->message_queues, msg_time, &time); } void bg_player_run(bg_player_t * player) { pthread_create(&player->player_thread, NULL, player_thread, player); } void bg_player_quit(bg_player_t *player) { bg_msg_t * msg; msg = bg_msg_queue_lock_write(player->command_queue); bg_msg_set_id(msg, BG_PLAYER_CMD_QUIT); bg_msg_queue_unlock_write(player->command_queue); // pthread_cancel(player->player_thread); pthread_join(player->player_thread, NULL); } gmerlin-1.2.0~dfsg/lib/subprocess.c0000644000175000017500000001404011764363410017177 0ustar alessioalessio/***************************************************************** * gmerlin - a general purpose multimedia framework and applications * * Copyright (c) 2001 - 2011 Members of the Gmerlin project * gmerlin-general@lists.sourceforge.net * http://gmerlin.sourceforge.net * * 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 of the License, 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 this program. If not, see . * *****************************************************************/ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #define READ 0 #define WRITE 1 #define LOG_DOMAIN "subprocess" static int my_close(int * fd) { int result; if(*fd >= 0) { result = close(*fd); *fd = -1; } return result; } typedef struct { int fd[2]; /* fd */ int use; int w; /* 1 if parent writes */ } pipe_t; static int create_pipe(pipe_t * p) { if(pipe(p->fd) == -1) return 0; p->use = 1; return 1; } static int connect_pipe_parent(pipe_t * p) { if(!p->use) return -1; /* Close unused end */ my_close(p->w ? &p->fd[READ] : &p->fd[WRITE]); if(p->w) return p->fd[WRITE]; else return p->fd[READ]; } static void connect_pipe_child(pipe_t * p, int fileno) { if(!p->use) return; /* Close unused end */ my_close(p->w ? &p->fd[WRITE] : &p->fd[READ]); close(fileno); if(p->w) { dup2(p->fd[READ], fileno); my_close(&p->fd[READ]); } else { dup2(p->fd[WRITE], fileno); my_close(&p->fd[WRITE]); } } typedef struct { pid_t pid; pipe_t stdin_fd; pipe_t stdout_fd; pipe_t stderr_fd; } subprocess_priv_t; bg_subprocess_t * bg_subprocess_create(const char * command, int do_stdin, int do_stdout, int do_stderr) { bg_subprocess_t * ret; subprocess_priv_t * ret_priv; pid_t pid; int open_max, i; ret = calloc(1, sizeof(*ret)); ret_priv = calloc(1, sizeof(*ret_priv)); ret->priv = ret_priv; ret_priv->stdin_fd.w = 1; if(do_stdin) create_pipe(&ret_priv->stdin_fd); if(do_stdout) create_pipe(&ret_priv->stdout_fd); if(do_stderr) create_pipe(&ret_priv->stderr_fd); pid = fork(); if(pid == (pid_t) 0) { /* Child */ connect_pipe_child(&ret_priv->stdin_fd, STDIN_FILENO); connect_pipe_child(&ret_priv->stdout_fd, STDOUT_FILENO); connect_pipe_child(&ret_priv->stderr_fd, STDERR_FILENO); /* Close all open filedescriptors from parent */ open_max = sysconf(_SC_OPEN_MAX); for(i = 3; i < open_max; i++) fcntl (i, F_SETFD, FD_CLOEXEC); /* Exec */ execl("/bin/sh", "sh", "-c", command, NULL); /* Never get here */ _exit(1); } else if(pid < 0) { goto fail; } else { /* Parent */ ret->stdin_fd = connect_pipe_parent(&ret_priv->stdin_fd); ret->stdout_fd = connect_pipe_parent(&ret_priv->stdout_fd); ret->stderr_fd = connect_pipe_parent(&ret_priv->stderr_fd); ret_priv->pid = pid; } bg_log(BG_LOG_DEBUG, LOG_DOMAIN, "Created process: %s [%d]", command, pid); return ret; fail: bg_log(BG_LOG_ERROR, LOG_DOMAIN, "Creating process failed: %s", strerror(errno)); free(ret_priv); free(ret); return NULL; } void bg_subprocess_kill(bg_subprocess_t * p, int sig) { subprocess_priv_t * priv = (subprocess_priv_t*)(p->priv); kill(priv->pid, sig); } int bg_subprocess_close(bg_subprocess_t*p) { int status, ret; subprocess_priv_t * priv = (subprocess_priv_t*)(p->priv); if(priv->stdin_fd.use) { my_close(&p->stdin_fd); } /* Some programs might rely on EOF in stdin */ // bg_subprocess_kill(p, SIGHUP); waitpid(priv->pid, &status, 0); ret = WEXITSTATUS(status); bg_log(BG_LOG_DEBUG, LOG_DOMAIN, "Finished process [%d] return value: %d", priv->pid, ret); if(priv->stdout_fd.use) my_close(&p->stdout_fd); if(priv->stderr_fd.use) my_close(&p->stderr_fd); free(priv); free(p); return ret; } int bg_system(const char * command) { bg_subprocess_t * sp = bg_subprocess_create(command, 0, 0, 0); if(!sp) return -1; return bg_subprocess_close(sp); } /* Read line without trailing '\r' or '\n' */ int bg_subprocess_read_line(int fd, char ** ret, int * ret_alloc, int milliseconds) { int bytes_read = 0; char c = 0; fd_set rset; struct timeval timeout; int result; if(milliseconds >= 0) { FD_ZERO (&rset); FD_SET (fd, &rset); timeout.tv_sec = milliseconds / 1000; timeout.tv_usec = (milliseconds % 1000) * 1000; if((result = select (fd+1, &rset, NULL, NULL, &timeout)) <= 0) { return bytes_read; } } while((c != '\n') && (c != '\r')) { if(!read(fd, &c, 1)) { return 0; } if((c != '\n') && (c != '\r')) { if(bytes_read + 2 > *ret_alloc) { *ret_alloc += 256; *ret = realloc(*ret, *ret_alloc); } (*ret)[bytes_read] = c; bytes_read++; } } (*ret)[bytes_read] = '\0'; return 1; } int bg_subprocess_read_data(int fd, uint8_t * ret, int len) { int result; int bytes_read = 0; while(bytes_read < len) { result = read(fd, ret + bytes_read, len - bytes_read); if(result <= 0) return bytes_read; bytes_read += result; } return bytes_read; } gmerlin-1.2.0~dfsg/lib/hexdump.c0000644000175000017500000000326211764363410016465 0ustar alessioalessio/***************************************************************** * gmerlin - a general purpose multimedia framework and applications * * Copyright (c) 2001 - 2011 Members of the Gmerlin project * gmerlin-general@lists.sourceforge.net * http://gmerlin.sourceforge.net * * 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 of the License, 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 this program. If not, see . * *****************************************************************/ #include #include void bg_hexdump(uint8_t * data, int len, int linebreak) { FILE * out = stderr; int i; int bytes_written = 0; int imax; while(bytes_written < len) { imax = (bytes_written + linebreak > len) ? len - bytes_written : linebreak; for(i = 0; i < imax; i++) fprintf(out, "%02x ", data[bytes_written + i]); for(i = imax; i < linebreak; i++) fprintf(out, " "); for(i = 0; i < imax; i++) { if(!(data[bytes_written + i] & 0x80) && (data[bytes_written + i] >= 32)) fprintf(out, "%c", data[bytes_written + i]); else fprintf(out, "."); } bytes_written += imax; fprintf(out, "\n"); } } gmerlin-1.2.0~dfsg/lib/player_video.c0000644000175000017500000002007111764363410017472 0ustar alessioalessio/***************************************************************** * gmerlin - a general purpose multimedia framework and applications * * Copyright (c) 2001 - 2011 Members of the Gmerlin project * gmerlin-general@lists.sourceforge.net * http://gmerlin.sourceforge.net * * 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 of the License, 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 this program. If not, see . * *****************************************************************/ #include #include #include #include #include #define LOG_DOMAIN "player.video" void bg_player_video_create(bg_player_t * p, bg_plugin_registry_t * plugin_reg) { bg_player_video_stream_t * s = &p->video_stream; s->th = bg_player_thread_create(p->thread_common); bg_gavl_video_options_init(&s->options); s->fc = bg_video_filter_chain_create(&s->options, plugin_reg); pthread_mutex_init(&s->config_mutex,NULL); pthread_mutex_init(&s->eof_mutex,NULL); s->ss = &p->subtitle_stream; s->msg_queue = bg_msg_queue_create(); s->accel_map = bg_accelerator_map_create(); s->osd = bg_osd_create(); } void bg_player_video_destroy(bg_player_t * p) { bg_player_video_stream_t * s = &p->video_stream; pthread_mutex_destroy(&s->config_mutex); pthread_mutex_destroy(&s->eof_mutex); bg_gavl_video_options_free(&s->options); bg_video_filter_chain_destroy(s->fc); bg_player_thread_destroy(s->th); bg_msg_queue_destroy(s->msg_queue); bg_osd_destroy(s->osd); bg_accelerator_map_destroy(s->accel_map); } int bg_player_video_init(bg_player_t * player, int video_stream) { bg_player_video_stream_t * s; s = &player->video_stream; s->skip = 0; s->frames_read = 0; if(s->do_still) s->in_func = bg_player_input_read_video_still; else s->in_func = bg_player_input_read_video; s->in_data = player; s->in_stream = player->current_video_stream; if(!DO_VIDEO(player->flags)) return 1; if(!DO_SUBTITLE_ONLY(player->flags)) { bg_player_input_get_video_format(player); bg_video_filter_chain_connect_input(s->fc, s->in_func, s->in_data, s->in_stream); bg_video_filter_chain_init(s->fc, &s->input_format, &s->output_format); s->in_func = bg_video_filter_chain_read; s->in_data = s->fc; s->in_stream = 0; } if(!bg_player_ov_init(&player->video_stream)) return 0; if(!DO_SUBTITLE_ONLY(player->flags)) bg_video_filter_chain_set_out_format(s->fc, &s->output_format); if(DO_SUBTITLE_ONLY(player->flags)) { /* Video output already initialized */ bg_player_ov_set_subtitle_format(&player->video_stream); bg_player_subtitle_init_converter(player); s->in_func = bg_player_input_read_video_subtitle_only; s->in_data = player; s->in_stream = 0; } return 1; } void bg_player_video_cleanup(bg_player_t * player) { } /* Configuration stuff */ static const bg_parameter_info_t parameters[] = { #if 0 { .name = "video", .long_name = TRS("Video"), .type = BG_PARAMETER_SECTION, }, #endif BG_GAVL_PARAM_CONVERSION_QUALITY, BG_GAVL_PARAM_ALPHA, BG_GAVL_PARAM_RESAMPLE_CHROMA, { .name = "still_framerate", .long_name = TRS("Still image framerate"), .type = BG_PARAMETER_FLOAT, .val_min = { .val_f = 1.0 }, .val_max = { .val_f = 100.0 }, .val_default = { .val_f = 10.0 }, .num_digits = 2, .help_string = TRS("Set framerate with which still images will be redisplayed periodically"), }, BG_GAVL_PARAM_THREADS, { /* End of parameters */ } }; const bg_parameter_info_t * bg_player_get_video_parameters(bg_player_t * p) { return parameters; } void bg_player_set_video_parameter(void * data, const char * name, const bg_parameter_value_t * val) { bg_player_t * p = (bg_player_t*)data; int need_restart = 0; int is_interrupted; int do_init; int check_restart; do_init = (bg_player_get_state(p) == BG_PLAYER_STATE_INIT); pthread_mutex_lock(&p->video_stream.config_mutex); is_interrupted = p->video_stream.interrupted; bg_gavl_video_set_parameter(&p->video_stream.options, name, val); if(!do_init && !is_interrupted) check_restart = 1; else check_restart = 0; if(check_restart) need_restart = p->video_stream.options.options_changed; pthread_mutex_unlock(&p->video_stream.config_mutex); if(!need_restart && check_restart) { bg_video_filter_chain_lock(p->video_stream.fc); need_restart = bg_video_filter_chain_need_restart(p->video_stream.fc); bg_video_filter_chain_unlock(p->video_stream.fc); } if(need_restart) { bg_log(BG_LOG_INFO, LOG_DOMAIN, "Restarting playback due to changed video options"); bg_player_interrupt(p); pthread_mutex_lock(&p->video_stream.config_mutex); p->video_stream.interrupted = 1; pthread_mutex_unlock(&p->video_stream.config_mutex); } if(!name && is_interrupted) { bg_player_interrupt_resume(p); pthread_mutex_lock(&p->video_stream.config_mutex); p->video_stream.interrupted = 0; pthread_mutex_unlock(&p->video_stream.config_mutex); } } const bg_parameter_info_t * bg_player_get_video_filter_parameters(bg_player_t * p) { return bg_video_filter_chain_get_parameters(p->video_stream.fc); } void bg_player_set_video_filter_parameter(void * data, const char * name, const bg_parameter_value_t * val) { int need_restart = 0; int is_interrupted; int do_init; bg_player_t * p = (bg_player_t*)data; do_init = (bg_player_get_state(p) == BG_PLAYER_STATE_INIT); pthread_mutex_lock(&p->video_stream.config_mutex); is_interrupted = p->video_stream.interrupted; pthread_mutex_unlock(&p->video_stream.config_mutex); bg_video_filter_chain_lock(p->video_stream.fc); bg_video_filter_chain_set_parameter(p->video_stream.fc, name, val); need_restart = bg_video_filter_chain_need_restart(p->video_stream.fc); bg_video_filter_chain_unlock(p->video_stream.fc); if(!do_init && need_restart && !is_interrupted) { bg_log(BG_LOG_INFO, LOG_DOMAIN, "Restarting playback due to changed video filters"); bg_player_interrupt(p); pthread_mutex_lock(&p->video_stream.config_mutex); p->video_stream.interrupted = 1; pthread_mutex_unlock(&p->video_stream.config_mutex); } if(!name && is_interrupted) { bg_player_interrupt_resume(p); pthread_mutex_lock(&p->video_stream.config_mutex); p->video_stream.interrupted = 0; pthread_mutex_unlock(&p->video_stream.config_mutex); } } int bg_player_read_video(bg_player_t * p, gavl_video_frame_t * frame) { bg_player_video_stream_t * s = &p->video_stream; return s->in_func(s->in_data, frame, s->in_stream); } void bg_player_video_set_eof(bg_player_t * p) { bg_msg_t * msg; bg_log(BG_LOG_INFO, LOG_DOMAIN, "Detected EOF"); pthread_mutex_lock(&p->video_stream.eof_mutex); pthread_mutex_lock(&p->audio_stream.eof_mutex); p->video_stream.eof = 1; if(p->audio_stream.eof) { msg = bg_msg_queue_lock_write(p->command_queue); bg_msg_set_id(msg, BG_PLAYER_CMD_SETSTATE); bg_msg_set_arg_int(msg, 0, BG_PLAYER_STATE_EOF); bg_msg_queue_unlock_write(p->command_queue); } pthread_mutex_unlock(&p->audio_stream.eof_mutex); pthread_mutex_unlock(&p->video_stream.eof_mutex); } gmerlin-1.2.0~dfsg/lib/md5.c0000644000175000017500000003320411764363410015477 0ustar alessioalessio/* Functions to compute MD5 message digest of files or memory blocks. according to the definition of MD5 in RFC 1321 from April 1992. Copyright (C) 1995,1996,1997,1999,2000,2001,2005,2006 Free Software Foundation, Inc. This file is part of the GNU C Library. 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 this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ /* Written by Ulrich Drepper , 1995. */ #include #include "md5.h" #include #include #include #include #if USE_UNLOCKED_IO # include "unlocked-io.h" #endif #ifdef _LIBC # include # if __BYTE_ORDER == __BIG_ENDIAN # define WORDS_BIGENDIAN 1 # endif /* We need to keep the namespace clean so define the MD5 function protected using leading __ . */ # define md5_init_ctx bg_md5_init_ctx # define md5_process_block bg_md5_process_block # define md5_process_bytes bg_md5_process_bytes # define md5_finish_ctx bg_md5_finish_ctx # define md5_read_ctx bg_md5_read_ctx # define md5_stream bg_md5_stream # define md5_buffer bg_md5_buffer #endif #ifdef WORDS_BIGENDIAN # define SWAP(n) \ (((n) << 24) | (((n) & 0xff00) << 8) | (((n) >> 8) & 0xff00) | ((n) >> 24)) #else # define SWAP(n) (n) #endif #define BLOCKSIZE 4096 #if BLOCKSIZE % 64 != 0 # error "invalid BLOCKSIZE" #endif /* This array contains the bytes used to pad the buffer to the next 64-byte boundary. (RFC 1321, 3.1: Step 1) */ static const unsigned char fillbuf[64] = { 0x80, 0 /* , 0, 0, ... */ }; /* Initialize structure containing state of computation. (RFC 1321, 3.3: Step 3) */ void md5_init_ctx (struct md5_ctx *ctx) { ctx->A = 0x67452301; ctx->B = 0xefcdab89; ctx->C = 0x98badcfe; ctx->D = 0x10325476; ctx->total[0] = ctx->total[1] = 0; ctx->buflen = 0; } /* Put result from CTX in first 16 bytes following RESBUF. The result must be in little endian byte order. IMPORTANT: On some systems it is required that RESBUF is correctly aligned for a 32-bit value. */ void * md5_read_ctx (const struct md5_ctx *ctx, void *resbuf) { ((uint32_t *) resbuf)[0] = SWAP (ctx->A); ((uint32_t *) resbuf)[1] = SWAP (ctx->B); ((uint32_t *) resbuf)[2] = SWAP (ctx->C); ((uint32_t *) resbuf)[3] = SWAP (ctx->D); return resbuf; } /* Process the remaining bytes in the internal buffer and the usual prolog according to the standard and write the result to RESBUF. IMPORTANT: On some systems it is required that RESBUF is correctly aligned for a 32-bit value. */ void * md5_finish_ctx (struct md5_ctx *ctx, void *resbuf) { /* Take yet unprocessed bytes into account. */ uint32_t bytes = ctx->buflen; size_t size = (bytes < 56) ? 64 / 4 : 64 * 2 / 4; /* Now count remaining bytes. */ ctx->total[0] += bytes; if (ctx->total[0] < bytes) ++ctx->total[1]; /* Put the 64-bit file length in *bits* at the end of the buffer. */ ctx->buffer[size - 2] = SWAP (ctx->total[0] << 3); ctx->buffer[size - 1] = SWAP ((ctx->total[1] << 3) | (ctx->total[0] >> 29)); memcpy (&((char *) ctx->buffer)[bytes], fillbuf, (size - 2) * 4 - bytes); /* Process last bytes. */ md5_process_block (ctx->buffer, size * 4, ctx); return md5_read_ctx (ctx, resbuf); } /* Compute MD5 message digest for bytes read from STREAM. The resulting message digest number will be written into the 16 bytes beginning at RESBLOCK. */ int md5_stream (FILE *stream, void *resblock) { struct md5_ctx ctx; char buffer[BLOCKSIZE + 72]; size_t sum; /* Initialize the computation context. */ md5_init_ctx (&ctx); /* Iterate over full file contents. */ while (1) { /* We read the file in blocks of BLOCKSIZE bytes. One call of the computation function processes the whole buffer so that with the next round of the loop another block can be read. */ size_t n; sum = 0; /* Read block. Take care for partial reads. */ while (1) { n = fread (buffer + sum, 1, BLOCKSIZE - sum, stream); sum += n; if (sum == BLOCKSIZE) break; if (n == 0) { /* Check for the error flag IFF N == 0, so that we don't exit the loop after a partial read due to e.g., EAGAIN or EWOULDBLOCK. */ if (ferror (stream)) return 1; goto process_partial_block; } /* We've read at least one byte, so ignore errors. But always check for EOF, since feof may be true even though N > 0. Otherwise, we could end up calling fread after EOF. */ if (feof (stream)) goto process_partial_block; } /* Process buffer with BLOCKSIZE bytes. Note that BLOCKSIZE % 64 == 0 */ md5_process_block (buffer, BLOCKSIZE, &ctx); } process_partial_block: /* Process any remaining bytes. */ if (sum > 0) md5_process_bytes (buffer, sum, &ctx); /* Construct result in desired memory. */ md5_finish_ctx (&ctx, resblock); return 0; } /* Compute MD5 message digest for LEN bytes beginning at BUFFER. The result is always in little endian byte order, so that a byte-wise output yields to the wanted ASCII representation of the message digest. */ void * md5_buffer (const char *buffer, size_t len, void *resblock) { struct md5_ctx ctx; /* Initialize the computation context. */ md5_init_ctx (&ctx); /* Process whole buffer but last len % 64 bytes. */ md5_process_bytes (buffer, len, &ctx); /* Put result in desired memory area. */ return md5_finish_ctx (&ctx, resblock); } void md5_process_bytes (const void *buffer, size_t len, struct md5_ctx *ctx) { /* When we already have some bits in our internal buffer concatenate both inputs first. */ if (ctx->buflen != 0) { size_t left_over = ctx->buflen; size_t add = 128 - left_over > len ? len : 128 - left_over; memcpy (&((char *) ctx->buffer)[left_over], buffer, add); ctx->buflen += add; if (ctx->buflen > 64) { md5_process_block (ctx->buffer, ctx->buflen & ~63, ctx); ctx->buflen &= 63; /* The regions in the following copy operation cannot overlap. */ memcpy (ctx->buffer, &((char *) ctx->buffer)[(left_over + add) & ~63], ctx->buflen); } buffer = (const char *) buffer + add; len -= add; } /* Process available complete blocks. */ if (len >= 64) { #if !_STRING_ARCH_unaligned # define alignof(type) offsetof (struct { char c; type x; }, x) # define UNALIGNED_P(p) (((size_t) p) % alignof (uint32_t) != 0) if (UNALIGNED_P (buffer)) while (len > 64) { md5_process_block (memcpy (ctx->buffer, buffer, 64), 64, ctx); buffer = (const char *) buffer + 64; len -= 64; } else #endif { md5_process_block (buffer, len & ~63, ctx); buffer = (const char *) buffer + (len & ~63); len &= 63; } } /* Move remaining bytes in internal buffer. */ if (len > 0) { size_t left_over = ctx->buflen; memcpy (&((char *) ctx->buffer)[left_over], buffer, len); left_over += len; if (left_over >= 64) { md5_process_block (ctx->buffer, 64, ctx); left_over -= 64; memcpy (ctx->buffer, &ctx->buffer[16], left_over); } ctx->buflen = left_over; } } /* These are the four functions used in the four steps of the MD5 algorithm and defined in the RFC 1321. The first function is a little bit optimized (as found in Colin Plumbs public domain implementation). */ /* #define FF(b, c, d) ((b & c) | (~b & d)) */ #define FF(b, c, d) (d ^ (b & (c ^ d))) #define FG(b, c, d) FF (d, b, c) #define FH(b, c, d) (b ^ c ^ d) #define FI(b, c, d) (c ^ (b | ~d)) /* Process LEN bytes of BUFFER, accumulating context into CTX. It is assumed that LEN % 64 == 0. */ void md5_process_block (const void *buffer, size_t len, struct md5_ctx *ctx) { uint32_t correct_words[16]; const uint32_t *words = buffer; size_t nwords = len / sizeof (uint32_t); const uint32_t *endp = words + nwords; uint32_t A = ctx->A; uint32_t B = ctx->B; uint32_t C = ctx->C; uint32_t D = ctx->D; /* First increment the byte count. RFC 1321 specifies the possible length of the file up to 2^64 bits. Here we only compute the number of bytes. Do a double word increment. */ ctx->total[0] += len; if (ctx->total[0] < len) ++ctx->total[1]; /* Process all bytes in the buffer with 64 bytes in each round of the loop. */ while (words < endp) { uint32_t *cwp = correct_words; uint32_t A_save = A; uint32_t B_save = B; uint32_t C_save = C; uint32_t D_save = D; /* First round: using the given function, the context and a constant the next context is computed. Because the algorithms processing unit is a 32-bit word and it is determined to work on words in little endian byte order we perhaps have to change the byte order before the computation. To reduce the work for the next steps we store the swapped words in the array CORRECT_WORDS. */ #define OP(a, b, c, d, s, T) \ do \ { \ a += FF (b, c, d) + (*cwp++ = SWAP (*words)) + T; \ ++words; \ CYCLIC (a, s); \ a += b; \ } \ while (0) /* It is unfortunate that C does not provide an operator for cyclic rotation. Hope the C compiler is smart enough. */ #define CYCLIC(w, s) (w = (w << s) | (w >> (32 - s))) /* Before we start, one word to the strange constants. They are defined in RFC 1321 as T[i] = (int) (4294967296.0 * fabs (sin (i))), i=1..64 Here is an equivalent invocation using Perl: perl -e 'foreach(1..64){printf "0x%08x\n", int (4294967296 * abs (sin $_))}' */ /* Round 1. */ OP (A, B, C, D, 7, 0xd76aa478); OP (D, A, B, C, 12, 0xe8c7b756); OP (C, D, A, B, 17, 0x242070db); OP (B, C, D, A, 22, 0xc1bdceee); OP (A, B, C, D, 7, 0xf57c0faf); OP (D, A, B, C, 12, 0x4787c62a); OP (C, D, A, B, 17, 0xa8304613); OP (B, C, D, A, 22, 0xfd469501); OP (A, B, C, D, 7, 0x698098d8); OP (D, A, B, C, 12, 0x8b44f7af); OP (C, D, A, B, 17, 0xffff5bb1); OP (B, C, D, A, 22, 0x895cd7be); OP (A, B, C, D, 7, 0x6b901122); OP (D, A, B, C, 12, 0xfd987193); OP (C, D, A, B, 17, 0xa679438e); OP (B, C, D, A, 22, 0x49b40821); /* For the second to fourth round we have the possibly swapped words in CORRECT_WORDS. Redefine the macro to take an additional first argument specifying the function to use. */ #undef OP #define OP(f, a, b, c, d, k, s, T) \ do \ { \ a += f (b, c, d) + correct_words[k] + T; \ CYCLIC (a, s); \ a += b; \ } \ while (0) /* Round 2. */ OP (FG, A, B, C, D, 1, 5, 0xf61e2562); OP (FG, D, A, B, C, 6, 9, 0xc040b340); OP (FG, C, D, A, B, 11, 14, 0x265e5a51); OP (FG, B, C, D, A, 0, 20, 0xe9b6c7aa); OP (FG, A, B, C, D, 5, 5, 0xd62f105d); OP (FG, D, A, B, C, 10, 9, 0x02441453); OP (FG, C, D, A, B, 15, 14, 0xd8a1e681); OP (FG, B, C, D, A, 4, 20, 0xe7d3fbc8); OP (FG, A, B, C, D, 9, 5, 0x21e1cde6); OP (FG, D, A, B, C, 14, 9, 0xc33707d6); OP (FG, C, D, A, B, 3, 14, 0xf4d50d87); OP (FG, B, C, D, A, 8, 20, 0x455a14ed); OP (FG, A, B, C, D, 13, 5, 0xa9e3e905); OP (FG, D, A, B, C, 2, 9, 0xfcefa3f8); OP (FG, C, D, A, B, 7, 14, 0x676f02d9); OP (FG, B, C, D, A, 12, 20, 0x8d2a4c8a); /* Round 3. */ OP (FH, A, B, C, D, 5, 4, 0xfffa3942); OP (FH, D, A, B, C, 8, 11, 0x8771f681); OP (FH, C, D, A, B, 11, 16, 0x6d9d6122); OP (FH, B, C, D, A, 14, 23, 0xfde5380c); OP (FH, A, B, C, D, 1, 4, 0xa4beea44); OP (FH, D, A, B, C, 4, 11, 0x4bdecfa9); OP (FH, C, D, A, B, 7, 16, 0xf6bb4b60); OP (FH, B, C, D, A, 10, 23, 0xbebfbc70); OP (FH, A, B, C, D, 13, 4, 0x289b7ec6); OP (FH, D, A, B, C, 0, 11, 0xeaa127fa); OP (FH, C, D, A, B, 3, 16, 0xd4ef3085); OP (FH, B, C, D, A, 6, 23, 0x04881d05); OP (FH, A, B, C, D, 9, 4, 0xd9d4d039); OP (FH, D, A, B, C, 12, 11, 0xe6db99e5); OP (FH, C, D, A, B, 15, 16, 0x1fa27cf8); OP (FH, B, C, D, A, 2, 23, 0xc4ac5665); /* Round 4. */ OP (FI, A, B, C, D, 0, 6, 0xf4292244); OP (FI, D, A, B, C, 7, 10, 0x432aff97); OP (FI, C, D, A, B, 14, 15, 0xab9423a7); OP (FI, B, C, D, A, 5, 21, 0xfc93a039); OP (FI, A, B, C, D, 12, 6, 0x655b59c3); OP (FI, D, A, B, C, 3, 10, 0x8f0ccc92); OP (FI, C, D, A, B, 10, 15, 0xffeff47d); OP (FI, B, C, D, A, 1, 21, 0x85845dd1); OP (FI, A, B, C, D, 8, 6, 0x6fa87e4f); OP (FI, D, A, B, C, 15, 10, 0xfe2ce6e0); OP (FI, C, D, A, B, 6, 15, 0xa3014314); OP (FI, B, C, D, A, 13, 21, 0x4e0811a1); OP (FI, A, B, C, D, 4, 6, 0xf7537e82); OP (FI, D, A, B, C, 11, 10, 0xbd3af235); OP (FI, C, D, A, B, 2, 15, 0x2ad7d2bb); OP (FI, B, C, D, A, 9, 21, 0xeb86d391); /* Add the starting values of the context. */ A += A_save; B += B_save; C += C_save; D += D_save; } /* Put checksum in context given as argument. */ ctx->A = A; ctx->B = B; ctx->C = C; ctx->D = D; } gmerlin-1.2.0~dfsg/lib/player_input.c0000644000175000017500000004156411764363410017535 0ustar alessioalessio/***************************************************************** * gmerlin - a general purpose multimedia framework and applications * * Copyright (c) 2001 - 2011 Members of the Gmerlin project * gmerlin-general@lists.sourceforge.net * http://gmerlin.sourceforge.net * * 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 of the License, 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 this program. If not, see . * *****************************************************************/ #include #include #include #include #include #include #define LOG_DOMAIN "player.input" // #define DUMP_TIMESTAMPS #define DEBUG_COUNTER #if 0 struct bg_player_input_context_s { /* Plugin stuff */ int audio_finished; int video_finished; int subtitle_finished; int send_silence; int64_t audio_samples_written; int64_t video_frames_written; #ifdef DEBUG_COUNTER int64_t audio_sample_counter; int64_t video_frame_counter; #endif // int has_first_audio_timestamp; /* Internal times */ gavl_time_t audio_time; gavl_time_t video_time; /* For changing global stuff */ bg_player_t * player; }; #endif void bg_player_input_create(bg_player_t * player) { } void bg_player_input_destroy(bg_player_t * player) { if(player->input_handle) bg_plugin_unref(player->input_handle); } void bg_player_input_select_streams(bg_player_t * p) { int i, vis_enable; bg_player_audio_stream_t * as = &p->audio_stream; bg_player_video_stream_t * vs = &p->video_stream; bg_player_subtitle_stream_t * ss = &p->subtitle_stream; vs->do_still = 0; if(vs->still_frame_in) { gavl_video_frame_destroy(vs->still_frame_in); vs->still_frame_in = NULL; } /* Adjust stream indices */ if(p->current_audio_stream >= p->track_info->num_audio_streams) p->current_audio_stream = 0; if(p->current_video_stream >= p->track_info->num_video_streams) p->current_video_stream = 0; if(p->current_subtitle_stream >= p->track_info->num_subtitle_streams) p->current_subtitle_stream = 0; if(!p->audio_stream.plugin_handle) p->current_audio_stream = -1; if(!p->video_stream.ov) { p->current_video_stream = -1; p->current_subtitle_stream = -1; } /* Check if the streams are actually there */ p->flags &= 0xFFFF0000; as->eof = 1; vs->eof = 1; ss->eof = 1; if((p->current_audio_stream >= 0) && (p->current_audio_stream < p->track_info->num_audio_streams)) { as->eof = 0; p->flags |= PLAYER_DO_AUDIO; } if((p->current_video_stream >= 0) && (p->current_video_stream < p->track_info->num_video_streams)) { vs->eof = 0; p->flags |= PLAYER_DO_VIDEO; } if((p->current_subtitle_stream >= 0) && (p->current_subtitle_stream < p->track_info->num_subtitle_streams)) { p->flags |= PLAYER_DO_SUBTITLE; ss->eof = 0; } pthread_mutex_lock(&p->config_mutex); vis_enable = p->visualizer_enabled; pthread_mutex_unlock(&p->config_mutex); if(DO_AUDIO(p->flags) && !DO_VIDEO(p->flags) && !DO_SUBTITLE(p->flags) && vis_enable) { p->flags |= PLAYER_DO_VISUALIZE; } else if(!DO_VIDEO(p->flags) && DO_SUBTITLE(p->flags)) { p->flags |= PLAYER_DO_VIDEO; vs->eof = 0; p->flags |= PLAYER_DO_SUBTITLE_ONLY; pthread_mutex_lock(&p->video_stream.config_mutex); /* Get background color */ gavl_video_options_get_background_color(p->video_stream.options.opt, vs->bg_color); pthread_mutex_unlock(&p->video_stream.config_mutex); vs->bg_color[3] = 1.0; } /* En-/Disable streams at the input plugin */ if(p->input_plugin->set_audio_stream) { for(i = 0; i < p->track_info->num_audio_streams; i++) { if(i == p->current_audio_stream) p->input_plugin->set_audio_stream(p->input_priv, i, BG_STREAM_ACTION_DECODE); else p->input_plugin->set_audio_stream(p->input_priv, i, BG_STREAM_ACTION_OFF); } } if(p->input_plugin->set_video_stream) { for(i = 0; i < p->track_info->num_video_streams; i++) { if(i == p->current_video_stream) p->input_plugin->set_video_stream(p->input_priv, i, BG_STREAM_ACTION_DECODE); else p->input_plugin->set_video_stream(p->input_priv, i, BG_STREAM_ACTION_OFF); } } if(p->input_plugin->set_subtitle_stream) { for(i = 0; i < p->track_info->num_subtitle_streams; i++) { if(i == p->current_subtitle_stream) p->input_plugin->set_subtitle_stream(p->input_priv, i, BG_STREAM_ACTION_DECODE); else p->input_plugin->set_subtitle_stream(p->input_priv, i, BG_STREAM_ACTION_OFF); } } } int bg_player_input_start(bg_player_t * p) { gavl_video_format_t * video_format; /* Start input plugin, so we get the formats */ if(p->input_plugin->start) { if(!p->input_plugin->start(p->input_priv)) { bg_log(BG_LOG_ERROR, LOG_DOMAIN, "Starting input plugin failed"); if(p->input_handle) bg_plugin_unref(p->input_handle); p->input_handle = NULL; p->input_plugin = NULL; return 0; } } /* Subtitle type must be set here, because it's unknown before the start() call */ if(DO_SUBTITLE(p->flags)) { if(p->track_info->subtitle_streams[p->current_subtitle_stream].is_text) p->flags |= PLAYER_DO_SUBTITLE_TEXT; else p->flags |= PLAYER_DO_SUBTITLE_OVERLAY; } /* Check for still image mode */ if(p->flags & PLAYER_DO_VIDEO) { video_format = &p->track_info->video_streams[p->current_video_stream].format; if(video_format->framerate_mode == GAVL_FRAMERATE_STILL) p->video_stream.do_still = 1; } p->audio_stream.has_first_timestamp_i = 0; return 1; } void bg_player_input_stop(bg_player_t * p) { if(p->input_plugin->stop) p->input_plugin->stop(p->input_priv); } int bg_player_input_set_track(bg_player_t * p) { if(p->input_plugin->set_track) { if(!p->input_plugin->set_track(p->input_priv, p->current_track)) { bg_log(BG_LOG_ERROR, LOG_DOMAIN, "Cannot select track, skipping"); return 0; } } return 1; } int bg_player_input_init(bg_player_t * p, bg_plugin_handle_t * handle, int track_index) { p->input_handle = handle; p->current_track = track_index; p->input_plugin = (bg_input_plugin_t*)(handle->plugin); p->input_priv = handle->priv; if(p->input_plugin->set_callbacks) { p->input_plugin->set_callbacks(p->input_priv, &p->input_callbacks); } p->track_info = p->input_plugin->get_track_info(p->input_priv, track_index); if(p->input_plugin->seek && (p->track_info->flags & BG_TRACK_SEEKABLE) && (p->track_info->duration > 0)) p->can_seek = 1; else p->can_seek = 0; if(p->track_info->flags & BG_TRACK_PAUSABLE) p->can_pause = 1; else p->can_pause = 0; if(!p->track_info->num_audio_streams && !p->track_info->num_video_streams) { bg_log(BG_LOG_ERROR, LOG_DOMAIN, "Track has neither audio nor video, skipping"); return 0; } /* Set the track if neccesary */ if(!bg_player_input_set_track(p)) return 0; /* Select streams */ bg_player_input_select_streams(p); /* Start input plugin, so we get the formats */ if(!bg_player_input_start(p)) { return 0; } return 1; } void bg_player_input_cleanup(bg_player_t * p) { #ifdef DEBUG_COUNTER char tmp_string[128]; #endif bg_player_input_stop(p); if(p->input_handle) bg_plugin_unref(p->input_handle); p->input_handle = NULL; p->input_plugin = NULL; if(p->video_stream.still_frame_in) { gavl_video_frame_destroy(p->video_stream.still_frame_in); p->video_stream.still_frame_in = NULL; } #ifdef DEBUG_COUNTER sprintf(tmp_string, "%" PRId64, p->audio_stream.samples_read); bg_log(BG_LOG_DEBUG, LOG_DOMAIN, "Audio sample counter: %s", tmp_string); sprintf(tmp_string, "%" PRId64, p->video_stream.frames_read); bg_log(BG_LOG_DEBUG, LOG_DOMAIN, "Video frame counter: %s", tmp_string); #endif } int bg_player_input_get_audio_format(bg_player_t * p) { gavl_audio_format_copy(&p->audio_stream.input_format, &p->track_info->audio_streams[p->current_audio_stream].format); return 1; } int bg_player_input_get_video_format(bg_player_t * p) { gavl_video_format_copy(&p->video_stream.input_format, &p->track_info->video_streams[p->current_video_stream].format); if(p->video_stream.do_still) { p->video_stream.input_format.timescale = GAVL_TIME_SCALE; pthread_mutex_lock(&p->config_mutex); p->video_stream.input_format.frame_duration = (int)((float)GAVL_TIME_SCALE / p->still_framerate); pthread_mutex_unlock(&p->config_mutex); } return 1; } int bg_player_input_get_subtitle_format(bg_player_t * p) { gavl_video_format_copy(&p->subtitle_stream.input_format, &p->track_info->subtitle_streams[p->current_subtitle_stream].format); return 1; } int bg_player_input_read_audio(void * priv, gavl_audio_frame_t * frame, int stream, int samples) { int result; bg_player_t * p = priv; bg_player_audio_stream_t * as = &p->audio_stream; bg_plugin_lock(p->input_handle); result = p->input_plugin->read_audio(p->input_priv, frame, stream, samples); bg_plugin_unlock(p->input_handle); if(!as->has_first_timestamp_i) { as->samples_read = frame->timestamp; as->has_first_timestamp_i = 1; } as->samples_read += frame->valid_samples; return result; } int bg_player_input_read_video_still(void * priv, gavl_video_frame_t * frame, int stream) { int result; bg_player_t * p = priv; bg_player_video_stream_t * vs = &p->video_stream; gavl_video_format_t * format; format = &vs->input_format; if(!vs->still_frame_in) { vs->still_frame_in = gavl_video_frame_create(&vs->input_format); vs->still_frame_in->timestamp = 0; } bg_plugin_lock(p->input_handle); if(p->input_plugin->has_still(p->input_priv, stream)) result = p->input_plugin->read_video(p->input_priv, frame, stream); else result = 0; bg_plugin_unlock(p->input_handle); if(result) gavl_video_frame_copy(&vs->input_format, vs->still_frame_in, frame); else { if(!DO_AUDIO(p->flags) && (p->track_info->duration != GAVL_TIME_UNDEFINED) && gavl_time_unscale(vs->input_format.timescale, vs->still_frame_in->timestamp) > p->track_info->duration) result = 0; else { gavl_video_frame_copy(&vs->input_format, frame, vs->still_frame_in); frame->timestamp = vs->still_frame_in->timestamp; result = 1; } } vs->still_frame_in->timestamp += vs->input_format.frame_duration; #ifdef DUMP_TIMESTAMPS bg_debug("Input timestamp: %"PRId64" (timescale: %d)\n", gavl_time_unscale(vs->input_format.timescale, frame->timestamp), vs->input_format.timescale); #endif return result; } int bg_player_input_read_video(void * priv, gavl_video_frame_t * frame, int stream) { int result; bg_player_t * p = priv; bg_player_video_stream_t * vs = &p->video_stream; bg_plugin_lock(p->input_handle); /* Skip */ if(vs->skip && p->input_plugin->skip_video) { gavl_time_t skip_time = vs->frame_time + vs->skip; p->input_plugin->skip_video(p->input_priv, stream, &skip_time, GAVL_TIME_SCALE, 0); } result = p->input_plugin->read_video(p->input_priv, frame, stream); bg_plugin_unlock(p->input_handle); #ifdef DUMP_TIMESTAMPS bg_debug("Input timestamp: %"PRId64"\n", gavl_time_unscale(vs->input_format.timescale, frame->timestamp)); #endif p->video_stream.frames_read++; // if(!result) // fprintf(stderr, "Read video failed\n"); return result; } int bg_player_input_read_video_subtitle_only(void * priv, gavl_video_frame_t * frame, int stream) { bg_player_t * p = priv; bg_player_video_stream_t * vs = &p->video_stream; gavl_video_frame_fill(frame, &vs->output_format, vs->bg_color); frame->timestamp = (int64_t)vs->frames_read * vs->output_format.frame_duration; return 1; } void bg_player_input_seek(bg_player_t * p, gavl_time_t * time, int scale) { int do_audio, do_video, do_subtitle; bg_player_audio_stream_t * as; bg_player_video_stream_t * vs; bg_player_subtitle_stream_t * ss; as = &p->audio_stream; vs = &p->video_stream; ss = &p->subtitle_stream; bg_plugin_lock(p->input_handle); p->input_plugin->seek(p->input_priv, time, scale); bg_plugin_unlock(p->input_handle); as->samples_read = gavl_time_to_samples(as->input_format.samplerate, *time); // This wasn't set before if we switch streams or replug filters as->has_first_timestamp_i = 1; if(DO_SUBTITLE_ONLY(p->flags)) vs->frames_read = gavl_time_to_frames(vs->output_format.timescale, vs->output_format.frame_duration, *time); else { vs->frames_written = gavl_time_to_frames(vs->input_format.timescale, vs->input_format.frame_duration, *time); if(vs->still_frame_in) vs->still_frame_in->timestamp = gavl_time_scale(vs->input_format.timescale, *time); } // Clear EOF states do_audio = DO_AUDIO(p->flags); do_video = DO_VIDEO(p->flags); do_subtitle = DO_SUBTITLE(p->flags); // fprintf(stderr, "Seek, do video: %d\n", do_video); ss->eof = !do_subtitle; as->eof = !do_audio; vs->eof = !do_video; as->send_silence = 0; vs->skip = 0; } /* Configuration stuff */ static const bg_parameter_info_t parameters[] = { { .name = "still_framerate", .long_name = "Still image repitition rate", .type = BG_PARAMETER_FLOAT, .val_default = { .val_f = 10.0 }, .val_min = { .val_f = 0.5 }, .val_max = { .val_f = 100.0 }, .help_string = TRS("When showing still images, gmerlin repeats them periodically to make realtime filter tweaking work."), }, { .name = "sync_offset", .long_name = "Sync offset [ms]", .type = BG_PARAMETER_SLIDER_INT, .flags = BG_PARAMETER_SYNC, .val_default = { .val_i = 0 }, .val_min = { .val_i = -1000 }, .val_max = { .val_i = 1000 }, .help_string = TRS("Use this for playing buggy files, which have a constant offset between audio and video. Use positive values if the video is ahead of audio"), }, { /* End of parameters */ } }; const bg_parameter_info_t * bg_player_get_input_parameters(bg_player_t * p) { return parameters; } void bg_player_set_input_parameter(void * data, const char * name, const bg_parameter_value_t * val) { bg_player_t * player = (bg_player_t*)data; if(!name) return; pthread_mutex_lock(&player->config_mutex); if(!strcmp(name, "still_framerate")) player->still_framerate = val->val_f; else if(!strcmp(name, "sync_offset")) player->sync_offset = gavl_time_unscale(1000, val->val_i); pthread_mutex_unlock(&player->config_mutex); } struct msg_input_data { bg_plugin_handle_t * handle; int track; }; static void msg_input(bg_msg_t * msg, const void * data) { struct msg_input_data * d = (struct msg_input_data *)data; bg_msg_set_id(msg, BG_PLAYER_MSG_INPUT); if(d->handle) { bg_msg_set_arg_string(msg, 0, d->handle->plugin->long_name); bg_msg_set_arg_string(msg, 1, d->handle->location); bg_msg_set_arg_int(msg, 2, d->track); } } void bg_player_input_send_messages(bg_player_t * p) { struct msg_input_data d; d.handle = p->input_handle; d.track = p->current_track; bg_msg_queue_list_send(p->message_queues, msg_input, &d); } gmerlin-1.2.0~dfsg/lib/uthread_sem.c0000644000175000017500000001217611764363410017317 0ustar alessioalessio/* * $Id: uthread_sem.c,v 1.2 2010-09-02 13:07:13 gmerlin Exp $ * * Copyright (C) 2000 Jason Evans . * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice(s), this list of conditions and the following disclaimer as * the first lines of this file unmodified other than the possible * addition of one or more copyright notices. * 2. Redistributions in binary form must reproduce the above copyright * notice(s), this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) ``AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * $FreeBSD: src/lib/libc_r/uthread/uthread_sem.c,v 1.3.2.1 2000/07/18 02:05:57 jasone Exp $ */ #include #include #include #include #include // #include "pthread_private.h" #define _SEM_CHECK_VALIDITY(sem) \ if ((*(sem))->magic != SEM_MAGIC) { \ errno = EINVAL; \ retval = -1; \ goto RETURN; \ } int sem_init(sem_t *sem, int pshared, unsigned int value) { int retval; // if (!THREAD_SAFE()) // THREAD_INIT(); /* * Range check the arguments. */ if (pshared != 0) { /* * The user wants a semaphore that can be shared among * processes, which this implementation can't do. Sounds like a * permissions problem to me (yeah right). */ errno = EPERM; retval = -1; goto RETURN; } if (value > SEM_VALUE_MAX) { errno = EINVAL; retval = -1; goto RETURN; } *sem = (sem_t)malloc(sizeof(struct sem)); if (*sem == NULL) { errno = ENOSPC; retval = -1; goto RETURN; } /* * Initialize the semaphore. */ if (pthread_mutex_init(&(*sem)->lock, NULL) != 0) { free(*sem); errno = ENOSPC; retval = -1; goto RETURN; } if (pthread_cond_init(&(*sem)->gtzero, NULL) != 0) { pthread_mutex_destroy(&(*sem)->lock); free(*sem); errno = ENOSPC; retval = -1; goto RETURN; } (*sem)->count = (u_int32_t)value; (*sem)->nwaiters = 0; (*sem)->magic = SEM_MAGIC; retval = 0; RETURN: return retval; } int sem_destroy(sem_t *sem) { int retval; _SEM_CHECK_VALIDITY(sem); /* Make sure there are no waiters. */ pthread_mutex_lock(&(*sem)->lock); if ((*sem)->nwaiters > 0) { pthread_mutex_unlock(&(*sem)->lock); errno = EBUSY; retval = -1; goto RETURN; } pthread_mutex_unlock(&(*sem)->lock); pthread_mutex_destroy(&(*sem)->lock); pthread_cond_destroy(&(*sem)->gtzero); (*sem)->magic = 0; free(*sem); retval = 0; RETURN: return retval; } sem_t * sem_open(const char *name, int oflag, ...) { errno = ENOSYS; return SEM_FAILED; } int sem_close(sem_t *sem) { errno = ENOSYS; return -1; } int sem_unlink(const char *name) { errno = ENOSYS; return -1; } int sem_wait(sem_t *sem) { int retval; pthread_testcancel(); _SEM_CHECK_VALIDITY(sem); pthread_mutex_lock(&(*sem)->lock); while ((*sem)->count == 0) { (*sem)->nwaiters++; pthread_cond_wait(&(*sem)->gtzero, &(*sem)->lock); (*sem)->nwaiters--; } (*sem)->count--; pthread_mutex_unlock(&(*sem)->lock); retval = 0; RETURN: pthread_testcancel(); return retval; } int sem_trywait(sem_t *sem) { int retval; _SEM_CHECK_VALIDITY(sem); pthread_mutex_lock(&(*sem)->lock); if ((*sem)->count > 0) { (*sem)->count--; retval = 0; } else { errno = EAGAIN; retval = -1; } pthread_mutex_unlock(&(*sem)->lock); RETURN: return retval; } int sem_post(sem_t *sem) { int retval; _SEM_CHECK_VALIDITY(sem); pthread_mutex_lock(&(*sem)->lock); (*sem)->count++; if ((*sem)->nwaiters > 0) { /* * We must use pthread_cond_broadcast() rather than * pthread_cond_signal() in order to assure that the highest * priority thread is run by the scheduler, since * pthread_cond_signal() signals waiting threads in FIFO order. */ pthread_cond_broadcast(&(*sem)->gtzero); } pthread_mutex_unlock(&(*sem)->lock); retval = 0; RETURN: return retval; } int sem_getvalue(sem_t *sem, int *sval) { int retval; _SEM_CHECK_VALIDITY(sem); pthread_mutex_lock(&(*sem)->lock); *sval = (int)(*sem)->count; pthread_mutex_unlock(&(*sem)->lock); retval = 0; RETURN: return retval; } gmerlin-1.2.0~dfsg/Makefile.am0000644000175000017500000000067411764363414016145 0ustar alessioalessio# aclocal Path ACLOCAL_AMFLAGS = -I m4 if HAVE_GTK gtk_pc = gmerlin-gtk.pc else gtk_pc = endif SUBDIRS = po lib plugins tests apps icons skins include doc m4 utils osd pkgconfigdir = $(libdir)/pkgconfig pkgconfig_DATA = gmerlin.pc $(gtk_pc) pkgdatadir = $(datadir)/gmerlin/ pkgdata_DATA = plugin.sym dist_pkgdata_DATA = plugin.sym EXTRA_DIST= config.rpath gmerlin.spec.in gmerlin.pc.in autogen.sh cvs_clean.sh cpuinfo.sh make_potfiles gmerlin-1.2.0~dfsg/gmerlin.spec.in0000644000175000017500000002551211764363414017025 0ustar alessioalessioSummary: Base library for gmerlin applications Name: gmerlin-lib Version: @VERSION@ Release: 1 License: GPL Group: Applications/Multimedia Group(de): Anwendungen/Multimedia Source0: gmerlin-%{version}.tar.gz URL: http://gmerlin.sourceforge.net/ BuildRequires: autoconf BuildRequires: automake BuildRequires: gtk2-devel BuildRequires: libxml2-devel >= @XML2_REQUIRED@ BuildRequires: libjpeg-devel >= @JPEG_REQUIRED@ BuildRequires: alsa-lib-devel >= @ALSA_REQUIRED@ BuildRequires: esound >= @ESD_REQUIRED@ BuildRequires: gavl-devel = @GAVL_REQUIRED@ BuildRequires: libpng-devel >= @PNG_REQUIRED@ BuildRequires: libquicktime-devel = @LQT_REQUIRED@ BuildRequires: libmusicbrainz-devel >= @MUSICBRAINZ_REQUIRED@ BuildRequires: libtiff-devel >= @TIFF_REQUIRED@ Requires: libxml2 >= @XML2_REQUIRED@ Requires: gavl = @GAVL_REQUIRED@ BuildRoot: /tmp/gmerlin-build %description Base library for gmerlin applications # # gmerlin-lib-devel # %package devel Summary: Header files for compiling gmerlin applications and plugins Group: Development/Libraries Group(de): Entwicklung/Libraries Group(es): Desarrollo/Bibliotecas Group(fr): Development/Librairies Group(pl): Programowanie/Biblioteki Group(pt_BR): Desenvolvimento/Bibliotecas Group(ru): / Group(uk): /̦ Requires: gavl-devel = @GAVL_REQUIRED@ Requires: %{name} = %{version} %description devel Header files for compiling gmerlin applications and plugins # # gmerlin-gtk # %package -n gmerlin-gtk Summary: Gtk support library for gmerlin Group: Development/Libraries Requires: gtk2 >= @GTK_REQUIRED@ Requires: gmerlin-lib = %{version} %description -n gmerlin-gtk Gtk support library for gmerlin # # gmerlin-gtk-devel # %package -n gmerlin-gtk-devel Summary: Header files for compiling gmerlin gtk applications Group: Development/Libraries Requires: gtk2-devel >= @GTK_REQUIRED@ Requires: gmerlin-lib-devel = %{version} %description -n gmerlin-gtk-devel Header files for compiling gmerlin gtk applications # # Libquicktime # %package -n gmerlin-lqt Summary: Libquicktime plugins for gmerlin Group: Applications/Multimedia Requires: gmerlin-lib = %{version} Provides: gmerlin-input-plugin Requires: libquicktime = @LQT_REQUIRED@ %description -n gmerlin-lqt Libquicktime plugins for gmerlin (see http://libquicktime.sf.net) # # Alsa # %package -n gmerlin-alsa Summary: Alsa plugins for gmerlin Group: Applications/Multimedia Requires: gmerlin-lib = %{version} Requires: alsa-lib >= @ALSA_REQUIRED@ Provides: gmerlin-soundcard-plugin %description -n gmerlin-alsa Alsa plugins for gmerlin (see http://alsa-project.org) # # Jpeg # %package -n gmerlin-jpeg Summary: Jpeg plugins for gmerlin Group: Applications/Multimedia Requires: gmerlin-lib = %{version} Requires: libjpeg >= @JPEG_REQUIRED@ Provides: gmerlin-image-reader-plugin Provides: gmerlin-image-writer-plugin %description -n gmerlin-jpeg Jpeg plugins for gmerlin # # PNG # %package -n gmerlin-png Summary: png plugins for gmerlin Group: Applications/Multimedia Requires: gmerlin-lib = %{version} Requires: libpng >= @PNG_REQUIRED@ Provides: gmerlin-image-reader-plugin Provides: gmerlin-image-writer-plugin %description -n gmerlin-png PNG plugins for gmerlin # # TIFF # %package -n gmerlin-tiff Summary: tiff plugins for gmerlin Group: Applications/Multimedia Requires: gmerlin-lib = %{version} Requires: libtiff >= @TIFF_REQUIRED@ Provides: gmerlin-image-reader-plugin Provides: gmerlin-image-writer-plugin %description -n gmerlin-tiff TIFF plugins for gmerlin # # OSS # %package -n gmerlin-oss Summary: OSS plugins for gmerlin Group: Applications/Multimedia Requires: gmerlin-lib = %{version} Provides: gmerlin-soundcard-plugin %description -n gmerlin-oss OSS plugins for gmerlin # # ESD # %package -n gmerlin-esd Summary: esd plugins for gmerlin Group: Applications/Multimedia Requires: gmerlin-lib = %{version} Requires: esound >= @ESD_REQUIRED@ Provides: gmerlin-soundcard-plugin %description -n gmerlin-esd esd plugins for gmerlin # # X11 # %package -n gmerlin-x11 Summary: X11 plugins for gmerlin Group: Applications/Multimedia Requires: gmerlin-lib = %{version} Provides: gmerlin-video-playback-plugin %description -n gmerlin-x11 X11 plugins for gmerlin # # V4l # %package -n gmerlin-v4l Summary: Video4linux plugin for gmerlin Group: Applications/Multimedia Requires: gmerlin-lib = %{version} Provides: gmerlin-video-recorder-plugin %description -n gmerlin-v4l Video4linux plugin for gmerlin # # cdaudio # %package -n gmerlin-cdaudio Summary: Audio CD playing/ripping plugin for gmerlin Group: Applications/Multimedia Requires: gmerlin-lib = %{version} Requires: libmusicbrainz >= @MUSICBRAINZ_REQUIRED@ %description -n gmerlin-cdaudio Audio CD playing/ripping plugin for gmerlin # # Applications: Player # %package -n gmerlin-player Summary: Multiformat media player Group: Applications/Multimedia Requires: gmerlin-gtk = %{version} Requires: gmerlin-soundcard-plugin Requires: gmerlin-video-playback-plugin %description -n gmerlin-player Multiformat media player # # Applications: Alsamixer # %package -n gmerlin-alsamixer Summary: Alsa mixer Group: Applications/Multimedia Requires: gmerlin-gtk = %{version} %description -n gmerlin-alsamixer Alsa mixer # # Applications: Transcoder # %package -n gmerlin-transcoder Summary: Audio/Video transcoder Group: Applications/Multimedia Requires: gmerlin-gtk = %{version} %description -n gmerlin-transcoder Audio/Video transcoder # # Applications: Camelot # %package -n gmerlin-camelot Summary: Webcam application Group: Applications/Multimedia Requires: gmerlin-gtk = %{version} Requires: gmerlin-x11 = %{version} Requires: gmerlin-v4l = %{version} Requires: gmerlin-video-playback-plugin Requires: gmerlin-video-recorder-plugin Requires: gmerlin-image-writer-plugin %description -n gmerlin-camelot Webcam application # # Utilities # %package -n gmerlin-utils Summary: Utilities for gmerlin Group: Applications/Multimedia Requires: gmerlin-gtk = %{version} %description -n gmerlin-utils Gmerlin Utilities %prep %setup -n gmerlin-%{version} %build ./cvs_clean.sh ./autogen.sh %configure %{__make} %install rm -rf $RPM_BUILD_ROOT %{__make} install DESTDIR=$RPM_BUILD_ROOT gzip -9nf README %clean rm -rf $RPM_BUILD_ROOT %post -p /sbin/ldconfig %postun -p /sbin/ldconfig %files %defattr(644,root,root) %doc README.gz %attr(644,root,root) %{_libdir}/libgmerlin.la %attr(755,root,root) %{_libdir}/libgmerlin.so* %attr(755,root,root) %dir %{_datadir}/gmerlin %attr(755,root,root) %dir %{_datadir}/gmerlin/icons %attr(755,root,root) %dir %{_libdir}/gmerlin/ %attr(755,root,root) %dir %{_libdir}/gmerlin/plugins %attr(644,root,root) %{_datadir}/gmerlin/icons/*_16.png %attr(644,root,root) %{_datadir}/gmerlin/icons/digit_*.png %attr(644,root,root) %{_datadir}/gmerlin/icons/display_mode_*.png %attr(644,root,root) %{_datadir}/gmerlin/icons/repeat_mode_*.png %attr(644,root,root) %{_datadir}/gmerlin/icons/state_*.png %attr(644,root,root) %{_datadir}/gmerlin/icons/gmerlin.jpg %attr(644,root,root) %{_datadir}/gmerlin/icons/tracks_dnd_32.png %attr(644,root,root) %{_datadir}/gmerlin/icons/tab_close.png %attr(644,root,root) %{_libdir}/gmerlin/plugins/e_wav.la %attr(755,root,root) %{_libdir}/gmerlin/plugins/e_wav.so %attr(644,root,root) %{_libdir}/gmerlin/plugins/*_tga.la %attr(755,root,root) %{_libdir}/gmerlin/plugins/*_tga.so %files devel %attr(755,root,root) %dir %{_includedir}/gmerlin %defattr(644,root,root) %{_includedir}/gmerlin/*.h %{_libdir}/pkgconfig/gmerlin.pc %files -n gmerlin-gtk %defattr(644,root,root) %attr(644,root,root) %{_libdir}/libgmerlin_gtk.la %attr(755,root,root) %{_libdir}/libgmerlin_gtk.so* %{_includedir}/gmerlin %files -n gmerlin-gtk-devel %defattr(644,root,root) %attr(644,root,root) %{_includedir}/gmerlin/gui_gtk/*.h %{_libdir}/pkgconfig/gmerlin-gtk.pc %files -n gmerlin-lqt %attr(644,root,root) %{_libdir}/gmerlin/plugins/*lqt*.la %attr(755,root,root) %{_libdir}/gmerlin/plugins/*lqt*.so %files -n gmerlin-oss %attr(644,root,root) %{_libdir}/gmerlin/plugins/*oss*.la %attr(755,root,root) %{_libdir}/gmerlin/plugins/*oss*.so %files -n gmerlin-alsa %attr(644,root,root) %{_libdir}/gmerlin/plugins/*alsa*.la %attr(755,root,root) %{_libdir}/gmerlin/plugins/*alsa*.so %files -n gmerlin-esd %attr(644,root,root) %{_libdir}/gmerlin/plugins/*esd*.la %attr(755,root,root) %{_libdir}/gmerlin/plugins/*esd*.so %files -n gmerlin-x11 %attr(644,root,root) %{_libdir}/gmerlin/plugins/*x11*.la %attr(755,root,root) %{_libdir}/gmerlin/plugins/*x11*.so %files -n gmerlin-v4l %attr(644,root,root) %{_libdir}/gmerlin/plugins/*v4l*.la %attr(755,root,root) %{_libdir}/gmerlin/plugins/*v4l*.so %files -n gmerlin-jpeg %attr(644,root,root) %{_libdir}/gmerlin/plugins/*jpeg*.la %attr(755,root,root) %{_libdir}/gmerlin/plugins/*jpeg*.so %files -n gmerlin-png %attr(644,root,root) %{_libdir}/gmerlin/plugins/*png*.la %attr(755,root,root) %{_libdir}/gmerlin/plugins/*png*.so %files -n gmerlin-tiff %attr(644,root,root) %{_libdir}/gmerlin/plugins/*tiff*.la %attr(755,root,root) %{_libdir}/gmerlin/plugins/*tiff*.so %files -n gmerlin-cdaudio %attr(644,root,root) %{_libdir}/gmerlin/plugins/*cdaudio*.la %attr(755,root,root) %{_libdir}/gmerlin/plugins/*cdaudio*.so %files -n gmerlin-player %attr(644,root,root) %{_datadir}/applications/gmerlin-player.desktop %attr(644,root,root) %{_datadir}/gmerlin/icons/player_icon.png %attr(644,root,root) %{_datadir}/gmerlin/skins/Default/* %attr(755,root,root) %{_bindir}/gmerlin %attr(755,root,root) %{_bindir}/gmerlin_remote %attr(755,root,root) %{_bindir}/gmerlin_launcher %files -n gmerlin-alsamixer %attr(644,root,root) %{_datadir}/applications/gmerlin-alsamixer.desktop %attr(644,root,root) %{_datadir}/gmerlin/icons/mixer_icon.png %attr(755,root,root) %{_bindir}/gmerlin_alsamixer %files -n gmerlin-transcoder %attr(644,root,root) %{_datadir}/applications/gmerlin-transcoder.desktop %attr(644,root,root) %{_datadir}/gmerlin/icons/transcoder_icon.png %attr(755,root,root) %{_bindir}/gmerlin_transcoder %attr(755,root,root) %{_bindir}/gmerlin_transcoder_remote %files -n gmerlin-camelot %attr(644,root,root) %{_datadir}/applications/gmerlin-camelot.desktop %attr(644,root,root) %{_datadir}/gmerlin/icons/camelot_icon.png %attr(755,root,root) %{_bindir}/camelot %files -n gmerlin-utils %attr(644,root,root) %{_datadir}/applications/gmerlin-plugincfg.desktop %attr(644,root,root) %{_datadir}/gmerlin/icons/plugincfg_icon.png %attr(755,root,root) %{_bindir}/gmerlin_plugincfg %define date %(echo `LC_ALL="C" date +"%a %b %d %Y"`) %changelog * Sat May 29 2004 Burkhard Plaum - Made it actually working * Sat Feb 08 2003 Burkhard Plaum - Initial creation gmerlin-1.2.0~dfsg/missing0000755000175000017500000002623311331674343015503 0ustar alessioalessio#! /bin/sh # Common stub for a few missing GNU programs while installing. scriptversion=2009-04-28.21; # UTC # Copyright (C) 1996, 1997, 1999, 2000, 2002, 2003, 2004, 2005, 2006, # 2008, 2009 Free Software Foundation, Inc. # Originally by Fran,cois Pinard , 1996. # 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 this program. If not, see . # As a special exception to the GNU General Public License, if you # distribute this file as part of a program that contains a # configuration script generated by Autoconf, you may include it under # the same distribution terms that you use for the rest of that program. if test $# -eq 0; then echo 1>&2 "Try \`$0 --help' for more information" exit 1 fi run=: sed_output='s/.* --output[ =]\([^ ]*\).*/\1/p' sed_minuso='s/.* -o \([^ ]*\).*/\1/p' # In the cases where this matters, `missing' is being run in the # srcdir already. if test -f configure.ac; then configure_ac=configure.ac else configure_ac=configure.in fi msg="missing on your system" case $1 in --run) # Try to run requested program, and just exit if it succeeds. run= shift "$@" && exit 0 # Exit code 63 means version mismatch. This often happens # when the user try to use an ancient version of a tool on # a file that requires a minimum version. In this case we # we should proceed has if the program had been absent, or # if --run hadn't been passed. if test $? = 63; then run=: msg="probably too old" fi ;; -h|--h|--he|--hel|--help) echo "\ $0 [OPTION]... PROGRAM [ARGUMENT]... Handle \`PROGRAM [ARGUMENT]...' for when PROGRAM is missing, or return an error status if there is no known handling for PROGRAM. Options: -h, --help display this help and exit -v, --version output version information and exit --run try to run the given command, and emulate it if it fails Supported PROGRAM values: aclocal touch file \`aclocal.m4' autoconf touch file \`configure' autoheader touch file \`config.h.in' autom4te touch the output file, or create a stub one automake touch all \`Makefile.in' files bison create \`y.tab.[ch]', if possible, from existing .[ch] flex create \`lex.yy.c', if possible, from existing .c help2man touch the output file lex create \`lex.yy.c', if possible, from existing .c makeinfo touch the output file tar try tar, gnutar, gtar, then tar without non-portable flags yacc create \`y.tab.[ch]', if possible, from existing .[ch] Version suffixes to PROGRAM as well as the prefixes \`gnu-', \`gnu', and \`g' are ignored when checking the name. Send bug reports to ." exit $? ;; -v|--v|--ve|--ver|--vers|--versi|--versio|--version) echo "missing $scriptversion (GNU Automake)" exit $? ;; -*) echo 1>&2 "$0: Unknown \`$1' option" echo 1>&2 "Try \`$0 --help' for more information" exit 1 ;; esac # normalize program name to check for. program=`echo "$1" | sed ' s/^gnu-//; t s/^gnu//; t s/^g//; t'` # Now exit if we have it, but it failed. Also exit now if we # don't have it and --version was passed (most likely to detect # the program). This is about non-GNU programs, so use $1 not # $program. case $1 in lex*|yacc*) # Not GNU programs, they don't have --version. ;; tar*) if test -n "$run"; then echo 1>&2 "ERROR: \`tar' requires --run" exit 1 elif test "x$2" = "x--version" || test "x$2" = "x--help"; then exit 1 fi ;; *) if test -z "$run" && ($1 --version) > /dev/null 2>&1; then # We have it, but it failed. exit 1 elif test "x$2" = "x--version" || test "x$2" = "x--help"; then # Could not run --version or --help. This is probably someone # running `$TOOL --version' or `$TOOL --help' to check whether # $TOOL exists and not knowing $TOOL uses missing. exit 1 fi ;; esac # If it does not exist, or fails to run (possibly an outdated version), # try to emulate it. case $program in aclocal*) echo 1>&2 "\ WARNING: \`$1' is $msg. You should only need it if you modified \`acinclude.m4' or \`${configure_ac}'. You might want to install the \`Automake' and \`Perl' packages. Grab them from any GNU archive site." touch aclocal.m4 ;; autoconf*) echo 1>&2 "\ WARNING: \`$1' is $msg. You should only need it if you modified \`${configure_ac}'. You might want to install the \`Autoconf' and \`GNU m4' packages. Grab them from any GNU archive site." touch configure ;; autoheader*) echo 1>&2 "\ WARNING: \`$1' is $msg. You should only need it if you modified \`acconfig.h' or \`${configure_ac}'. You might want to install the \`Autoconf' and \`GNU m4' packages. Grab them from any GNU archive site." files=`sed -n 's/^[ ]*A[CM]_CONFIG_HEADER(\([^)]*\)).*/\1/p' ${configure_ac}` test -z "$files" && files="config.h" touch_files= for f in $files; do case $f in *:*) touch_files="$touch_files "`echo "$f" | sed -e 's/^[^:]*://' -e 's/:.*//'`;; *) touch_files="$touch_files $f.in";; esac done touch $touch_files ;; automake*) echo 1>&2 "\ WARNING: \`$1' is $msg. You should only need it if you modified \`Makefile.am', \`acinclude.m4' or \`${configure_ac}'. You might want to install the \`Automake' and \`Perl' packages. Grab them from any GNU archive site." find . -type f -name Makefile.am -print | sed 's/\.am$/.in/' | while read f; do touch "$f"; done ;; autom4te*) echo 1>&2 "\ WARNING: \`$1' is needed, but is $msg. You might have modified some files without having the proper tools for further handling them. You can get \`$1' as part of \`Autoconf' from any GNU archive site." file=`echo "$*" | sed -n "$sed_output"` test -z "$file" && file=`echo "$*" | sed -n "$sed_minuso"` if test -f "$file"; then touch $file else test -z "$file" || exec >$file echo "#! /bin/sh" echo "# Created by GNU Automake missing as a replacement of" echo "# $ $@" echo "exit 0" chmod +x $file exit 1 fi ;; bison*|yacc*) echo 1>&2 "\ WARNING: \`$1' $msg. You should only need it if you modified a \`.y' file. You may need the \`Bison' package in order for those modifications to take effect. You can get \`Bison' from any GNU archive site." rm -f y.tab.c y.tab.h if test $# -ne 1; then eval LASTARG="\${$#}" case $LASTARG in *.y) SRCFILE=`echo "$LASTARG" | sed 's/y$/c/'` if test -f "$SRCFILE"; then cp "$SRCFILE" y.tab.c fi SRCFILE=`echo "$LASTARG" | sed 's/y$/h/'` if test -f "$SRCFILE"; then cp "$SRCFILE" y.tab.h fi ;; esac fi if test ! -f y.tab.h; then echo >y.tab.h fi if test ! -f y.tab.c; then echo 'main() { return 0; }' >y.tab.c fi ;; lex*|flex*) echo 1>&2 "\ WARNING: \`$1' is $msg. You should only need it if you modified a \`.l' file. You may need the \`Flex' package in order for those modifications to take effect. You can get \`Flex' from any GNU archive site." rm -f lex.yy.c if test $# -ne 1; then eval LASTARG="\${$#}" case $LASTARG in *.l) SRCFILE=`echo "$LASTARG" | sed 's/l$/c/'` if test -f "$SRCFILE"; then cp "$SRCFILE" lex.yy.c fi ;; esac fi if test ! -f lex.yy.c; then echo 'main() { return 0; }' >lex.yy.c fi ;; help2man*) echo 1>&2 "\ WARNING: \`$1' is $msg. You should only need it if you modified a dependency of a manual page. You may need the \`Help2man' package in order for those modifications to take effect. You can get \`Help2man' from any GNU archive site." file=`echo "$*" | sed -n "$sed_output"` test -z "$file" && file=`echo "$*" | sed -n "$sed_minuso"` if test -f "$file"; then touch $file else test -z "$file" || exec >$file echo ".ab help2man is required to generate this page" exit $? fi ;; makeinfo*) echo 1>&2 "\ WARNING: \`$1' is $msg. You should only need it if you modified a \`.texi' or \`.texinfo' file, or any other file indirectly affecting the aspect of the manual. The spurious call might also be the consequence of using a buggy \`make' (AIX, DU, IRIX). You might want to install the \`Texinfo' package or the \`GNU make' package. Grab either from any GNU archive site." # The file to touch is that specified with -o ... file=`echo "$*" | sed -n "$sed_output"` test -z "$file" && file=`echo "$*" | sed -n "$sed_minuso"` if test -z "$file"; then # ... or it is the one specified with @setfilename ... infile=`echo "$*" | sed 's/.* \([^ ]*\) *$/\1/'` file=`sed -n ' /^@setfilename/{ s/.* \([^ ]*\) *$/\1/ p q }' $infile` # ... or it is derived from the source name (dir/f.texi becomes f.info) test -z "$file" && file=`echo "$infile" | sed 's,.*/,,;s,.[^.]*$,,'`.info fi # If the file does not exist, the user really needs makeinfo; # let's fail without touching anything. test -f $file || exit 1 touch $file ;; tar*) shift # We have already tried tar in the generic part. # Look for gnutar/gtar before invocation to avoid ugly error # messages. if (gnutar --version > /dev/null 2>&1); then gnutar "$@" && exit 0 fi if (gtar --version > /dev/null 2>&1); then gtar "$@" && exit 0 fi firstarg="$1" if shift; then case $firstarg in *o*) firstarg=`echo "$firstarg" | sed s/o//` tar "$firstarg" "$@" && exit 0 ;; esac case $firstarg in *h*) firstarg=`echo "$firstarg" | sed s/h//` tar "$firstarg" "$@" && exit 0 ;; esac fi echo 1>&2 "\ WARNING: I can't seem to be able to run \`tar' with the given arguments. You may want to install GNU tar or Free paxutils, or check the command line arguments." exit 1 ;; *) echo 1>&2 "\ WARNING: \`$1' is needed, and is $msg. You might have modified some files without having the proper tools for further handling them. Check the \`README' file, it often tells you about the needed prerequisites for installing this package. You may also peek at any GNU archive site, in case some other package would contain this missing \`$1' program." exit 1 ;; esac exit 0 # Local variables: # eval: (add-hook 'write-file-hooks 'time-stamp) # time-stamp-start: "scriptversion=" # time-stamp-format: "%:y-%02m-%02d.%02H" # time-stamp-time-zone: "UTC" # time-stamp-end: "; # UTC" # End: gmerlin-1.2.0~dfsg/ltmain.sh0000755000175000017500000073341511764363420015737 0ustar alessioalessio# Generated from ltmain.m4sh. # ltmain.sh (GNU libtool) 2.2.6b # Written by Gordon Matzigkeit , 1996 # Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2003, 2004, 2005, 2006, 2007 2008 Free Software Foundation, Inc. # This is free software; see the source for copying conditions. There is NO # warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. # GNU Libtool 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 of the License, or # (at your option) any later version. # # As a special exception to the GNU General Public License, # if you distribute this file as part of a program or library that # is built using GNU Libtool, you may include this file under the # same distribution terms that you use for the rest of that program. # # GNU Libtool 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 Libtool; see the file COPYING. If not, a copy # can be downloaded from http://www.gnu.org/licenses/gpl.html, # or obtained by writing to the Free Software Foundation, Inc., # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. # Usage: $progname [OPTION]... [MODE-ARG]... # # Provide generalized library-building support services. # # --config show all configuration variables # --debug enable verbose shell tracing # -n, --dry-run display commands without modifying any files # --features display basic configuration information and exit # --mode=MODE use operation mode MODE # --preserve-dup-deps don't remove duplicate dependency libraries # --quiet, --silent don't print informational messages # --tag=TAG use configuration variables from tag TAG # -v, --verbose print informational messages (default) # --version print version information # -h, --help print short or long help message # # MODE must be one of the following: # # clean remove files from the build directory # compile compile a source file into a libtool object # execute automatically set library path, then run a program # finish complete the installation of libtool libraries # install install libraries or executables # link create a library or an executable # uninstall remove libraries from an installed directory # # MODE-ARGS vary depending on the MODE. # Try `$progname --help --mode=MODE' for a more detailed description of MODE. # # When reporting a bug, please describe a test case to reproduce it and # include the following information: # # host-triplet: $host # shell: $SHELL # compiler: $LTCC # compiler flags: $LTCFLAGS # linker: $LD (gnu? $with_gnu_ld) # $progname: (GNU libtool) 2.2.6b Debian-2.2.6b-2ubuntu1 # automake: $automake_version # autoconf: $autoconf_version # # Report bugs to . PROGRAM=ltmain.sh PACKAGE=libtool VERSION="2.2.6b Debian-2.2.6b-2ubuntu1" TIMESTAMP="" package_revision=1.3017 # Be Bourne compatible if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then emulate sh NULLCMD=: # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which # is contrary to our usage. Disable this feature. alias -g '${1+"$@"}'='"$@"' setopt NO_GLOB_SUBST else case `(set -o) 2>/dev/null` in *posix*) set -o posix;; esac fi BIN_SH=xpg4; export BIN_SH # for Tru64 DUALCASE=1; export DUALCASE # for MKS sh # NLS nuisances: We save the old values to restore during execute mode. # Only set LANG and LC_ALL to C if already set. # These must not be set unconditionally because not all systems understand # e.g. LANG=C (notably SCO). lt_user_locale= lt_safe_locale= for lt_var in LANG LANGUAGE LC_ALL LC_CTYPE LC_COLLATE LC_MESSAGES do eval "if test \"\${$lt_var+set}\" = set; then save_$lt_var=\$$lt_var $lt_var=C export $lt_var lt_user_locale=\"$lt_var=\\\$save_\$lt_var; \$lt_user_locale\" lt_safe_locale=\"$lt_var=C; \$lt_safe_locale\" fi" done $lt_unset CDPATH : ${CP="cp -f"} : ${ECHO="echo"} : ${EGREP="/bin/grep -E"} : ${FGREP="/bin/grep -F"} : ${GREP="/bin/grep"} : ${LN_S="ln -s"} : ${MAKE="make"} : ${MKDIR="mkdir"} : ${MV="mv -f"} : ${RM="rm -f"} : ${SED="/bin/sed"} : ${SHELL="${CONFIG_SHELL-/bin/sh}"} : ${Xsed="$SED -e 1s/^X//"} # Global variables: EXIT_SUCCESS=0 EXIT_FAILURE=1 EXIT_MISMATCH=63 # $? = 63 is used to indicate version mismatch to missing. EXIT_SKIP=77 # $? = 77 is used to indicate a skipped test to automake. exit_status=$EXIT_SUCCESS # Make sure IFS has a sensible default lt_nl=' ' IFS=" $lt_nl" dirname="s,/[^/]*$,," basename="s,^.*/,," # func_dirname_and_basename file append nondir_replacement # perform func_basename and func_dirname in a single function # call: # dirname: Compute the dirname of FILE. If nonempty, # add APPEND to the result, otherwise set result # to NONDIR_REPLACEMENT. # value returned in "$func_dirname_result" # basename: Compute filename of FILE. # value retuned in "$func_basename_result" # Implementation must be kept synchronized with func_dirname # and func_basename. For efficiency, we do not delegate to # those functions but instead duplicate the functionality here. func_dirname_and_basename () { # Extract subdirectory from the argument. func_dirname_result=`$ECHO "X${1}" | $Xsed -e "$dirname"` if test "X$func_dirname_result" = "X${1}"; then func_dirname_result="${3}" else func_dirname_result="$func_dirname_result${2}" fi func_basename_result=`$ECHO "X${1}" | $Xsed -e "$basename"` } # Generated shell functions inserted here. # Work around backward compatibility issue on IRIX 6.5. On IRIX 6.4+, sh # is ksh but when the shell is invoked as "sh" and the current value of # the _XPG environment variable is not equal to 1 (one), the special # positional parameter $0, within a function call, is the name of the # function. progpath="$0" # The name of this program: # In the unlikely event $progname began with a '-', it would play havoc with # func_echo (imagine progname=-n), so we prepend ./ in that case: func_dirname_and_basename "$progpath" progname=$func_basename_result case $progname in -*) progname=./$progname ;; esac # Make sure we have an absolute path for reexecution: case $progpath in [\\/]*|[A-Za-z]:\\*) ;; *[\\/]*) progdir=$func_dirname_result progdir=`cd "$progdir" && pwd` progpath="$progdir/$progname" ;; *) save_IFS="$IFS" IFS=: for progdir in $PATH; do IFS="$save_IFS" test -x "$progdir/$progname" && break done IFS="$save_IFS" test -n "$progdir" || progdir=`pwd` progpath="$progdir/$progname" ;; esac # Sed substitution that helps us do robust quoting. It backslashifies # metacharacters that are still active within double-quoted strings. Xsed="${SED}"' -e 1s/^X//' sed_quote_subst='s/\([`"$\\]\)/\\\1/g' # Same as above, but do not quote variable references. double_quote_subst='s/\(["`\\]\)/\\\1/g' # Re-`\' parameter expansions in output of double_quote_subst that were # `\'-ed in input to the same. If an odd number of `\' preceded a '$' # in input to double_quote_subst, that '$' was protected from expansion. # Since each input `\' is now two `\'s, look for any number of runs of # four `\'s followed by two `\'s and then a '$'. `\' that '$'. bs='\\' bs2='\\\\' bs4='\\\\\\\\' dollar='\$' sed_double_backslash="\ s/$bs4/&\\ /g s/^$bs2$dollar/$bs&/ s/\\([^$bs]\\)$bs2$dollar/\\1$bs2$bs$dollar/g s/\n//g" # Standard options: opt_dry_run=false opt_help=false opt_quiet=false opt_verbose=false opt_warning=: # func_echo arg... # Echo program name prefixed message, along with the current mode # name if it has been set yet. func_echo () { $ECHO "$progname${mode+: }$mode: $*" } # func_verbose arg... # Echo program name prefixed message in verbose mode only. func_verbose () { $opt_verbose && func_echo ${1+"$@"} # A bug in bash halts the script if the last line of a function # fails when set -e is in force, so we need another command to # work around that: : } # func_error arg... # Echo program name prefixed message to standard error. func_error () { $ECHO "$progname${mode+: }$mode: "${1+"$@"} 1>&2 } # func_warning arg... # Echo program name prefixed warning message to standard error. func_warning () { $opt_warning && $ECHO "$progname${mode+: }$mode: warning: "${1+"$@"} 1>&2 # bash bug again: : } # func_fatal_error arg... # Echo program name prefixed message to standard error, and exit. func_fatal_error () { func_error ${1+"$@"} exit $EXIT_FAILURE } # func_fatal_help arg... # Echo program name prefixed message to standard error, followed by # a help hint, and exit. func_fatal_help () { func_error ${1+"$@"} func_fatal_error "$help" } help="Try \`$progname --help' for more information." ## default # func_grep expression filename # Check whether EXPRESSION matches any line of FILENAME, without output. func_grep () { $GREP "$1" "$2" >/dev/null 2>&1 } # func_mkdir_p directory-path # Make sure the entire path to DIRECTORY-PATH is available. func_mkdir_p () { my_directory_path="$1" my_dir_list= if test -n "$my_directory_path" && test "$opt_dry_run" != ":"; then # Protect directory names starting with `-' case $my_directory_path in -*) my_directory_path="./$my_directory_path" ;; esac # While some portion of DIR does not yet exist... while test ! -d "$my_directory_path"; do # ...make a list in topmost first order. Use a colon delimited # list incase some portion of path contains whitespace. my_dir_list="$my_directory_path:$my_dir_list" # If the last portion added has no slash in it, the list is done case $my_directory_path in */*) ;; *) break ;; esac # ...otherwise throw away the child directory and loop my_directory_path=`$ECHO "X$my_directory_path" | $Xsed -e "$dirname"` done my_dir_list=`$ECHO "X$my_dir_list" | $Xsed -e 's,:*$,,'` save_mkdir_p_IFS="$IFS"; IFS=':' for my_dir in $my_dir_list; do IFS="$save_mkdir_p_IFS" # mkdir can fail with a `File exist' error if two processes # try to create one of the directories concurrently. Don't # stop in that case! $MKDIR "$my_dir" 2>/dev/null || : done IFS="$save_mkdir_p_IFS" # Bail out if we (or some other process) failed to create a directory. test -d "$my_directory_path" || \ func_fatal_error "Failed to create \`$1'" fi } # func_mktempdir [string] # Make a temporary directory that won't clash with other running # libtool processes, and avoids race conditions if possible. If # given, STRING is the basename for that directory. func_mktempdir () { my_template="${TMPDIR-/tmp}/${1-$progname}" if test "$opt_dry_run" = ":"; then # Return a directory name, but don't create it in dry-run mode my_tmpdir="${my_template}-$$" else # If mktemp works, use that first and foremost my_tmpdir=`mktemp -d "${my_template}-XXXXXXXX" 2>/dev/null` if test ! -d "$my_tmpdir"; then # Failing that, at least try and use $RANDOM to avoid a race my_tmpdir="${my_template}-${RANDOM-0}$$" save_mktempdir_umask=`umask` umask 0077 $MKDIR "$my_tmpdir" umask $save_mktempdir_umask fi # If we're not in dry-run mode, bomb out on failure test -d "$my_tmpdir" || \ func_fatal_error "cannot create temporary directory \`$my_tmpdir'" fi $ECHO "X$my_tmpdir" | $Xsed } # func_quote_for_eval arg # Aesthetically quote ARG to be evaled later. # This function returns two values: FUNC_QUOTE_FOR_EVAL_RESULT # is double-quoted, suitable for a subsequent eval, whereas # FUNC_QUOTE_FOR_EVAL_UNQUOTED_RESULT has merely all characters # which are still active within double quotes backslashified. func_quote_for_eval () { case $1 in *[\\\`\"\$]*) func_quote_for_eval_unquoted_result=`$ECHO "X$1" | $Xsed -e "$sed_quote_subst"` ;; *) func_quote_for_eval_unquoted_result="$1" ;; esac case $func_quote_for_eval_unquoted_result in # Double-quote args containing shell metacharacters to delay # word splitting, command substitution and and variable # expansion for a subsequent eval. # Many Bourne shells cannot handle close brackets correctly # in scan sets, so we specify it separately. *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") func_quote_for_eval_result="\"$func_quote_for_eval_unquoted_result\"" ;; *) func_quote_for_eval_result="$func_quote_for_eval_unquoted_result" esac } # func_quote_for_expand arg # Aesthetically quote ARG to be evaled later; same as above, # but do not quote variable references. func_quote_for_expand () { case $1 in *[\\\`\"]*) my_arg=`$ECHO "X$1" | $Xsed \ -e "$double_quote_subst" -e "$sed_double_backslash"` ;; *) my_arg="$1" ;; esac case $my_arg in # Double-quote args containing shell metacharacters to delay # word splitting and command substitution for a subsequent eval. # Many Bourne shells cannot handle close brackets correctly # in scan sets, so we specify it separately. *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") my_arg="\"$my_arg\"" ;; esac func_quote_for_expand_result="$my_arg" } # func_show_eval cmd [fail_exp] # Unless opt_silent is true, then output CMD. Then, if opt_dryrun is # not true, evaluate CMD. If the evaluation of CMD fails, and FAIL_EXP # is given, then evaluate it. func_show_eval () { my_cmd="$1" my_fail_exp="${2-:}" ${opt_silent-false} || { func_quote_for_expand "$my_cmd" eval "func_echo $func_quote_for_expand_result" } if ${opt_dry_run-false}; then :; else eval "$my_cmd" my_status=$? if test "$my_status" -eq 0; then :; else eval "(exit $my_status); $my_fail_exp" fi fi } # func_show_eval_locale cmd [fail_exp] # Unless opt_silent is true, then output CMD. Then, if opt_dryrun is # not true, evaluate CMD. If the evaluation of CMD fails, and FAIL_EXP # is given, then evaluate it. Use the saved locale for evaluation. func_show_eval_locale () { my_cmd="$1" my_fail_exp="${2-:}" ${opt_silent-false} || { func_quote_for_expand "$my_cmd" eval "func_echo $func_quote_for_expand_result" } if ${opt_dry_run-false}; then :; else eval "$lt_user_locale $my_cmd" my_status=$? eval "$lt_safe_locale" if test "$my_status" -eq 0; then :; else eval "(exit $my_status); $my_fail_exp" fi fi } # func_version # Echo version message to standard output and exit. func_version () { $SED -n '/^# '$PROGRAM' (GNU /,/# warranty; / { s/^# // s/^# *$// s/\((C)\)[ 0-9,-]*\( [1-9][0-9]*\)/\1\2/ p }' < "$progpath" exit $? } # func_usage # Echo short help message to standard output and exit. func_usage () { $SED -n '/^# Usage:/,/# -h/ { s/^# // s/^# *$// s/\$progname/'$progname'/ p }' < "$progpath" $ECHO $ECHO "run \`$progname --help | more' for full usage" exit $? } # func_help # Echo long help message to standard output and exit. func_help () { $SED -n '/^# Usage:/,/# Report bugs to/ { s/^# // s/^# *$// s*\$progname*'$progname'* s*\$host*'"$host"'* s*\$SHELL*'"$SHELL"'* s*\$LTCC*'"$LTCC"'* s*\$LTCFLAGS*'"$LTCFLAGS"'* s*\$LD*'"$LD"'* s/\$with_gnu_ld/'"$with_gnu_ld"'/ s/\$automake_version/'"`(automake --version) 2>/dev/null |$SED 1q`"'/ s/\$autoconf_version/'"`(autoconf --version) 2>/dev/null |$SED 1q`"'/ p }' < "$progpath" exit $? } # func_missing_arg argname # Echo program name prefixed message to standard error and set global # exit_cmd. func_missing_arg () { func_error "missing argument for $1" exit_cmd=exit } exit_cmd=: # Check that we have a working $ECHO. if test "X$1" = X--no-reexec; then # Discard the --no-reexec flag, and continue. shift elif test "X$1" = X--fallback-echo; then # Avoid inline document here, it may be left over : elif test "X`{ $ECHO '\t'; } 2>/dev/null`" = 'X\t'; then # Yippee, $ECHO works! : else # Restart under the correct shell, and then maybe $ECHO will work. exec $SHELL "$progpath" --no-reexec ${1+"$@"} fi if test "X$1" = X--fallback-echo; then # used as fallback echo shift cat </dev/null 2>&1; then taglist="$taglist $tagname" # Evaluate the configuration. Be careful to quote the path # and the sed script, to avoid splitting on whitespace, but # also don't use non-portable quotes within backquotes within # quotes we have to do it in 2 steps: extractedcf=`$SED -n -e "$sed_extractcf" < "$progpath"` eval "$extractedcf" else func_error "ignoring unknown tag $tagname" fi ;; esac } # Parse options once, thoroughly. This comes as soon as possible in # the script to make things like `libtool --version' happen quickly. { # Shorthand for --mode=foo, only valid as the first argument case $1 in clean|clea|cle|cl) shift; set dummy --mode clean ${1+"$@"}; shift ;; compile|compil|compi|comp|com|co|c) shift; set dummy --mode compile ${1+"$@"}; shift ;; execute|execut|execu|exec|exe|ex|e) shift; set dummy --mode execute ${1+"$@"}; shift ;; finish|finis|fini|fin|fi|f) shift; set dummy --mode finish ${1+"$@"}; shift ;; install|instal|insta|inst|ins|in|i) shift; set dummy --mode install ${1+"$@"}; shift ;; link|lin|li|l) shift; set dummy --mode link ${1+"$@"}; shift ;; uninstall|uninstal|uninsta|uninst|unins|unin|uni|un|u) shift; set dummy --mode uninstall ${1+"$@"}; shift ;; esac # Parse non-mode specific arguments: while test "$#" -gt 0; do opt="$1" shift case $opt in --config) func_config ;; --debug) preserve_args="$preserve_args $opt" func_echo "enabling shell trace mode" opt_debug='set -x' $opt_debug ;; -dlopen) test "$#" -eq 0 && func_missing_arg "$opt" && break execute_dlfiles="$execute_dlfiles $1" shift ;; --dry-run | -n) opt_dry_run=: ;; --features) func_features ;; --finish) mode="finish" ;; --mode) test "$#" -eq 0 && func_missing_arg "$opt" && break case $1 in # Valid mode arguments: clean) ;; compile) ;; execute) ;; finish) ;; install) ;; link) ;; relink) ;; uninstall) ;; # Catch anything else as an error *) func_error "invalid argument for $opt" exit_cmd=exit break ;; esac mode="$1" shift ;; --preserve-dup-deps) opt_duplicate_deps=: ;; --quiet|--silent) preserve_args="$preserve_args $opt" opt_silent=: ;; --verbose| -v) preserve_args="$preserve_args $opt" opt_silent=false ;; --tag) test "$#" -eq 0 && func_missing_arg "$opt" && break preserve_args="$preserve_args $opt $1" func_enable_tag "$1" # tagname is set here shift ;; # Separate optargs to long options: -dlopen=*|--mode=*|--tag=*) func_opt_split "$opt" set dummy "$func_opt_split_opt" "$func_opt_split_arg" ${1+"$@"} shift ;; -\?|-h) func_usage ;; --help) opt_help=: ;; --version) func_version ;; -*) func_fatal_help "unrecognized option \`$opt'" ;; *) nonopt="$opt" break ;; esac done case $host in *cygwin* | *mingw* | *pw32* | *cegcc*) # don't eliminate duplications in $postdeps and $predeps opt_duplicate_compiler_generated_deps=: ;; *) opt_duplicate_compiler_generated_deps=$opt_duplicate_deps ;; esac # Having warned about all mis-specified options, bail out if # anything was wrong. $exit_cmd $EXIT_FAILURE } # func_check_version_match # Ensure that we are using m4 macros, and libtool script from the same # release of libtool. func_check_version_match () { if test "$package_revision" != "$macro_revision"; then if test "$VERSION" != "$macro_version"; then if test -z "$macro_version"; then cat >&2 <<_LT_EOF $progname: Version mismatch error. This is $PACKAGE $VERSION, but the $progname: definition of this LT_INIT comes from an older release. $progname: You should recreate aclocal.m4 with macros from $PACKAGE $VERSION $progname: and run autoconf again. _LT_EOF else cat >&2 <<_LT_EOF $progname: Version mismatch error. This is $PACKAGE $VERSION, but the $progname: definition of this LT_INIT comes from $PACKAGE $macro_version. $progname: You should recreate aclocal.m4 with macros from $PACKAGE $VERSION $progname: and run autoconf again. _LT_EOF fi else cat >&2 <<_LT_EOF $progname: Version mismatch error. This is $PACKAGE $VERSION, revision $package_revision, $progname: but the definition of this LT_INIT comes from revision $macro_revision. $progname: You should recreate aclocal.m4 with macros from revision $package_revision $progname: of $PACKAGE $VERSION and run autoconf again. _LT_EOF fi exit $EXIT_MISMATCH fi } ## ----------- ## ## Main. ## ## ----------- ## $opt_help || { # Sanity checks first: func_check_version_match if test "$build_libtool_libs" != yes && test "$build_old_libs" != yes; then func_fatal_configuration "not configured to build any kind of library" fi test -z "$mode" && func_fatal_error "error: you must specify a MODE." # Darwin sucks eval std_shrext=\"$shrext_cmds\" # Only execute mode is allowed to have -dlopen flags. if test -n "$execute_dlfiles" && test "$mode" != execute; then func_error "unrecognized option \`-dlopen'" $ECHO "$help" 1>&2 exit $EXIT_FAILURE fi # Change the help message to a mode-specific one. generic_help="$help" help="Try \`$progname --help --mode=$mode' for more information." } # func_lalib_p file # True iff FILE is a libtool `.la' library or `.lo' object file. # This function is only a basic sanity check; it will hardly flush out # determined imposters. func_lalib_p () { test -f "$1" && $SED -e 4q "$1" 2>/dev/null \ | $GREP "^# Generated by .*$PACKAGE" > /dev/null 2>&1 } # func_lalib_unsafe_p file # True iff FILE is a libtool `.la' library or `.lo' object file. # This function implements the same check as func_lalib_p without # resorting to external programs. To this end, it redirects stdin and # closes it afterwards, without saving the original file descriptor. # As a safety measure, use it only where a negative result would be # fatal anyway. Works if `file' does not exist. func_lalib_unsafe_p () { lalib_p=no if test -f "$1" && test -r "$1" && exec 5<&0 <"$1"; then for lalib_p_l in 1 2 3 4 do read lalib_p_line case "$lalib_p_line" in \#\ Generated\ by\ *$PACKAGE* ) lalib_p=yes; break;; esac done exec 0<&5 5<&- fi test "$lalib_p" = yes } # func_ltwrapper_script_p file # True iff FILE is a libtool wrapper script # This function is only a basic sanity check; it will hardly flush out # determined imposters. func_ltwrapper_script_p () { func_lalib_p "$1" } # func_ltwrapper_executable_p file # True iff FILE is a libtool wrapper executable # This function is only a basic sanity check; it will hardly flush out # determined imposters. func_ltwrapper_executable_p () { func_ltwrapper_exec_suffix= case $1 in *.exe) ;; *) func_ltwrapper_exec_suffix=.exe ;; esac $GREP "$magic_exe" "$1$func_ltwrapper_exec_suffix" >/dev/null 2>&1 } # func_ltwrapper_scriptname file # Assumes file is an ltwrapper_executable # uses $file to determine the appropriate filename for a # temporary ltwrapper_script. func_ltwrapper_scriptname () { func_ltwrapper_scriptname_result="" if func_ltwrapper_executable_p "$1"; then func_dirname_and_basename "$1" "" "." func_stripname '' '.exe' "$func_basename_result" func_ltwrapper_scriptname_result="$func_dirname_result/$objdir/${func_stripname_result}_ltshwrapper" fi } # func_ltwrapper_p file # True iff FILE is a libtool wrapper script or wrapper executable # This function is only a basic sanity check; it will hardly flush out # determined imposters. func_ltwrapper_p () { func_ltwrapper_script_p "$1" || func_ltwrapper_executable_p "$1" } # func_execute_cmds commands fail_cmd # Execute tilde-delimited COMMANDS. # If FAIL_CMD is given, eval that upon failure. # FAIL_CMD may read-access the current command in variable CMD! func_execute_cmds () { $opt_debug save_ifs=$IFS; IFS='~' for cmd in $1; do IFS=$save_ifs eval cmd=\"$cmd\" func_show_eval "$cmd" "${2-:}" done IFS=$save_ifs } # func_source file # Source FILE, adding directory component if necessary. # Note that it is not necessary on cygwin/mingw to append a dot to # FILE even if both FILE and FILE.exe exist: automatic-append-.exe # behavior happens only for exec(3), not for open(2)! Also, sourcing # `FILE.' does not work on cygwin managed mounts. func_source () { $opt_debug case $1 in */* | *\\*) . "$1" ;; *) . "./$1" ;; esac } # func_infer_tag arg # Infer tagged configuration to use if any are available and # if one wasn't chosen via the "--tag" command line option. # Only attempt this if the compiler in the base compile # command doesn't match the default compiler. # arg is usually of the form 'gcc ...' func_infer_tag () { $opt_debug if test -n "$available_tags" && test -z "$tagname"; then CC_quoted= for arg in $CC; do func_quote_for_eval "$arg" CC_quoted="$CC_quoted $func_quote_for_eval_result" done case $@ in # Blanks in the command may have been stripped by the calling shell, # but not from the CC environment variable when configure was run. " $CC "* | "$CC "* | " `$ECHO $CC` "* | "`$ECHO $CC` "* | " $CC_quoted"* | "$CC_quoted "* | " `$ECHO $CC_quoted` "* | "`$ECHO $CC_quoted` "*) ;; # Blanks at the start of $base_compile will cause this to fail # if we don't check for them as well. *) for z in $available_tags; do if $GREP "^# ### BEGIN LIBTOOL TAG CONFIG: $z$" < "$progpath" > /dev/null; then # Evaluate the configuration. eval "`${SED} -n -e '/^# ### BEGIN LIBTOOL TAG CONFIG: '$z'$/,/^# ### END LIBTOOL TAG CONFIG: '$z'$/p' < $progpath`" CC_quoted= for arg in $CC; do # Double-quote args containing other shell metacharacters. func_quote_for_eval "$arg" CC_quoted="$CC_quoted $func_quote_for_eval_result" done case "$@ " in " $CC "* | "$CC "* | " `$ECHO $CC` "* | "`$ECHO $CC` "* | " $CC_quoted"* | "$CC_quoted "* | " `$ECHO $CC_quoted` "* | "`$ECHO $CC_quoted` "*) # The compiler in the base compile command matches # the one in the tagged configuration. # Assume this is the tagged configuration we want. tagname=$z break ;; esac fi done # If $tagname still isn't set, then no tagged configuration # was found and let the user know that the "--tag" command # line option must be used. if test -z "$tagname"; then func_echo "unable to infer tagged configuration" func_fatal_error "specify a tag with \`--tag'" # else # func_verbose "using $tagname tagged configuration" fi ;; esac fi } # func_write_libtool_object output_name pic_name nonpic_name # Create a libtool object file (analogous to a ".la" file), # but don't create it if we're doing a dry run. func_write_libtool_object () { write_libobj=${1} if test "$build_libtool_libs" = yes; then write_lobj=\'${2}\' else write_lobj=none fi if test "$build_old_libs" = yes; then write_oldobj=\'${3}\' else write_oldobj=none fi $opt_dry_run || { cat >${write_libobj}T <?"'"'"' &()|`$[]' \ && func_warning "libobj name \`$libobj' may not contain shell special characters." func_dirname_and_basename "$obj" "/" "" objname="$func_basename_result" xdir="$func_dirname_result" lobj=${xdir}$objdir/$objname test -z "$base_compile" && \ func_fatal_help "you must specify a compilation command" # Delete any leftover library objects. if test "$build_old_libs" = yes; then removelist="$obj $lobj $libobj ${libobj}T" else removelist="$lobj $libobj ${libobj}T" fi # On Cygwin there's no "real" PIC flag so we must build both object types case $host_os in cygwin* | mingw* | pw32* | os2* | cegcc*) pic_mode=default ;; esac if test "$pic_mode" = no && test "$deplibs_check_method" != pass_all; then # non-PIC code in shared libraries is not supported pic_mode=default fi # Calculate the filename of the output object if compiler does # not support -o with -c if test "$compiler_c_o" = no; then output_obj=`$ECHO "X$srcfile" | $Xsed -e 's%^.*/%%' -e 's%\.[^.]*$%%'`.${objext} lockfile="$output_obj.lock" else output_obj= need_locks=no lockfile= fi # Lock this critical section if it is needed # We use this script file to make the link, it avoids creating a new file if test "$need_locks" = yes; then until $opt_dry_run || ln "$progpath" "$lockfile" 2>/dev/null; do func_echo "Waiting for $lockfile to be removed" sleep 2 done elif test "$need_locks" = warn; then if test -f "$lockfile"; then $ECHO "\ *** ERROR, $lockfile exists and contains: `cat $lockfile 2>/dev/null` This indicates that another process is trying to use the same temporary object file, and libtool could not work around it because your compiler does not support \`-c' and \`-o' together. If you repeat this compilation, it may succeed, by chance, but you had better avoid parallel builds (make -j) in this platform, or get a better compiler." $opt_dry_run || $RM $removelist exit $EXIT_FAILURE fi removelist="$removelist $output_obj" $ECHO "$srcfile" > "$lockfile" fi $opt_dry_run || $RM $removelist removelist="$removelist $lockfile" trap '$opt_dry_run || $RM $removelist; exit $EXIT_FAILURE' 1 2 15 if test -n "$fix_srcfile_path"; then eval srcfile=\"$fix_srcfile_path\" fi func_quote_for_eval "$srcfile" qsrcfile=$func_quote_for_eval_result # Only build a PIC object if we are building libtool libraries. if test "$build_libtool_libs" = yes; then # Without this assignment, base_compile gets emptied. fbsd_hideous_sh_bug=$base_compile if test "$pic_mode" != no; then command="$base_compile $qsrcfile $pic_flag" else # Don't build PIC code command="$base_compile $qsrcfile" fi func_mkdir_p "$xdir$objdir" if test -z "$output_obj"; then # Place PIC objects in $objdir command="$command -o $lobj" fi func_show_eval_locale "$command" \ 'test -n "$output_obj" && $RM $removelist; exit $EXIT_FAILURE' if test "$need_locks" = warn && test "X`cat $lockfile 2>/dev/null`" != "X$srcfile"; then $ECHO "\ *** ERROR, $lockfile contains: `cat $lockfile 2>/dev/null` but it should contain: $srcfile This indicates that another process is trying to use the same temporary object file, and libtool could not work around it because your compiler does not support \`-c' and \`-o' together. If you repeat this compilation, it may succeed, by chance, but you had better avoid parallel builds (make -j) in this platform, or get a better compiler." $opt_dry_run || $RM $removelist exit $EXIT_FAILURE fi # Just move the object if needed, then go on to compile the next one if test -n "$output_obj" && test "X$output_obj" != "X$lobj"; then func_show_eval '$MV "$output_obj" "$lobj"' \ 'error=$?; $opt_dry_run || $RM $removelist; exit $error' fi # Allow error messages only from the first compilation. if test "$suppress_opt" = yes; then suppress_output=' >/dev/null 2>&1' fi fi # Only build a position-dependent object if we build old libraries. if test "$build_old_libs" = yes; then if test "$pic_mode" != yes; then # Don't build PIC code command="$base_compile $qsrcfile$pie_flag" else command="$base_compile $qsrcfile $pic_flag" fi if test "$compiler_c_o" = yes; then command="$command -o $obj" fi # Suppress compiler output if we already did a PIC compilation. command="$command$suppress_output" func_show_eval_locale "$command" \ '$opt_dry_run || $RM $removelist; exit $EXIT_FAILURE' if test "$need_locks" = warn && test "X`cat $lockfile 2>/dev/null`" != "X$srcfile"; then $ECHO "\ *** ERROR, $lockfile contains: `cat $lockfile 2>/dev/null` but it should contain: $srcfile This indicates that another process is trying to use the same temporary object file, and libtool could not work around it because your compiler does not support \`-c' and \`-o' together. If you repeat this compilation, it may succeed, by chance, but you had better avoid parallel builds (make -j) in this platform, or get a better compiler." $opt_dry_run || $RM $removelist exit $EXIT_FAILURE fi # Just move the object if needed if test -n "$output_obj" && test "X$output_obj" != "X$obj"; then func_show_eval '$MV "$output_obj" "$obj"' \ 'error=$?; $opt_dry_run || $RM $removelist; exit $error' fi fi $opt_dry_run || { func_write_libtool_object "$libobj" "$objdir/$objname" "$objname" # Unlock the critical section if it was locked if test "$need_locks" != no; then removelist=$lockfile $RM "$lockfile" fi } exit $EXIT_SUCCESS } $opt_help || { test "$mode" = compile && func_mode_compile ${1+"$@"} } func_mode_help () { # We need to display help for each of the modes. case $mode in "") # Generic help is extracted from the usage comments # at the start of this file. func_help ;; clean) $ECHO \ "Usage: $progname [OPTION]... --mode=clean RM [RM-OPTION]... FILE... Remove files from the build directory. RM is the name of the program to use to delete files associated with each FILE (typically \`/bin/rm'). RM-OPTIONS are options (such as \`-f') to be passed to RM. If FILE is a libtool library, object or program, all the files associated with it are deleted. Otherwise, only FILE itself is deleted using RM." ;; compile) $ECHO \ "Usage: $progname [OPTION]... --mode=compile COMPILE-COMMAND... SOURCEFILE Compile a source file into a libtool library object. This mode accepts the following additional options: -o OUTPUT-FILE set the output file name to OUTPUT-FILE -no-suppress do not suppress compiler output for multiple passes -prefer-pic try to building PIC objects only -prefer-non-pic try to building non-PIC objects only -shared do not build a \`.o' file suitable for static linking -static only build a \`.o' file suitable for static linking COMPILE-COMMAND is a command to be used in creating a \`standard' object file from the given SOURCEFILE. The output file name is determined by removing the directory component from SOURCEFILE, then substituting the C source code suffix \`.c' with the library object suffix, \`.lo'." ;; execute) $ECHO \ "Usage: $progname [OPTION]... --mode=execute COMMAND [ARGS]... Automatically set library path, then run a program. This mode accepts the following additional options: -dlopen FILE add the directory containing FILE to the library path This mode sets the library path environment variable according to \`-dlopen' flags. If any of the ARGS are libtool executable wrappers, then they are translated into their corresponding uninstalled binary, and any of their required library directories are added to the library path. Then, COMMAND is executed, with ARGS as arguments." ;; finish) $ECHO \ "Usage: $progname [OPTION]... --mode=finish [LIBDIR]... Complete the installation of libtool libraries. Each LIBDIR is a directory that contains libtool libraries. The commands that this mode executes may require superuser privileges. Use the \`--dry-run' option if you just want to see what would be executed." ;; install) $ECHO \ "Usage: $progname [OPTION]... --mode=install INSTALL-COMMAND... Install executables or libraries. INSTALL-COMMAND is the installation command. The first component should be either the \`install' or \`cp' program. The following components of INSTALL-COMMAND are treated specially: -inst-prefix PREFIX-DIR Use PREFIX-DIR as a staging area for installation The rest of the components are interpreted as arguments to that command (only BSD-compatible install options are recognized)." ;; link) $ECHO \ "Usage: $progname [OPTION]... --mode=link LINK-COMMAND... Link object files or libraries together to form another library, or to create an executable program. LINK-COMMAND is a command using the C compiler that you would use to create a program from several object files. The following components of LINK-COMMAND are treated specially: -all-static do not do any dynamic linking at all -avoid-version do not add a version suffix if possible -dlopen FILE \`-dlpreopen' FILE if it cannot be dlopened at runtime -dlpreopen FILE link in FILE and add its symbols to lt_preloaded_symbols -export-dynamic allow symbols from OUTPUT-FILE to be resolved with dlsym(3) -export-symbols SYMFILE try to export only the symbols listed in SYMFILE -export-symbols-regex REGEX try to export only the symbols matching REGEX -LLIBDIR search LIBDIR for required installed libraries -lNAME OUTPUT-FILE requires the installed library libNAME -module build a library that can dlopened -no-fast-install disable the fast-install mode -no-install link a not-installable executable -no-undefined declare that a library does not refer to external symbols -o OUTPUT-FILE create OUTPUT-FILE from the specified objects -objectlist FILE Use a list of object files found in FILE to specify objects -precious-files-regex REGEX don't remove output files matching REGEX -release RELEASE specify package release information -rpath LIBDIR the created library will eventually be installed in LIBDIR -R[ ]LIBDIR add LIBDIR to the runtime path of programs and libraries -shared only do dynamic linking of libtool libraries -shrext SUFFIX override the standard shared library file extension -static do not do any dynamic linking of uninstalled libtool libraries -static-libtool-libs do not do any dynamic linking of libtool libraries -version-info CURRENT[:REVISION[:AGE]] specify library version info [each variable defaults to 0] -weak LIBNAME declare that the target provides the LIBNAME interface All other options (arguments beginning with \`-') are ignored. Every other argument is treated as a filename. Files ending in \`.la' are treated as uninstalled libtool libraries, other files are standard or library object files. If the OUTPUT-FILE ends in \`.la', then a libtool library is created, only library objects (\`.lo' files) may be specified, and \`-rpath' is required, except when creating a convenience library. If OUTPUT-FILE ends in \`.a' or \`.lib', then a standard library is created using \`ar' and \`ranlib', or on Windows using \`lib'. If OUTPUT-FILE ends in \`.lo' or \`.${objext}', then a reloadable object file is created, otherwise an executable program is created." ;; uninstall) $ECHO \ "Usage: $progname [OPTION]... --mode=uninstall RM [RM-OPTION]... FILE... Remove libraries from an installation directory. RM is the name of the program to use to delete files associated with each FILE (typically \`/bin/rm'). RM-OPTIONS are options (such as \`-f') to be passed to RM. If FILE is a libtool library, all the files associated with it are deleted. Otherwise, only FILE itself is deleted using RM." ;; *) func_fatal_help "invalid operation mode \`$mode'" ;; esac $ECHO $ECHO "Try \`$progname --help' for more information about other modes." exit $? } # Now that we've collected a possible --mode arg, show help if necessary $opt_help && func_mode_help # func_mode_execute arg... func_mode_execute () { $opt_debug # The first argument is the command name. cmd="$nonopt" test -z "$cmd" && \ func_fatal_help "you must specify a COMMAND" # Handle -dlopen flags immediately. for file in $execute_dlfiles; do test -f "$file" \ || func_fatal_help "\`$file' is not a file" dir= case $file in *.la) # Check to see that this really is a libtool archive. func_lalib_unsafe_p "$file" \ || func_fatal_help "\`$lib' is not a valid libtool archive" # Read the libtool library. dlname= library_names= func_source "$file" # Skip this library if it cannot be dlopened. if test -z "$dlname"; then # Warn if it was a shared library. test -n "$library_names" && \ func_warning "\`$file' was not linked with \`-export-dynamic'" continue fi func_dirname "$file" "" "." dir="$func_dirname_result" if test -f "$dir/$objdir/$dlname"; then dir="$dir/$objdir" else if test ! -f "$dir/$dlname"; then func_fatal_error "cannot find \`$dlname' in \`$dir' or \`$dir/$objdir'" fi fi ;; *.lo) # Just add the directory containing the .lo file. func_dirname "$file" "" "." dir="$func_dirname_result" ;; *) func_warning "\`-dlopen' is ignored for non-libtool libraries and objects" continue ;; esac # Get the absolute pathname. absdir=`cd "$dir" && pwd` test -n "$absdir" && dir="$absdir" # Now add the directory to shlibpath_var. if eval "test -z \"\$$shlibpath_var\""; then eval "$shlibpath_var=\"\$dir\"" else eval "$shlibpath_var=\"\$dir:\$$shlibpath_var\"" fi done # This variable tells wrapper scripts just to set shlibpath_var # rather than running their programs. libtool_execute_magic="$magic" # Check if any of the arguments is a wrapper script. args= for file do case $file in -*) ;; *) # Do a test to see if this is really a libtool program. if func_ltwrapper_script_p "$file"; then func_source "$file" # Transform arg to wrapped name. file="$progdir/$program" elif func_ltwrapper_executable_p "$file"; then func_ltwrapper_scriptname "$file" func_source "$func_ltwrapper_scriptname_result" # Transform arg to wrapped name. file="$progdir/$program" fi ;; esac # Quote arguments (to preserve shell metacharacters). func_quote_for_eval "$file" args="$args $func_quote_for_eval_result" done if test "X$opt_dry_run" = Xfalse; then if test -n "$shlibpath_var"; then # Export the shlibpath_var. eval "export $shlibpath_var" fi # Restore saved environment variables for lt_var in LANG LANGUAGE LC_ALL LC_CTYPE LC_COLLATE LC_MESSAGES do eval "if test \"\${save_$lt_var+set}\" = set; then $lt_var=\$save_$lt_var; export $lt_var else $lt_unset $lt_var fi" done # Now prepare to actually exec the command. exec_cmd="\$cmd$args" else # Display what would be done. if test -n "$shlibpath_var"; then eval "\$ECHO \"\$shlibpath_var=\$$shlibpath_var\"" $ECHO "export $shlibpath_var" fi $ECHO "$cmd$args" exit $EXIT_SUCCESS fi } test "$mode" = execute && func_mode_execute ${1+"$@"} # func_mode_finish arg... func_mode_finish () { $opt_debug libdirs="$nonopt" admincmds= if test -n "$finish_cmds$finish_eval" && test -n "$libdirs"; then for dir do libdirs="$libdirs $dir" done for libdir in $libdirs; do if test -n "$finish_cmds"; then # Do each command in the finish commands. func_execute_cmds "$finish_cmds" 'admincmds="$admincmds '"$cmd"'"' fi if test -n "$finish_eval"; then # Do the single finish_eval. eval cmds=\"$finish_eval\" $opt_dry_run || eval "$cmds" || admincmds="$admincmds $cmds" fi done fi # Exit here if they wanted silent mode. $opt_silent && exit $EXIT_SUCCESS $ECHO "X----------------------------------------------------------------------" | $Xsed $ECHO "Libraries have been installed in:" for libdir in $libdirs; do $ECHO " $libdir" done $ECHO $ECHO "If you ever happen to want to link against installed libraries" $ECHO "in a given directory, LIBDIR, you must either use libtool, and" $ECHO "specify the full pathname of the library, or use the \`-LLIBDIR'" $ECHO "flag during linking and do at least one of the following:" if test -n "$shlibpath_var"; then $ECHO " - add LIBDIR to the \`$shlibpath_var' environment variable" $ECHO " during execution" fi if test -n "$runpath_var"; then $ECHO " - add LIBDIR to the \`$runpath_var' environment variable" $ECHO " during linking" fi if test -n "$hardcode_libdir_flag_spec"; then libdir=LIBDIR eval flag=\"$hardcode_libdir_flag_spec\" $ECHO " - use the \`$flag' linker flag" fi if test -n "$admincmds"; then $ECHO " - have your system administrator run these commands:$admincmds" fi if test -f /etc/ld.so.conf; then $ECHO " - have your system administrator add LIBDIR to \`/etc/ld.so.conf'" fi $ECHO $ECHO "See any operating system documentation about shared libraries for" case $host in solaris2.[6789]|solaris2.1[0-9]) $ECHO "more information, such as the ld(1), crle(1) and ld.so(8) manual" $ECHO "pages." ;; *) $ECHO "more information, such as the ld(1) and ld.so(8) manual pages." ;; esac $ECHO "X----------------------------------------------------------------------" | $Xsed exit $EXIT_SUCCESS } test "$mode" = finish && func_mode_finish ${1+"$@"} # func_mode_install arg... func_mode_install () { $opt_debug # There may be an optional sh(1) argument at the beginning of # install_prog (especially on Windows NT). if test "$nonopt" = "$SHELL" || test "$nonopt" = /bin/sh || # Allow the use of GNU shtool's install command. $ECHO "X$nonopt" | $GREP shtool >/dev/null; then # Aesthetically quote it. func_quote_for_eval "$nonopt" install_prog="$func_quote_for_eval_result " arg=$1 shift else install_prog= arg=$nonopt fi # The real first argument should be the name of the installation program. # Aesthetically quote it. func_quote_for_eval "$arg" install_prog="$install_prog$func_quote_for_eval_result" # We need to accept at least all the BSD install flags. dest= files= opts= prev= install_type= isdir=no stripme= for arg do if test -n "$dest"; then files="$files $dest" dest=$arg continue fi case $arg in -d) isdir=yes ;; -f) case " $install_prog " in *[\\\ /]cp\ *) ;; *) prev=$arg ;; esac ;; -g | -m | -o) prev=$arg ;; -s) stripme=" -s" continue ;; -*) ;; *) # If the previous option needed an argument, then skip it. if test -n "$prev"; then prev= else dest=$arg continue fi ;; esac # Aesthetically quote the argument. func_quote_for_eval "$arg" install_prog="$install_prog $func_quote_for_eval_result" done test -z "$install_prog" && \ func_fatal_help "you must specify an install program" test -n "$prev" && \ func_fatal_help "the \`$prev' option requires an argument" if test -z "$files"; then if test -z "$dest"; then func_fatal_help "no file or destination specified" else func_fatal_help "you must specify a destination" fi fi # Strip any trailing slash from the destination. func_stripname '' '/' "$dest" dest=$func_stripname_result # Check to see that the destination is a directory. test -d "$dest" && isdir=yes if test "$isdir" = yes; then destdir="$dest" destname= else func_dirname_and_basename "$dest" "" "." destdir="$func_dirname_result" destname="$func_basename_result" # Not a directory, so check to see that there is only one file specified. set dummy $files; shift test "$#" -gt 1 && \ func_fatal_help "\`$dest' is not a directory" fi case $destdir in [\\/]* | [A-Za-z]:[\\/]*) ;; *) for file in $files; do case $file in *.lo) ;; *) func_fatal_help "\`$destdir' must be an absolute directory name" ;; esac done ;; esac # This variable tells wrapper scripts just to set variables rather # than running their programs. libtool_install_magic="$magic" staticlibs= future_libdirs= current_libdirs= for file in $files; do # Do each installation. case $file in *.$libext) # Do the static libraries later. staticlibs="$staticlibs $file" ;; *.la) # Check to see that this really is a libtool archive. func_lalib_unsafe_p "$file" \ || func_fatal_help "\`$file' is not a valid libtool archive" library_names= old_library= relink_command= func_source "$file" # Add the libdir to current_libdirs if it is the destination. if test "X$destdir" = "X$libdir"; then case "$current_libdirs " in *" $libdir "*) ;; *) current_libdirs="$current_libdirs $libdir" ;; esac else # Note the libdir as a future libdir. case "$future_libdirs " in *" $libdir "*) ;; *) future_libdirs="$future_libdirs $libdir" ;; esac fi func_dirname "$file" "/" "" dir="$func_dirname_result" dir="$dir$objdir" if test -n "$relink_command"; then # Determine the prefix the user has applied to our future dir. inst_prefix_dir=`$ECHO "X$destdir" | $Xsed -e "s%$libdir\$%%"` # Don't allow the user to place us outside of our expected # location b/c this prevents finding dependent libraries that # are installed to the same prefix. # At present, this check doesn't affect windows .dll's that # are installed into $libdir/../bin (currently, that works fine) # but it's something to keep an eye on. test "$inst_prefix_dir" = "$destdir" && \ func_fatal_error "error: cannot install \`$file' to a directory not ending in $libdir" if test -n "$inst_prefix_dir"; then # Stick the inst_prefix_dir data into the link command. relink_command=`$ECHO "X$relink_command" | $Xsed -e "s%@inst_prefix_dir@%-inst-prefix-dir $inst_prefix_dir%"` else relink_command=`$ECHO "X$relink_command" | $Xsed -e "s%@inst_prefix_dir@%%"` fi func_warning "relinking \`$file'" func_show_eval "$relink_command" \ 'func_fatal_error "error: relink \`$file'\'' with the above command before installing it"' fi # See the names of the shared library. set dummy $library_names; shift if test -n "$1"; then realname="$1" shift srcname="$realname" test -n "$relink_command" && srcname="$realname"T # Install the shared library and build the symlinks. func_show_eval "$install_prog $dir/$srcname $destdir/$realname" \ 'exit $?' tstripme="$stripme" case $host_os in cygwin* | mingw* | pw32* | cegcc*) case $realname in *.dll.a) tstripme="" ;; esac ;; esac if test -n "$tstripme" && test -n "$striplib"; then func_show_eval "$striplib $destdir/$realname" 'exit $?' fi if test "$#" -gt 0; then # Delete the old symlinks, and create new ones. # Try `ln -sf' first, because the `ln' binary might depend on # the symlink we replace! Solaris /bin/ln does not understand -f, # so we also need to try rm && ln -s. for linkname do test "$linkname" != "$realname" \ && func_show_eval "(cd $destdir && { $LN_S -f $realname $linkname || { $RM $linkname && $LN_S $realname $linkname; }; })" done fi # Do each command in the postinstall commands. lib="$destdir/$realname" func_execute_cmds "$postinstall_cmds" 'exit $?' fi # Install the pseudo-library for information purposes. func_basename "$file" name="$func_basename_result" instname="$dir/$name"i func_show_eval "$install_prog $instname $destdir/$name" 'exit $?' # Maybe install the static library, too. test -n "$old_library" && staticlibs="$staticlibs $dir/$old_library" ;; *.lo) # Install (i.e. copy) a libtool object. # Figure out destination file name, if it wasn't already specified. if test -n "$destname"; then destfile="$destdir/$destname" else func_basename "$file" destfile="$func_basename_result" destfile="$destdir/$destfile" fi # Deduce the name of the destination old-style object file. case $destfile in *.lo) func_lo2o "$destfile" staticdest=$func_lo2o_result ;; *.$objext) staticdest="$destfile" destfile= ;; *) func_fatal_help "cannot copy a libtool object to \`$destfile'" ;; esac # Install the libtool object if requested. test -n "$destfile" && \ func_show_eval "$install_prog $file $destfile" 'exit $?' # Install the old object if enabled. if test "$build_old_libs" = yes; then # Deduce the name of the old-style object file. func_lo2o "$file" staticobj=$func_lo2o_result func_show_eval "$install_prog \$staticobj \$staticdest" 'exit $?' fi exit $EXIT_SUCCESS ;; *) # Figure out destination file name, if it wasn't already specified. if test -n "$destname"; then destfile="$destdir/$destname" else func_basename "$file" destfile="$func_basename_result" destfile="$destdir/$destfile" fi # If the file is missing, and there is a .exe on the end, strip it # because it is most likely a libtool script we actually want to # install stripped_ext="" case $file in *.exe) if test ! -f "$file"; then func_stripname '' '.exe' "$file" file=$func_stripname_result stripped_ext=".exe" fi ;; esac # Do a test to see if this is really a libtool program. case $host in *cygwin* | *mingw*) if func_ltwrapper_executable_p "$file"; then func_ltwrapper_scriptname "$file" wrapper=$func_ltwrapper_scriptname_result else func_stripname '' '.exe' "$file" wrapper=$func_stripname_result fi ;; *) wrapper=$file ;; esac if func_ltwrapper_script_p "$wrapper"; then notinst_deplibs= relink_command= func_source "$wrapper" # Check the variables that should have been set. test -z "$generated_by_libtool_version" && \ func_fatal_error "invalid libtool wrapper script \`$wrapper'" finalize=yes for lib in $notinst_deplibs; do # Check to see that each library is installed. libdir= if test -f "$lib"; then func_source "$lib" fi libfile="$libdir/"`$ECHO "X$lib" | $Xsed -e 's%^.*/%%g'` ### testsuite: skip nested quoting test if test -n "$libdir" && test ! -f "$libfile"; then func_warning "\`$lib' has not been installed in \`$libdir'" finalize=no fi done relink_command= func_source "$wrapper" outputname= if test "$fast_install" = no && test -n "$relink_command"; then $opt_dry_run || { if test "$finalize" = yes; then tmpdir=`func_mktempdir` func_basename "$file$stripped_ext" file="$func_basename_result" outputname="$tmpdir/$file" # Replace the output file specification. relink_command=`$ECHO "X$relink_command" | $Xsed -e 's%@OUTPUT@%'"$outputname"'%g'` $opt_silent || { func_quote_for_expand "$relink_command" eval "func_echo $func_quote_for_expand_result" } if eval "$relink_command"; then : else func_error "error: relink \`$file' with the above command before installing it" $opt_dry_run || ${RM}r "$tmpdir" continue fi file="$outputname" else func_warning "cannot relink \`$file'" fi } else # Install the binary that we compiled earlier. file=`$ECHO "X$file$stripped_ext" | $Xsed -e "s%\([^/]*\)$%$objdir/\1%"` fi fi # remove .exe since cygwin /usr/bin/install will append another # one anyway case $install_prog,$host in */usr/bin/install*,*cygwin*) case $file:$destfile in *.exe:*.exe) # this is ok ;; *.exe:*) destfile=$destfile.exe ;; *:*.exe) func_stripname '' '.exe' "$destfile" destfile=$func_stripname_result ;; esac ;; esac func_show_eval "$install_prog\$stripme \$file \$destfile" 'exit $?' $opt_dry_run || if test -n "$outputname"; then ${RM}r "$tmpdir" fi ;; esac done for file in $staticlibs; do func_basename "$file" name="$func_basename_result" # Set up the ranlib parameters. oldlib="$destdir/$name" func_show_eval "$install_prog \$file \$oldlib" 'exit $?' if test -n "$stripme" && test -n "$old_striplib"; then func_show_eval "$old_striplib $oldlib" 'exit $?' fi # Do each command in the postinstall commands. func_execute_cmds "$old_postinstall_cmds" 'exit $?' done test -n "$future_libdirs" && \ func_warning "remember to run \`$progname --finish$future_libdirs'" if test -n "$current_libdirs"; then # Maybe just do a dry run. $opt_dry_run && current_libdirs=" -n$current_libdirs" exec_cmd='$SHELL $progpath $preserve_args --finish$current_libdirs' else exit $EXIT_SUCCESS fi } test "$mode" = install && func_mode_install ${1+"$@"} # func_generate_dlsyms outputname originator pic_p # Extract symbols from dlprefiles and create ${outputname}S.o with # a dlpreopen symbol table. func_generate_dlsyms () { $opt_debug my_outputname="$1" my_originator="$2" my_pic_p="${3-no}" my_prefix=`$ECHO "$my_originator" | sed 's%[^a-zA-Z0-9]%_%g'` my_dlsyms= if test -n "$dlfiles$dlprefiles" || test "$dlself" != no; then if test -n "$NM" && test -n "$global_symbol_pipe"; then my_dlsyms="${my_outputname}S.c" else func_error "not configured to extract global symbols from dlpreopened files" fi fi if test -n "$my_dlsyms"; then case $my_dlsyms in "") ;; *.c) # Discover the nlist of each of the dlfiles. nlist="$output_objdir/${my_outputname}.nm" func_show_eval "$RM $nlist ${nlist}S ${nlist}T" # Parse the name list into a source file. func_verbose "creating $output_objdir/$my_dlsyms" $opt_dry_run || $ECHO > "$output_objdir/$my_dlsyms" "\ /* $my_dlsyms - symbol resolution table for \`$my_outputname' dlsym emulation. */ /* Generated by $PROGRAM (GNU $PACKAGE$TIMESTAMP) $VERSION */ #ifdef __cplusplus extern \"C\" { #endif /* External symbol declarations for the compiler. */\ " if test "$dlself" = yes; then func_verbose "generating symbol list for \`$output'" $opt_dry_run || echo ': @PROGRAM@ ' > "$nlist" # Add our own program objects to the symbol list. progfiles=`$ECHO "X$objs$old_deplibs" | $SP2NL | $Xsed -e "$lo2o" | $NL2SP` for progfile in $progfiles; do func_verbose "extracting global C symbols from \`$progfile'" $opt_dry_run || eval "$NM $progfile | $global_symbol_pipe >> '$nlist'" done if test -n "$exclude_expsyms"; then $opt_dry_run || { eval '$EGREP -v " ($exclude_expsyms)$" "$nlist" > "$nlist"T' eval '$MV "$nlist"T "$nlist"' } fi if test -n "$export_symbols_regex"; then $opt_dry_run || { eval '$EGREP -e "$export_symbols_regex" "$nlist" > "$nlist"T' eval '$MV "$nlist"T "$nlist"' } fi # Prepare the list of exported symbols if test -z "$export_symbols"; then export_symbols="$output_objdir/$outputname.exp" $opt_dry_run || { $RM $export_symbols eval "${SED} -n -e '/^: @PROGRAM@ $/d' -e 's/^.* \(.*\)$/\1/p' "'< "$nlist" > "$export_symbols"' case $host in *cygwin* | *mingw* | *cegcc* ) eval "echo EXPORTS "'> "$output_objdir/$outputname.def"' eval 'cat "$export_symbols" >> "$output_objdir/$outputname.def"' ;; esac } else $opt_dry_run || { eval "${SED} -e 's/\([].[*^$]\)/\\\\\1/g' -e 's/^/ /' -e 's/$/$/'"' < "$export_symbols" > "$output_objdir/$outputname.exp"' eval '$GREP -f "$output_objdir/$outputname.exp" < "$nlist" > "$nlist"T' eval '$MV "$nlist"T "$nlist"' case $host in *cygwin | *mingw* | *cegcc* ) eval "echo EXPORTS "'> "$output_objdir/$outputname.def"' eval 'cat "$nlist" >> "$output_objdir/$outputname.def"' ;; esac } fi fi for dlprefile in $dlprefiles; do func_verbose "extracting global C symbols from \`$dlprefile'" func_basename "$dlprefile" name="$func_basename_result" $opt_dry_run || { eval '$ECHO ": $name " >> "$nlist"' eval "$NM $dlprefile 2>/dev/null | $global_symbol_pipe >> '$nlist'" } done $opt_dry_run || { # Make sure we have at least an empty file. test -f "$nlist" || : > "$nlist" if test -n "$exclude_expsyms"; then $EGREP -v " ($exclude_expsyms)$" "$nlist" > "$nlist"T $MV "$nlist"T "$nlist" fi # Try sorting and uniquifying the output. if $GREP -v "^: " < "$nlist" | if sort -k 3 /dev/null 2>&1; then sort -k 3 else sort +2 fi | uniq > "$nlist"S; then : else $GREP -v "^: " < "$nlist" > "$nlist"S fi if test -f "$nlist"S; then eval "$global_symbol_to_cdecl"' < "$nlist"S >> "$output_objdir/$my_dlsyms"' else $ECHO '/* NONE */' >> "$output_objdir/$my_dlsyms" fi $ECHO >> "$output_objdir/$my_dlsyms" "\ /* The mapping between symbol names and symbols. */ typedef struct { const char *name; void *address; } lt_dlsymlist; " case $host in *cygwin* | *mingw* | *cegcc* ) $ECHO >> "$output_objdir/$my_dlsyms" "\ /* DATA imports from DLLs on WIN32 con't be const, because runtime relocations are performed -- see ld's documentation on pseudo-relocs. */" lt_dlsym_const= ;; *osf5*) echo >> "$output_objdir/$my_dlsyms" "\ /* This system does not cope well with relocations in const data */" lt_dlsym_const= ;; *) lt_dlsym_const=const ;; esac $ECHO >> "$output_objdir/$my_dlsyms" "\ extern $lt_dlsym_const lt_dlsymlist lt_${my_prefix}_LTX_preloaded_symbols[]; $lt_dlsym_const lt_dlsymlist lt_${my_prefix}_LTX_preloaded_symbols[] = {\ { \"$my_originator\", (void *) 0 }," case $need_lib_prefix in no) eval "$global_symbol_to_c_name_address" < "$nlist" >> "$output_objdir/$my_dlsyms" ;; *) eval "$global_symbol_to_c_name_address_lib_prefix" < "$nlist" >> "$output_objdir/$my_dlsyms" ;; esac $ECHO >> "$output_objdir/$my_dlsyms" "\ {0, (void *) 0} }; /* This works around a problem in FreeBSD linker */ #ifdef FREEBSD_WORKAROUND static const void *lt_preloaded_setup() { return lt_${my_prefix}_LTX_preloaded_symbols; } #endif #ifdef __cplusplus } #endif\ " } # !$opt_dry_run pic_flag_for_symtable= case "$compile_command " in *" -static "*) ;; *) case $host in # compiling the symbol table file with pic_flag works around # a FreeBSD bug that causes programs to crash when -lm is # linked before any other PIC object. But we must not use # pic_flag when linking with -static. The problem exists in # FreeBSD 2.2.6 and is fixed in FreeBSD 3.1. *-*-freebsd2*|*-*-freebsd3.0*|*-*-freebsdelf3.0*) pic_flag_for_symtable=" $pic_flag -DFREEBSD_WORKAROUND" ;; *-*-hpux*) pic_flag_for_symtable=" $pic_flag" ;; *) if test "X$my_pic_p" != Xno; then pic_flag_for_symtable=" $pic_flag" fi ;; esac ;; esac symtab_cflags= for arg in $LTCFLAGS; do case $arg in -pie | -fpie | -fPIE) ;; *) symtab_cflags="$symtab_cflags $arg" ;; esac done # Now compile the dynamic symbol file. func_show_eval '(cd $output_objdir && $LTCC$symtab_cflags -c$no_builtin_flag$pic_flag_for_symtable "$my_dlsyms")' 'exit $?' # Clean up the generated files. func_show_eval '$RM "$output_objdir/$my_dlsyms" "$nlist" "${nlist}S" "${nlist}T"' # Transform the symbol file into the correct name. symfileobj="$output_objdir/${my_outputname}S.$objext" case $host in *cygwin* | *mingw* | *cegcc* ) if test -f "$output_objdir/$my_outputname.def"; then compile_command=`$ECHO "X$compile_command" | $Xsed -e "s%@SYMFILE@%$output_objdir/$my_outputname.def $symfileobj%"` finalize_command=`$ECHO "X$finalize_command" | $Xsed -e "s%@SYMFILE@%$output_objdir/$my_outputname.def $symfileobj%"` else compile_command=`$ECHO "X$compile_command" | $Xsed -e "s%@SYMFILE@%$symfileobj%"` finalize_command=`$ECHO "X$finalize_command" | $Xsed -e "s%@SYMFILE@%$symfileobj%"` fi ;; *) compile_command=`$ECHO "X$compile_command" | $Xsed -e "s%@SYMFILE@%$symfileobj%"` finalize_command=`$ECHO "X$finalize_command" | $Xsed -e "s%@SYMFILE@%$symfileobj%"` ;; esac ;; *) func_fatal_error "unknown suffix for \`$my_dlsyms'" ;; esac else # We keep going just in case the user didn't refer to # lt_preloaded_symbols. The linker will fail if global_symbol_pipe # really was required. # Nullify the symbol file. compile_command=`$ECHO "X$compile_command" | $Xsed -e "s% @SYMFILE@%%"` finalize_command=`$ECHO "X$finalize_command" | $Xsed -e "s% @SYMFILE@%%"` fi } # func_win32_libid arg # return the library type of file 'arg' # # Need a lot of goo to handle *both* DLLs and import libs # Has to be a shell function in order to 'eat' the argument # that is supplied when $file_magic_command is called. func_win32_libid () { $opt_debug win32_libid_type="unknown" win32_fileres=`file -L $1 2>/dev/null` case $win32_fileres in *ar\ archive\ import\ library*) # definitely import win32_libid_type="x86 archive import" ;; *ar\ archive*) # could be an import, or static if eval $OBJDUMP -f $1 | $SED -e '10q' 2>/dev/null | $EGREP 'file format pe-i386(.*architecture: i386)?' >/dev/null ; then win32_nmres=`eval $NM -f posix -A $1 | $SED -n -e ' 1,100{ / I /{ s,.*,import, p q } }'` case $win32_nmres in import*) win32_libid_type="x86 archive import";; *) win32_libid_type="x86 archive static";; esac fi ;; *DLL*) win32_libid_type="x86 DLL" ;; *executable*) # but shell scripts are "executable" too... case $win32_fileres in *MS\ Windows\ PE\ Intel*) win32_libid_type="x86 DLL" ;; esac ;; esac $ECHO "$win32_libid_type" } # func_extract_an_archive dir oldlib func_extract_an_archive () { $opt_debug f_ex_an_ar_dir="$1"; shift f_ex_an_ar_oldlib="$1" func_show_eval "(cd \$f_ex_an_ar_dir && $AR x \"\$f_ex_an_ar_oldlib\")" 'exit $?' if ($AR t "$f_ex_an_ar_oldlib" | sort | sort -uc >/dev/null 2>&1); then : else func_fatal_error "object name conflicts in archive: $f_ex_an_ar_dir/$f_ex_an_ar_oldlib" fi } # func_extract_archives gentop oldlib ... func_extract_archives () { $opt_debug my_gentop="$1"; shift my_oldlibs=${1+"$@"} my_oldobjs="" my_xlib="" my_xabs="" my_xdir="" for my_xlib in $my_oldlibs; do # Extract the objects. case $my_xlib in [\\/]* | [A-Za-z]:[\\/]*) my_xabs="$my_xlib" ;; *) my_xabs=`pwd`"/$my_xlib" ;; esac func_basename "$my_xlib" my_xlib="$func_basename_result" my_xlib_u=$my_xlib while :; do case " $extracted_archives " in *" $my_xlib_u "*) func_arith $extracted_serial + 1 extracted_serial=$func_arith_result my_xlib_u=lt$extracted_serial-$my_xlib ;; *) break ;; esac done extracted_archives="$extracted_archives $my_xlib_u" my_xdir="$my_gentop/$my_xlib_u" func_mkdir_p "$my_xdir" case $host in *-darwin*) func_verbose "Extracting $my_xabs" # Do not bother doing anything if just a dry run $opt_dry_run || { darwin_orig_dir=`pwd` cd $my_xdir || exit $? darwin_archive=$my_xabs darwin_curdir=`pwd` darwin_base_archive=`basename "$darwin_archive"` darwin_arches=`$LIPO -info "$darwin_archive" 2>/dev/null | $GREP Architectures 2>/dev/null || true` if test -n "$darwin_arches"; then darwin_arches=`$ECHO "$darwin_arches" | $SED -e 's/.*are://'` darwin_arch= func_verbose "$darwin_base_archive has multiple architectures $darwin_arches" for darwin_arch in $darwin_arches ; do func_mkdir_p "unfat-$$/${darwin_base_archive}-${darwin_arch}" $LIPO -thin $darwin_arch -output "unfat-$$/${darwin_base_archive}-${darwin_arch}/${darwin_base_archive}" "${darwin_archive}" cd "unfat-$$/${darwin_base_archive}-${darwin_arch}" func_extract_an_archive "`pwd`" "${darwin_base_archive}" cd "$darwin_curdir" $RM "unfat-$$/${darwin_base_archive}-${darwin_arch}/${darwin_base_archive}" done # $darwin_arches ## Okay now we've a bunch of thin objects, gotta fatten them up :) darwin_filelist=`find unfat-$$ -type f -name \*.o -print -o -name \*.lo -print | $SED -e "$basename" | sort -u` darwin_file= darwin_files= for darwin_file in $darwin_filelist; do darwin_files=`find unfat-$$ -name $darwin_file -print | $NL2SP` $LIPO -create -output "$darwin_file" $darwin_files done # $darwin_filelist $RM -rf unfat-$$ cd "$darwin_orig_dir" else cd $darwin_orig_dir func_extract_an_archive "$my_xdir" "$my_xabs" fi # $darwin_arches } # !$opt_dry_run ;; *) func_extract_an_archive "$my_xdir" "$my_xabs" ;; esac my_oldobjs="$my_oldobjs "`find $my_xdir -name \*.$objext -print -o -name \*.lo -print | $NL2SP` done func_extract_archives_result="$my_oldobjs" } # func_emit_wrapper_part1 [arg=no] # # Emit the first part of a libtool wrapper script on stdout. # For more information, see the description associated with # func_emit_wrapper(), below. func_emit_wrapper_part1 () { func_emit_wrapper_part1_arg1=no if test -n "$1" ; then func_emit_wrapper_part1_arg1=$1 fi $ECHO "\ #! $SHELL # $output - temporary wrapper script for $objdir/$outputname # Generated by $PROGRAM (GNU $PACKAGE$TIMESTAMP) $VERSION # # The $output program cannot be directly executed until all the libtool # libraries that it depends on are installed. # # This wrapper script should never be moved out of the build directory. # If it is, it will not operate correctly. # Sed substitution that helps us do robust quoting. It backslashifies # metacharacters that are still active within double-quoted strings. Xsed='${SED} -e 1s/^X//' sed_quote_subst='$sed_quote_subst' # Be Bourne compatible if test -n \"\${ZSH_VERSION+set}\" && (emulate sh) >/dev/null 2>&1; then emulate sh NULLCMD=: # Zsh 3.x and 4.x performs word splitting on \${1+\"\$@\"}, which # is contrary to our usage. Disable this feature. alias -g '\${1+\"\$@\"}'='\"\$@\"' setopt NO_GLOB_SUBST else case \`(set -o) 2>/dev/null\` in *posix*) set -o posix;; esac fi BIN_SH=xpg4; export BIN_SH # for Tru64 DUALCASE=1; export DUALCASE # for MKS sh # The HP-UX ksh and POSIX shell print the target directory to stdout # if CDPATH is set. (unset CDPATH) >/dev/null 2>&1 && unset CDPATH relink_command=\"$relink_command\" # This environment variable determines our operation mode. if test \"\$libtool_install_magic\" = \"$magic\"; then # install mode needs the following variables: generated_by_libtool_version='$macro_version' notinst_deplibs='$notinst_deplibs' else # When we are sourced in execute mode, \$file and \$ECHO are already set. if test \"\$libtool_execute_magic\" != \"$magic\"; then ECHO=\"$qecho\" file=\"\$0\" # Make sure echo works. if test \"X\$1\" = X--no-reexec; then # Discard the --no-reexec flag, and continue. shift elif test \"X\`{ \$ECHO '\t'; } 2>/dev/null\`\" = 'X\t'; then # Yippee, \$ECHO works! : else # Restart under the correct shell, and then maybe \$ECHO will work. exec $SHELL \"\$0\" --no-reexec \${1+\"\$@\"} fi fi\ " $ECHO "\ # Find the directory that this script lives in. thisdir=\`\$ECHO \"X\$file\" | \$Xsed -e 's%/[^/]*$%%'\` test \"x\$thisdir\" = \"x\$file\" && thisdir=. # Follow symbolic links until we get to the real thisdir. file=\`ls -ld \"\$file\" | ${SED} -n 's/.*-> //p'\` while test -n \"\$file\"; do destdir=\`\$ECHO \"X\$file\" | \$Xsed -e 's%/[^/]*\$%%'\` # If there was a directory component, then change thisdir. if test \"x\$destdir\" != \"x\$file\"; then case \"\$destdir\" in [\\\\/]* | [A-Za-z]:[\\\\/]*) thisdir=\"\$destdir\" ;; *) thisdir=\"\$thisdir/\$destdir\" ;; esac fi file=\`\$ECHO \"X\$file\" | \$Xsed -e 's%^.*/%%'\` file=\`ls -ld \"\$thisdir/\$file\" | ${SED} -n 's/.*-> //p'\` done " } # end: func_emit_wrapper_part1 # func_emit_wrapper_part2 [arg=no] # # Emit the second part of a libtool wrapper script on stdout. # For more information, see the description associated with # func_emit_wrapper(), below. func_emit_wrapper_part2 () { func_emit_wrapper_part2_arg1=no if test -n "$1" ; then func_emit_wrapper_part2_arg1=$1 fi $ECHO "\ # Usually 'no', except on cygwin/mingw when embedded into # the cwrapper. WRAPPER_SCRIPT_BELONGS_IN_OBJDIR=$func_emit_wrapper_part2_arg1 if test \"\$WRAPPER_SCRIPT_BELONGS_IN_OBJDIR\" = \"yes\"; then # special case for '.' if test \"\$thisdir\" = \".\"; then thisdir=\`pwd\` fi # remove .libs from thisdir case \"\$thisdir\" in *[\\\\/]$objdir ) thisdir=\`\$ECHO \"X\$thisdir\" | \$Xsed -e 's%[\\\\/][^\\\\/]*$%%'\` ;; $objdir ) thisdir=. ;; esac fi # Try to get the absolute directory name. absdir=\`cd \"\$thisdir\" && pwd\` test -n \"\$absdir\" && thisdir=\"\$absdir\" " if test "$fast_install" = yes; then $ECHO "\ program=lt-'$outputname'$exeext progdir=\"\$thisdir/$objdir\" if test ! -f \"\$progdir/\$program\" || { file=\`ls -1dt \"\$progdir/\$program\" \"\$progdir/../\$program\" 2>/dev/null | ${SED} 1q\`; \\ test \"X\$file\" != \"X\$progdir/\$program\"; }; then file=\"\$\$-\$program\" if test ! -d \"\$progdir\"; then $MKDIR \"\$progdir\" else $RM \"\$progdir/\$file\" fi" $ECHO "\ # relink executable if necessary if test -n \"\$relink_command\"; then if relink_command_output=\`eval \$relink_command 2>&1\`; then : else $ECHO \"\$relink_command_output\" >&2 $RM \"\$progdir/\$file\" exit 1 fi fi $MV \"\$progdir/\$file\" \"\$progdir/\$program\" 2>/dev/null || { $RM \"\$progdir/\$program\"; $MV \"\$progdir/\$file\" \"\$progdir/\$program\"; } $RM \"\$progdir/\$file\" fi" else $ECHO "\ program='$outputname' progdir=\"\$thisdir/$objdir\" " fi $ECHO "\ if test -f \"\$progdir/\$program\"; then" # Export our shlibpath_var if we have one. if test "$shlibpath_overrides_runpath" = yes && test -n "$shlibpath_var" && test -n "$temp_rpath"; then $ECHO "\ # Add our own library path to $shlibpath_var $shlibpath_var=\"$temp_rpath\$$shlibpath_var\" # Some systems cannot cope with colon-terminated $shlibpath_var # The second colon is a workaround for a bug in BeOS R4 sed $shlibpath_var=\`\$ECHO \"X\$$shlibpath_var\" | \$Xsed -e 's/::*\$//'\` export $shlibpath_var " fi # fixup the dll searchpath if we need to. if test -n "$dllsearchpath"; then $ECHO "\ # Add the dll search path components to the executable PATH PATH=$dllsearchpath:\$PATH " fi $ECHO "\ if test \"\$libtool_execute_magic\" != \"$magic\"; then # Run the actual program with our arguments. " case $host in # Backslashes separate directories on plain windows *-*-mingw | *-*-os2* | *-cegcc*) $ECHO "\ exec \"\$progdir\\\\\$program\" \${1+\"\$@\"} " ;; *) $ECHO "\ exec \"\$progdir/\$program\" \${1+\"\$@\"} " ;; esac $ECHO "\ \$ECHO \"\$0: cannot exec \$program \$*\" 1>&2 exit 1 fi else # The program doesn't exist. \$ECHO \"\$0: error: \\\`\$progdir/\$program' does not exist\" 1>&2 \$ECHO \"This script is just a wrapper for \$program.\" 1>&2 $ECHO \"See the $PACKAGE documentation for more information.\" 1>&2 exit 1 fi fi\ " } # end: func_emit_wrapper_part2 # func_emit_wrapper [arg=no] # # Emit a libtool wrapper script on stdout. # Don't directly open a file because we may want to # incorporate the script contents within a cygwin/mingw # wrapper executable. Must ONLY be called from within # func_mode_link because it depends on a number of variables # set therein. # # ARG is the value that the WRAPPER_SCRIPT_BELONGS_IN_OBJDIR # variable will take. If 'yes', then the emitted script # will assume that the directory in which it is stored is # the $objdir directory. This is a cygwin/mingw-specific # behavior. func_emit_wrapper () { func_emit_wrapper_arg1=no if test -n "$1" ; then func_emit_wrapper_arg1=$1 fi # split this up so that func_emit_cwrapperexe_src # can call each part independently. func_emit_wrapper_part1 "${func_emit_wrapper_arg1}" func_emit_wrapper_part2 "${func_emit_wrapper_arg1}" } # func_to_host_path arg # # Convert paths to host format when used with build tools. # Intended for use with "native" mingw (where libtool itself # is running under the msys shell), or in the following cross- # build environments: # $build $host # mingw (msys) mingw [e.g. native] # cygwin mingw # *nix + wine mingw # where wine is equipped with the `winepath' executable. # In the native mingw case, the (msys) shell automatically # converts paths for any non-msys applications it launches, # but that facility isn't available from inside the cwrapper. # Similar accommodations are necessary for $host mingw and # $build cygwin. Calling this function does no harm for other # $host/$build combinations not listed above. # # ARG is the path (on $build) that should be converted to # the proper representation for $host. The result is stored # in $func_to_host_path_result. func_to_host_path () { func_to_host_path_result="$1" if test -n "$1" ; then case $host in *mingw* ) lt_sed_naive_backslashify='s|\\\\*|\\|g;s|/|\\|g;s|\\|\\\\|g' case $build in *mingw* ) # actually, msys # awkward: cmd appends spaces to result lt_sed_strip_trailing_spaces="s/[ ]*\$//" func_to_host_path_tmp1=`( cmd //c echo "$1" |\ $SED -e "$lt_sed_strip_trailing_spaces" ) 2>/dev/null || echo ""` func_to_host_path_result=`echo "$func_to_host_path_tmp1" |\ $SED -e "$lt_sed_naive_backslashify"` ;; *cygwin* ) func_to_host_path_tmp1=`cygpath -w "$1"` func_to_host_path_result=`echo "$func_to_host_path_tmp1" |\ $SED -e "$lt_sed_naive_backslashify"` ;; * ) # Unfortunately, winepath does not exit with a non-zero # error code, so we are forced to check the contents of # stdout. On the other hand, if the command is not # found, the shell will set an exit code of 127 and print # *an error message* to stdout. So we must check for both # error code of zero AND non-empty stdout, which explains # the odd construction: func_to_host_path_tmp1=`winepath -w "$1" 2>/dev/null` if test "$?" -eq 0 && test -n "${func_to_host_path_tmp1}"; then func_to_host_path_result=`echo "$func_to_host_path_tmp1" |\ $SED -e "$lt_sed_naive_backslashify"` else # Allow warning below. func_to_host_path_result="" fi ;; esac if test -z "$func_to_host_path_result" ; then func_error "Could not determine host path corresponding to" func_error " '$1'" func_error "Continuing, but uninstalled executables may not work." # Fallback: func_to_host_path_result="$1" fi ;; esac fi } # end: func_to_host_path # func_to_host_pathlist arg # # Convert pathlists to host format when used with build tools. # See func_to_host_path(), above. This function supports the # following $build/$host combinations (but does no harm for # combinations not listed here): # $build $host # mingw (msys) mingw [e.g. native] # cygwin mingw # *nix + wine mingw # # Path separators are also converted from $build format to # $host format. If ARG begins or ends with a path separator # character, it is preserved (but converted to $host format) # on output. # # ARG is a pathlist (on $build) that should be converted to # the proper representation on $host. The result is stored # in $func_to_host_pathlist_result. func_to_host_pathlist () { func_to_host_pathlist_result="$1" if test -n "$1" ; then case $host in *mingw* ) lt_sed_naive_backslashify='s|\\\\*|\\|g;s|/|\\|g;s|\\|\\\\|g' # Remove leading and trailing path separator characters from # ARG. msys behavior is inconsistent here, cygpath turns them # into '.;' and ';.', and winepath ignores them completely. func_to_host_pathlist_tmp2="$1" # Once set for this call, this variable should not be # reassigned. It is used in tha fallback case. func_to_host_pathlist_tmp1=`echo "$func_to_host_pathlist_tmp2" |\ $SED -e 's|^:*||' -e 's|:*$||'` case $build in *mingw* ) # Actually, msys. # Awkward: cmd appends spaces to result. lt_sed_strip_trailing_spaces="s/[ ]*\$//" func_to_host_pathlist_tmp2=`( cmd //c echo "$func_to_host_pathlist_tmp1" |\ $SED -e "$lt_sed_strip_trailing_spaces" ) 2>/dev/null || echo ""` func_to_host_pathlist_result=`echo "$func_to_host_pathlist_tmp2" |\ $SED -e "$lt_sed_naive_backslashify"` ;; *cygwin* ) func_to_host_pathlist_tmp2=`cygpath -w -p "$func_to_host_pathlist_tmp1"` func_to_host_pathlist_result=`echo "$func_to_host_pathlist_tmp2" |\ $SED -e "$lt_sed_naive_backslashify"` ;; * ) # unfortunately, winepath doesn't convert pathlists func_to_host_pathlist_result="" func_to_host_pathlist_oldIFS=$IFS IFS=: for func_to_host_pathlist_f in $func_to_host_pathlist_tmp1 ; do IFS=$func_to_host_pathlist_oldIFS if test -n "$func_to_host_pathlist_f" ; then func_to_host_path "$func_to_host_pathlist_f" if test -n "$func_to_host_path_result" ; then if test -z "$func_to_host_pathlist_result" ; then func_to_host_pathlist_result="$func_to_host_path_result" else func_to_host_pathlist_result="$func_to_host_pathlist_result;$func_to_host_path_result" fi fi fi IFS=: done IFS=$func_to_host_pathlist_oldIFS ;; esac if test -z "$func_to_host_pathlist_result" ; then func_error "Could not determine the host path(s) corresponding to" func_error " '$1'" func_error "Continuing, but uninstalled executables may not work." # Fallback. This may break if $1 contains DOS-style drive # specifications. The fix is not to complicate the expression # below, but for the user to provide a working wine installation # with winepath so that path translation in the cross-to-mingw # case works properly. lt_replace_pathsep_nix_to_dos="s|:|;|g" func_to_host_pathlist_result=`echo "$func_to_host_pathlist_tmp1" |\ $SED -e "$lt_replace_pathsep_nix_to_dos"` fi # Now, add the leading and trailing path separators back case "$1" in :* ) func_to_host_pathlist_result=";$func_to_host_pathlist_result" ;; esac case "$1" in *: ) func_to_host_pathlist_result="$func_to_host_pathlist_result;" ;; esac ;; esac fi } # end: func_to_host_pathlist # func_emit_cwrapperexe_src # emit the source code for a wrapper executable on stdout # Must ONLY be called from within func_mode_link because # it depends on a number of variable set therein. func_emit_cwrapperexe_src () { cat < #include #ifdef _MSC_VER # include # include # include # define setmode _setmode #else # include # include # ifdef __CYGWIN__ # include # define HAVE_SETENV # ifdef __STRICT_ANSI__ char *realpath (const char *, char *); int putenv (char *); int setenv (const char *, const char *, int); # endif # endif #endif #include #include #include #include #include #include #include #include #if defined(PATH_MAX) # define LT_PATHMAX PATH_MAX #elif defined(MAXPATHLEN) # define LT_PATHMAX MAXPATHLEN #else # define LT_PATHMAX 1024 #endif #ifndef S_IXOTH # define S_IXOTH 0 #endif #ifndef S_IXGRP # define S_IXGRP 0 #endif #ifdef _MSC_VER # define S_IXUSR _S_IEXEC # define stat _stat # ifndef _INTPTR_T_DEFINED # define intptr_t int # endif #endif #ifndef DIR_SEPARATOR # define DIR_SEPARATOR '/' # define PATH_SEPARATOR ':' #endif #if defined (_WIN32) || defined (__MSDOS__) || defined (__DJGPP__) || \ defined (__OS2__) # define HAVE_DOS_BASED_FILE_SYSTEM # define FOPEN_WB "wb" # ifndef DIR_SEPARATOR_2 # define DIR_SEPARATOR_2 '\\' # endif # ifndef PATH_SEPARATOR_2 # define PATH_SEPARATOR_2 ';' # endif #endif #ifndef DIR_SEPARATOR_2 # define IS_DIR_SEPARATOR(ch) ((ch) == DIR_SEPARATOR) #else /* DIR_SEPARATOR_2 */ # define IS_DIR_SEPARATOR(ch) \ (((ch) == DIR_SEPARATOR) || ((ch) == DIR_SEPARATOR_2)) #endif /* DIR_SEPARATOR_2 */ #ifndef PATH_SEPARATOR_2 # define IS_PATH_SEPARATOR(ch) ((ch) == PATH_SEPARATOR) #else /* PATH_SEPARATOR_2 */ # define IS_PATH_SEPARATOR(ch) ((ch) == PATH_SEPARATOR_2) #endif /* PATH_SEPARATOR_2 */ #ifdef __CYGWIN__ # define FOPEN_WB "wb" #endif #ifndef FOPEN_WB # define FOPEN_WB "w" #endif #ifndef _O_BINARY # define _O_BINARY 0 #endif #define XMALLOC(type, num) ((type *) xmalloc ((num) * sizeof(type))) #define XFREE(stale) do { \ if (stale) { free ((void *) stale); stale = 0; } \ } while (0) #undef LTWRAPPER_DEBUGPRINTF #if defined DEBUGWRAPPER # define LTWRAPPER_DEBUGPRINTF(args) ltwrapper_debugprintf args static void ltwrapper_debugprintf (const char *fmt, ...) { va_list args; va_start (args, fmt); (void) vfprintf (stderr, fmt, args); va_end (args); } #else # define LTWRAPPER_DEBUGPRINTF(args) #endif const char *program_name = NULL; void *xmalloc (size_t num); char *xstrdup (const char *string); const char *base_name (const char *name); char *find_executable (const char *wrapper); char *chase_symlinks (const char *pathspec); int make_executable (const char *path); int check_executable (const char *path); char *strendzap (char *str, const char *pat); void lt_fatal (const char *message, ...); void lt_setenv (const char *name, const char *value); char *lt_extend_str (const char *orig_value, const char *add, int to_end); void lt_opt_process_env_set (const char *arg); void lt_opt_process_env_prepend (const char *arg); void lt_opt_process_env_append (const char *arg); int lt_split_name_value (const char *arg, char** name, char** value); void lt_update_exe_path (const char *name, const char *value); void lt_update_lib_path (const char *name, const char *value); static const char *script_text_part1 = EOF func_emit_wrapper_part1 yes | $SED -e 's/\([\\"]\)/\\\1/g' \ -e 's/^/ "/' -e 's/$/\\n"/' echo ";" cat <"))); for (i = 0; i < newargc; i++) { LTWRAPPER_DEBUGPRINTF (("(main) newargz[%d] : %s\n", i, (newargz[i] ? newargz[i] : ""))); } EOF case $host_os in mingw*) cat <<"EOF" /* execv doesn't actually work on mingw as expected on unix */ rval = _spawnv (_P_WAIT, lt_argv_zero, (const char * const *) newargz); if (rval == -1) { /* failed to start process */ LTWRAPPER_DEBUGPRINTF (("(main) failed to launch target \"%s\": errno = %d\n", lt_argv_zero, errno)); return 127; } return rval; EOF ;; *) cat <<"EOF" execv (lt_argv_zero, newargz); return rval; /* =127, but avoids unused variable warning */ EOF ;; esac cat <<"EOF" } void * xmalloc (size_t num) { void *p = (void *) malloc (num); if (!p) lt_fatal ("Memory exhausted"); return p; } char * xstrdup (const char *string) { return string ? strcpy ((char *) xmalloc (strlen (string) + 1), string) : NULL; } const char * base_name (const char *name) { const char *base; #if defined (HAVE_DOS_BASED_FILE_SYSTEM) /* Skip over the disk name in MSDOS pathnames. */ if (isalpha ((unsigned char) name[0]) && name[1] == ':') name += 2; #endif for (base = name; *name; name++) if (IS_DIR_SEPARATOR (*name)) base = name + 1; return base; } int check_executable (const char *path) { struct stat st; LTWRAPPER_DEBUGPRINTF (("(check_executable) : %s\n", path ? (*path ? path : "EMPTY!") : "NULL!")); if ((!path) || (!*path)) return 0; if ((stat (path, &st) >= 0) && (st.st_mode & (S_IXUSR | S_IXGRP | S_IXOTH))) return 1; else return 0; } int make_executable (const char *path) { int rval = 0; struct stat st; LTWRAPPER_DEBUGPRINTF (("(make_executable) : %s\n", path ? (*path ? path : "EMPTY!") : "NULL!")); if ((!path) || (!*path)) return 0; if (stat (path, &st) >= 0) { rval = chmod (path, st.st_mode | S_IXOTH | S_IXGRP | S_IXUSR); } return rval; } /* Searches for the full path of the wrapper. Returns newly allocated full path name if found, NULL otherwise Does not chase symlinks, even on platforms that support them. */ char * find_executable (const char *wrapper) { int has_slash = 0; const char *p; const char *p_next; /* static buffer for getcwd */ char tmp[LT_PATHMAX + 1]; int tmp_len; char *concat_name; LTWRAPPER_DEBUGPRINTF (("(find_executable) : %s\n", wrapper ? (*wrapper ? wrapper : "EMPTY!") : "NULL!")); if ((wrapper == NULL) || (*wrapper == '\0')) return NULL; /* Absolute path? */ #if defined (HAVE_DOS_BASED_FILE_SYSTEM) if (isalpha ((unsigned char) wrapper[0]) && wrapper[1] == ':') { concat_name = xstrdup (wrapper); if (check_executable (concat_name)) return concat_name; XFREE (concat_name); } else { #endif if (IS_DIR_SEPARATOR (wrapper[0])) { concat_name = xstrdup (wrapper); if (check_executable (concat_name)) return concat_name; XFREE (concat_name); } #if defined (HAVE_DOS_BASED_FILE_SYSTEM) } #endif for (p = wrapper; *p; p++) if (*p == '/') { has_slash = 1; break; } if (!has_slash) { /* no slashes; search PATH */ const char *path = getenv ("PATH"); if (path != NULL) { for (p = path; *p; p = p_next) { const char *q; size_t p_len; for (q = p; *q; q++) if (IS_PATH_SEPARATOR (*q)) break; p_len = q - p; p_next = (*q == '\0' ? q : q + 1); if (p_len == 0) { /* empty path: current directory */ if (getcwd (tmp, LT_PATHMAX) == NULL) lt_fatal ("getcwd failed"); tmp_len = strlen (tmp); concat_name = XMALLOC (char, tmp_len + 1 + strlen (wrapper) + 1); memcpy (concat_name, tmp, tmp_len); concat_name[tmp_len] = '/'; strcpy (concat_name + tmp_len + 1, wrapper); } else { concat_name = XMALLOC (char, p_len + 1 + strlen (wrapper) + 1); memcpy (concat_name, p, p_len); concat_name[p_len] = '/'; strcpy (concat_name + p_len + 1, wrapper); } if (check_executable (concat_name)) return concat_name; XFREE (concat_name); } } /* not found in PATH; assume curdir */ } /* Relative path | not found in path: prepend cwd */ if (getcwd (tmp, LT_PATHMAX) == NULL) lt_fatal ("getcwd failed"); tmp_len = strlen (tmp); concat_name = XMALLOC (char, tmp_len + 1 + strlen (wrapper) + 1); memcpy (concat_name, tmp, tmp_len); concat_name[tmp_len] = '/'; strcpy (concat_name + tmp_len + 1, wrapper); if (check_executable (concat_name)) return concat_name; XFREE (concat_name); return NULL; } char * chase_symlinks (const char *pathspec) { #ifndef S_ISLNK return xstrdup (pathspec); #else char buf[LT_PATHMAX]; struct stat s; char *tmp_pathspec = xstrdup (pathspec); char *p; int has_symlinks = 0; while (strlen (tmp_pathspec) && !has_symlinks) { LTWRAPPER_DEBUGPRINTF (("checking path component for symlinks: %s\n", tmp_pathspec)); if (lstat (tmp_pathspec, &s) == 0) { if (S_ISLNK (s.st_mode) != 0) { has_symlinks = 1; break; } /* search backwards for last DIR_SEPARATOR */ p = tmp_pathspec + strlen (tmp_pathspec) - 1; while ((p > tmp_pathspec) && (!IS_DIR_SEPARATOR (*p))) p--; if ((p == tmp_pathspec) && (!IS_DIR_SEPARATOR (*p))) { /* no more DIR_SEPARATORS left */ break; } *p = '\0'; } else { char *errstr = strerror (errno); lt_fatal ("Error accessing file %s (%s)", tmp_pathspec, errstr); } } XFREE (tmp_pathspec); if (!has_symlinks) { return xstrdup (pathspec); } tmp_pathspec = realpath (pathspec, buf); if (tmp_pathspec == 0) { lt_fatal ("Could not follow symlinks for %s", pathspec); } return xstrdup (tmp_pathspec); #endif } char * strendzap (char *str, const char *pat) { size_t len, patlen; assert (str != NULL); assert (pat != NULL); len = strlen (str); patlen = strlen (pat); if (patlen <= len) { str += len - patlen; if (strcmp (str, pat) == 0) *str = '\0'; } return str; } static void lt_error_core (int exit_status, const char *mode, const char *message, va_list ap) { fprintf (stderr, "%s: %s: ", program_name, mode); vfprintf (stderr, message, ap); fprintf (stderr, ".\n"); if (exit_status >= 0) exit (exit_status); } void lt_fatal (const char *message, ...) { va_list ap; va_start (ap, message); lt_error_core (EXIT_FAILURE, "FATAL", message, ap); va_end (ap); } void lt_setenv (const char *name, const char *value) { LTWRAPPER_DEBUGPRINTF (("(lt_setenv) setting '%s' to '%s'\n", (name ? name : ""), (value ? value : ""))); { #ifdef HAVE_SETENV /* always make a copy, for consistency with !HAVE_SETENV */ char *str = xstrdup (value); setenv (name, str, 1); #else int len = strlen (name) + 1 + strlen (value) + 1; char *str = XMALLOC (char, len); sprintf (str, "%s=%s", name, value); if (putenv (str) != EXIT_SUCCESS) { XFREE (str); } #endif } } char * lt_extend_str (const char *orig_value, const char *add, int to_end) { char *new_value; if (orig_value && *orig_value) { int orig_value_len = strlen (orig_value); int add_len = strlen (add); new_value = XMALLOC (char, add_len + orig_value_len + 1); if (to_end) { strcpy (new_value, orig_value); strcpy (new_value + orig_value_len, add); } else { strcpy (new_value, add); strcpy (new_value + add_len, orig_value); } } else { new_value = xstrdup (add); } return new_value; } int lt_split_name_value (const char *arg, char** name, char** value) { const char *p; int len; if (!arg || !*arg) return 1; p = strchr (arg, (int)'='); if (!p) return 1; *value = xstrdup (++p); len = strlen (arg) - strlen (*value); *name = XMALLOC (char, len); strncpy (*name, arg, len-1); (*name)[len - 1] = '\0'; return 0; } void lt_opt_process_env_set (const char *arg) { char *name = NULL; char *value = NULL; if (lt_split_name_value (arg, &name, &value) != 0) { XFREE (name); XFREE (value); lt_fatal ("bad argument for %s: '%s'", env_set_opt, arg); } lt_setenv (name, value); XFREE (name); XFREE (value); } void lt_opt_process_env_prepend (const char *arg) { char *name = NULL; char *value = NULL; char *new_value = NULL; if (lt_split_name_value (arg, &name, &value) != 0) { XFREE (name); XFREE (value); lt_fatal ("bad argument for %s: '%s'", env_prepend_opt, arg); } new_value = lt_extend_str (getenv (name), value, 0); lt_setenv (name, new_value); XFREE (new_value); XFREE (name); XFREE (value); } void lt_opt_process_env_append (const char *arg) { char *name = NULL; char *value = NULL; char *new_value = NULL; if (lt_split_name_value (arg, &name, &value) != 0) { XFREE (name); XFREE (value); lt_fatal ("bad argument for %s: '%s'", env_append_opt, arg); } new_value = lt_extend_str (getenv (name), value, 1); lt_setenv (name, new_value); XFREE (new_value); XFREE (name); XFREE (value); } void lt_update_exe_path (const char *name, const char *value) { LTWRAPPER_DEBUGPRINTF (("(lt_update_exe_path) modifying '%s' by prepending '%s'\n", (name ? name : ""), (value ? value : ""))); if (name && *name && value && *value) { char *new_value = lt_extend_str (getenv (name), value, 0); /* some systems can't cope with a ':'-terminated path #' */ int len = strlen (new_value); while (((len = strlen (new_value)) > 0) && IS_PATH_SEPARATOR (new_value[len-1])) { new_value[len-1] = '\0'; } lt_setenv (name, new_value); XFREE (new_value); } } void lt_update_lib_path (const char *name, const char *value) { LTWRAPPER_DEBUGPRINTF (("(lt_update_lib_path) modifying '%s' by prepending '%s'\n", (name ? name : ""), (value ? value : ""))); if (name && *name && value && *value) { char *new_value = lt_extend_str (getenv (name), value, 0); lt_setenv (name, new_value); XFREE (new_value); } } EOF } # end: func_emit_cwrapperexe_src # func_mode_link arg... func_mode_link () { $opt_debug case $host in *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-cegcc*) # It is impossible to link a dll without this setting, and # we shouldn't force the makefile maintainer to figure out # which system we are compiling for in order to pass an extra # flag for every libtool invocation. # allow_undefined=no # FIXME: Unfortunately, there are problems with the above when trying # to make a dll which has undefined symbols, in which case not # even a static library is built. For now, we need to specify # -no-undefined on the libtool link line when we can be certain # that all symbols are satisfied, otherwise we get a static library. allow_undefined=yes ;; *) allow_undefined=yes ;; esac libtool_args=$nonopt base_compile="$nonopt $@" compile_command=$nonopt finalize_command=$nonopt compile_rpath= finalize_rpath= compile_shlibpath= finalize_shlibpath= convenience= old_convenience= deplibs= old_deplibs= compiler_flags= linker_flags= dllsearchpath= lib_search_path=`pwd` inst_prefix_dir= new_inherited_linker_flags= avoid_version=no dlfiles= dlprefiles= dlself=no export_dynamic=no export_symbols= export_symbols_regex= generated= libobjs= ltlibs= module=no no_install=no objs= non_pic_objects= precious_files_regex= prefer_static_libs=no preload=no prev= prevarg= release= rpath= xrpath= perm_rpath= temp_rpath= thread_safe=no vinfo= vinfo_number=no weak_libs= single_module="${wl}-single_module" func_infer_tag $base_compile # We need to know -static, to get the right output filenames. for arg do case $arg in -shared) test "$build_libtool_libs" != yes && \ func_fatal_configuration "can not build a shared library" build_old_libs=no break ;; -all-static | -static | -static-libtool-libs) case $arg in -all-static) if test "$build_libtool_libs" = yes && test -z "$link_static_flag"; then func_warning "complete static linking is impossible in this configuration" fi if test -n "$link_static_flag"; then dlopen_self=$dlopen_self_static fi prefer_static_libs=yes ;; -static) if test -z "$pic_flag" && test -n "$link_static_flag"; then dlopen_self=$dlopen_self_static fi prefer_static_libs=built ;; -static-libtool-libs) if test -z "$pic_flag" && test -n "$link_static_flag"; then dlopen_self=$dlopen_self_static fi prefer_static_libs=yes ;; esac build_libtool_libs=no build_old_libs=yes break ;; esac done # See if our shared archives depend on static archives. test -n "$old_archive_from_new_cmds" && build_old_libs=yes # Go through the arguments, transforming them on the way. while test "$#" -gt 0; do arg="$1" shift func_quote_for_eval "$arg" qarg=$func_quote_for_eval_unquoted_result func_append libtool_args " $func_quote_for_eval_result" # If the previous option needs an argument, assign it. if test -n "$prev"; then case $prev in output) func_append compile_command " @OUTPUT@" func_append finalize_command " @OUTPUT@" ;; esac case $prev in dlfiles|dlprefiles) if test "$preload" = no; then # Add the symbol object into the linking commands. func_append compile_command " @SYMFILE@" func_append finalize_command " @SYMFILE@" preload=yes fi case $arg in *.la | *.lo) ;; # We handle these cases below. force) if test "$dlself" = no; then dlself=needless export_dynamic=yes fi prev= continue ;; self) if test "$prev" = dlprefiles; then dlself=yes elif test "$prev" = dlfiles && test "$dlopen_self" != yes; then dlself=yes else dlself=needless export_dynamic=yes fi prev= continue ;; *) if test "$prev" = dlfiles; then dlfiles="$dlfiles $arg" else dlprefiles="$dlprefiles $arg" fi prev= continue ;; esac ;; expsyms) export_symbols="$arg" test -f "$arg" \ || func_fatal_error "symbol file \`$arg' does not exist" prev= continue ;; expsyms_regex) export_symbols_regex="$arg" prev= continue ;; framework) case $host in *-*-darwin*) case "$deplibs " in *" $qarg.ltframework "*) ;; *) deplibs="$deplibs $qarg.ltframework" # this is fixed later ;; esac ;; esac prev= continue ;; inst_prefix) inst_prefix_dir="$arg" prev= continue ;; objectlist) if test -f "$arg"; then save_arg=$arg moreargs= for fil in `cat "$save_arg"` do # moreargs="$moreargs $fil" arg=$fil # A libtool-controlled object. # Check to see that this really is a libtool object. if func_lalib_unsafe_p "$arg"; then pic_object= non_pic_object= # Read the .lo file func_source "$arg" if test -z "$pic_object" || test -z "$non_pic_object" || test "$pic_object" = none && test "$non_pic_object" = none; then func_fatal_error "cannot find name of object for \`$arg'" fi # Extract subdirectory from the argument. func_dirname "$arg" "/" "" xdir="$func_dirname_result" if test "$pic_object" != none; then # Prepend the subdirectory the object is found in. pic_object="$xdir$pic_object" if test "$prev" = dlfiles; then if test "$build_libtool_libs" = yes && test "$dlopen_support" = yes; then dlfiles="$dlfiles $pic_object" prev= continue else # If libtool objects are unsupported, then we need to preload. prev=dlprefiles fi fi # CHECK ME: I think I busted this. -Ossama if test "$prev" = dlprefiles; then # Preload the old-style object. dlprefiles="$dlprefiles $pic_object" prev= fi # A PIC object. func_append libobjs " $pic_object" arg="$pic_object" fi # Non-PIC object. if test "$non_pic_object" != none; then # Prepend the subdirectory the object is found in. non_pic_object="$xdir$non_pic_object" # A standard non-PIC object func_append non_pic_objects " $non_pic_object" if test -z "$pic_object" || test "$pic_object" = none ; then arg="$non_pic_object" fi else # If the PIC object exists, use it instead. # $xdir was prepended to $pic_object above. non_pic_object="$pic_object" func_append non_pic_objects " $non_pic_object" fi else # Only an error if not doing a dry-run. if $opt_dry_run; then # Extract subdirectory from the argument. func_dirname "$arg" "/" "" xdir="$func_dirname_result" func_lo2o "$arg" pic_object=$xdir$objdir/$func_lo2o_result non_pic_object=$xdir$func_lo2o_result func_append libobjs " $pic_object" func_append non_pic_objects " $non_pic_object" else func_fatal_error "\`$arg' is not a valid libtool object" fi fi done else func_fatal_error "link input file \`$arg' does not exist" fi arg=$save_arg prev= continue ;; precious_regex) precious_files_regex="$arg" prev= continue ;; release) release="-$arg" prev= continue ;; rpath | xrpath) # We need an absolute path. case $arg in [\\/]* | [A-Za-z]:[\\/]*) ;; *) func_fatal_error "only absolute run-paths are allowed" ;; esac if test "$prev" = rpath; then case "$rpath " in *" $arg "*) ;; *) rpath="$rpath $arg" ;; esac else case "$xrpath " in *" $arg "*) ;; *) xrpath="$xrpath $arg" ;; esac fi prev= continue ;; shrext) shrext_cmds="$arg" prev= continue ;; weak) weak_libs="$weak_libs $arg" prev= continue ;; xcclinker) linker_flags="$linker_flags $qarg" compiler_flags="$compiler_flags $qarg" prev= func_append compile_command " $qarg" func_append finalize_command " $qarg" continue ;; xcompiler) compiler_flags="$compiler_flags $qarg" prev= func_append compile_command " $qarg" func_append finalize_command " $qarg" continue ;; xlinker) linker_flags="$linker_flags $qarg" compiler_flags="$compiler_flags $wl$qarg" prev= func_append compile_command " $wl$qarg" func_append finalize_command " $wl$qarg" continue ;; *) eval "$prev=\"\$arg\"" prev= continue ;; esac fi # test -n "$prev" prevarg="$arg" case $arg in -all-static) if test -n "$link_static_flag"; then # See comment for -static flag below, for more details. func_append compile_command " $link_static_flag" func_append finalize_command " $link_static_flag" fi continue ;; -allow-undefined) # FIXME: remove this flag sometime in the future. func_fatal_error "\`-allow-undefined' must not be used because it is the default" ;; -avoid-version) avoid_version=yes continue ;; -dlopen) prev=dlfiles continue ;; -dlpreopen) prev=dlprefiles continue ;; -export-dynamic) export_dynamic=yes continue ;; -export-symbols | -export-symbols-regex) if test -n "$export_symbols" || test -n "$export_symbols_regex"; then func_fatal_error "more than one -exported-symbols argument is not allowed" fi if test "X$arg" = "X-export-symbols"; then prev=expsyms else prev=expsyms_regex fi continue ;; -framework) prev=framework continue ;; -inst-prefix-dir) prev=inst_prefix continue ;; # The native IRIX linker understands -LANG:*, -LIST:* and -LNO:* # so, if we see these flags be careful not to treat them like -L -L[A-Z][A-Z]*:*) case $with_gcc/$host in no/*-*-irix* | /*-*-irix*) func_append compile_command " $arg" func_append finalize_command " $arg" ;; esac continue ;; -L*) func_stripname '-L' '' "$arg" dir=$func_stripname_result if test -z "$dir"; then if test "$#" -gt 0; then func_fatal_error "require no space between \`-L' and \`$1'" else func_fatal_error "need path for \`-L' option" fi fi # We need an absolute path. case $dir in [\\/]* | [A-Za-z]:[\\/]*) ;; *) absdir=`cd "$dir" && pwd` test -z "$absdir" && \ func_fatal_error "cannot determine absolute directory name of \`$dir'" dir="$absdir" ;; esac case "$deplibs " in *" -L$dir "*) ;; *) deplibs="$deplibs -L$dir" lib_search_path="$lib_search_path $dir" ;; esac case $host in *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-cegcc*) testbindir=`$ECHO "X$dir" | $Xsed -e 's*/lib$*/bin*'` case :$dllsearchpath: in *":$dir:"*) ;; ::) dllsearchpath=$dir;; *) dllsearchpath="$dllsearchpath:$dir";; esac case :$dllsearchpath: in *":$testbindir:"*) ;; ::) dllsearchpath=$testbindir;; *) dllsearchpath="$dllsearchpath:$testbindir";; esac ;; esac continue ;; -l*) if test "X$arg" = "X-lc" || test "X$arg" = "X-lm"; then case $host in *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-beos* | *-cegcc*) # These systems don't actually have a C or math library (as such) continue ;; *-*-os2*) # These systems don't actually have a C library (as such) test "X$arg" = "X-lc" && continue ;; *-*-openbsd* | *-*-freebsd* | *-*-dragonfly*) # Do not include libc due to us having libc/libc_r. test "X$arg" = "X-lc" && continue ;; *-*-rhapsody* | *-*-darwin1.[012]) # Rhapsody C and math libraries are in the System framework deplibs="$deplibs System.ltframework" continue ;; *-*-sco3.2v5* | *-*-sco5v6*) # Causes problems with __ctype test "X$arg" = "X-lc" && continue ;; *-*-sysv4.2uw2* | *-*-sysv5* | *-*-unixware* | *-*-OpenUNIX*) # Compiler inserts libc in the correct place for threads to work test "X$arg" = "X-lc" && continue ;; esac elif test "X$arg" = "X-lc_r"; then case $host in *-*-openbsd* | *-*-freebsd* | *-*-dragonfly*) # Do not include libc_r directly, use -pthread flag. continue ;; esac fi deplibs="$deplibs $arg" continue ;; -module) module=yes continue ;; # Tru64 UNIX uses -model [arg] to determine the layout of C++ # classes, name mangling, and exception handling. # Darwin uses the -arch flag to determine output architecture. -model|-arch|-isysroot) compiler_flags="$compiler_flags $arg" func_append compile_command " $arg" func_append finalize_command " $arg" prev=xcompiler continue ;; -mt|-mthreads|-kthread|-Kthread|-pthread|-pthreads|--thread-safe|-threads) compiler_flags="$compiler_flags $arg" func_append compile_command " $arg" func_append finalize_command " $arg" case "$new_inherited_linker_flags " in *" $arg "*) ;; * ) new_inherited_linker_flags="$new_inherited_linker_flags $arg" ;; esac continue ;; -multi_module) single_module="${wl}-multi_module" continue ;; -no-fast-install) fast_install=no continue ;; -no-install) case $host in *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-*-darwin* | *-cegcc*) # The PATH hackery in wrapper scripts is required on Windows # and Darwin in order for the loader to find any dlls it needs. func_warning "\`-no-install' is ignored for $host" func_warning "assuming \`-no-fast-install' instead" fast_install=no ;; *) no_install=yes ;; esac continue ;; -no-undefined) allow_undefined=no continue ;; -objectlist) prev=objectlist continue ;; -o) prev=output ;; -precious-files-regex) prev=precious_regex continue ;; -release) prev=release continue ;; -rpath) prev=rpath continue ;; -R) prev=xrpath continue ;; -R*) func_stripname '-R' '' "$arg" dir=$func_stripname_result # We need an absolute path. case $dir in [\\/]* | [A-Za-z]:[\\/]*) ;; *) func_fatal_error "only absolute run-paths are allowed" ;; esac case "$xrpath " in *" $dir "*) ;; *) xrpath="$xrpath $dir" ;; esac continue ;; -shared) # The effects of -shared are defined in a previous loop. continue ;; -shrext) prev=shrext continue ;; -static | -static-libtool-libs) # The effects of -static are defined in a previous loop. # We used to do the same as -all-static on platforms that # didn't have a PIC flag, but the assumption that the effects # would be equivalent was wrong. It would break on at least # Digital Unix and AIX. continue ;; -thread-safe) thread_safe=yes continue ;; -version-info) prev=vinfo continue ;; -version-number) prev=vinfo vinfo_number=yes continue ;; -weak) prev=weak continue ;; -Wc,*) func_stripname '-Wc,' '' "$arg" args=$func_stripname_result arg= save_ifs="$IFS"; IFS=',' for flag in $args; do IFS="$save_ifs" func_quote_for_eval "$flag" arg="$arg $wl$func_quote_for_eval_result" compiler_flags="$compiler_flags $func_quote_for_eval_result" done IFS="$save_ifs" func_stripname ' ' '' "$arg" arg=$func_stripname_result ;; -Wl,*) func_stripname '-Wl,' '' "$arg" args=$func_stripname_result arg= save_ifs="$IFS"; IFS=',' for flag in $args; do IFS="$save_ifs" func_quote_for_eval "$flag" arg="$arg $wl$func_quote_for_eval_result" compiler_flags="$compiler_flags $wl$func_quote_for_eval_result" linker_flags="$linker_flags $func_quote_for_eval_result" done IFS="$save_ifs" func_stripname ' ' '' "$arg" arg=$func_stripname_result ;; -Xcompiler) prev=xcompiler continue ;; -Xlinker) prev=xlinker continue ;; -XCClinker) prev=xcclinker continue ;; # -msg_* for osf cc -msg_*) func_quote_for_eval "$arg" arg="$func_quote_for_eval_result" ;; # -64, -mips[0-9] enable 64-bit mode on the SGI compiler # -r[0-9][0-9]* specifies the processor on the SGI compiler # -xarch=*, -xtarget=* enable 64-bit mode on the Sun compiler # +DA*, +DD* enable 64-bit mode on the HP compiler # -q* pass through compiler args for the IBM compiler # -m*, -t[45]*, -txscale* pass through architecture-specific # compiler args for GCC # -F/path gives path to uninstalled frameworks, gcc on darwin # -p, -pg, --coverage, -fprofile-* pass through profiling flag for GCC # @file GCC response files -64|-mips[0-9]|-r[0-9][0-9]*|-xarch=*|-xtarget=*|+DA*|+DD*|-q*|-m*| \ -t[45]*|-txscale*|-p|-pg|--coverage|-fprofile-*|-F*|@*) func_quote_for_eval "$arg" arg="$func_quote_for_eval_result" func_append compile_command " $arg" func_append finalize_command " $arg" compiler_flags="$compiler_flags $arg" continue ;; # Some other compiler flag. -* | +*) func_quote_for_eval "$arg" arg="$func_quote_for_eval_result" ;; *.$objext) # A standard object. objs="$objs $arg" ;; *.lo) # A libtool-controlled object. # Check to see that this really is a libtool object. if func_lalib_unsafe_p "$arg"; then pic_object= non_pic_object= # Read the .lo file func_source "$arg" if test -z "$pic_object" || test -z "$non_pic_object" || test "$pic_object" = none && test "$non_pic_object" = none; then func_fatal_error "cannot find name of object for \`$arg'" fi # Extract subdirectory from the argument. func_dirname "$arg" "/" "" xdir="$func_dirname_result" if test "$pic_object" != none; then # Prepend the subdirectory the object is found in. pic_object="$xdir$pic_object" if test "$prev" = dlfiles; then if test "$build_libtool_libs" = yes && test "$dlopen_support" = yes; then dlfiles="$dlfiles $pic_object" prev= continue else # If libtool objects are unsupported, then we need to preload. prev=dlprefiles fi fi # CHECK ME: I think I busted this. -Ossama if test "$prev" = dlprefiles; then # Preload the old-style object. dlprefiles="$dlprefiles $pic_object" prev= fi # A PIC object. func_append libobjs " $pic_object" arg="$pic_object" fi # Non-PIC object. if test "$non_pic_object" != none; then # Prepend the subdirectory the object is found in. non_pic_object="$xdir$non_pic_object" # A standard non-PIC object func_append non_pic_objects " $non_pic_object" if test -z "$pic_object" || test "$pic_object" = none ; then arg="$non_pic_object" fi else # If the PIC object exists, use it instead. # $xdir was prepended to $pic_object above. non_pic_object="$pic_object" func_append non_pic_objects " $non_pic_object" fi else # Only an error if not doing a dry-run. if $opt_dry_run; then # Extract subdirectory from the argument. func_dirname "$arg" "/" "" xdir="$func_dirname_result" func_lo2o "$arg" pic_object=$xdir$objdir/$func_lo2o_result non_pic_object=$xdir$func_lo2o_result func_append libobjs " $pic_object" func_append non_pic_objects " $non_pic_object" else func_fatal_error "\`$arg' is not a valid libtool object" fi fi ;; *.$libext) # An archive. deplibs="$deplibs $arg" old_deplibs="$old_deplibs $arg" continue ;; *.la) # A libtool-controlled library. if test "$prev" = dlfiles; then # This library was specified with -dlopen. dlfiles="$dlfiles $arg" prev= elif test "$prev" = dlprefiles; then # The library was specified with -dlpreopen. dlprefiles="$dlprefiles $arg" prev= else deplibs="$deplibs $arg" fi continue ;; # Some other compiler argument. *) # Unknown arguments in both finalize_command and compile_command need # to be aesthetically quoted because they are evaled later. func_quote_for_eval "$arg" arg="$func_quote_for_eval_result" ;; esac # arg # Now actually substitute the argument into the commands. if test -n "$arg"; then func_append compile_command " $arg" func_append finalize_command " $arg" fi done # argument parsing loop test -n "$prev" && \ func_fatal_help "the \`$prevarg' option requires an argument" if test "$export_dynamic" = yes && test -n "$export_dynamic_flag_spec"; then eval arg=\"$export_dynamic_flag_spec\" func_append compile_command " $arg" func_append finalize_command " $arg" fi oldlibs= # calculate the name of the file, without its directory func_basename "$output" outputname="$func_basename_result" libobjs_save="$libobjs" if test -n "$shlibpath_var"; then # get the directories listed in $shlibpath_var eval shlib_search_path=\`\$ECHO \"X\${$shlibpath_var}\" \| \$Xsed -e \'s/:/ /g\'\` else shlib_search_path= fi eval sys_lib_search_path=\"$sys_lib_search_path_spec\" eval sys_lib_dlsearch_path=\"$sys_lib_dlsearch_path_spec\" func_dirname "$output" "/" "" output_objdir="$func_dirname_result$objdir" # Create the object directory. func_mkdir_p "$output_objdir" # Determine the type of output case $output in "") func_fatal_help "you must specify an output file" ;; *.$libext) linkmode=oldlib ;; *.lo | *.$objext) linkmode=obj ;; *.la) linkmode=lib ;; *) linkmode=prog ;; # Anything else should be a program. esac specialdeplibs= libs= # Find all interdependent deplibs by searching for libraries # that are linked more than once (e.g. -la -lb -la) for deplib in $deplibs; do if $opt_duplicate_deps ; then case "$libs " in *" $deplib "*) specialdeplibs="$specialdeplibs $deplib" ;; esac fi libs="$libs $deplib" done if test "$linkmode" = lib; then libs="$predeps $libs $compiler_lib_search_path $postdeps" # Compute libraries that are listed more than once in $predeps # $postdeps and mark them as special (i.e., whose duplicates are # not to be eliminated). pre_post_deps= if $opt_duplicate_compiler_generated_deps; then for pre_post_dep in $predeps $postdeps; do case "$pre_post_deps " in *" $pre_post_dep "*) specialdeplibs="$specialdeplibs $pre_post_deps" ;; esac pre_post_deps="$pre_post_deps $pre_post_dep" done fi pre_post_deps= fi deplibs= newdependency_libs= newlib_search_path= need_relink=no # whether we're linking any uninstalled libtool libraries notinst_deplibs= # not-installed libtool libraries notinst_path= # paths that contain not-installed libtool libraries case $linkmode in lib) passes="conv dlpreopen link" for file in $dlfiles $dlprefiles; do case $file in *.la) ;; *) func_fatal_help "libraries can \`-dlopen' only libtool libraries: $file" ;; esac done ;; prog) compile_deplibs= finalize_deplibs= alldeplibs=no newdlfiles= newdlprefiles= passes="conv scan dlopen dlpreopen link" ;; *) passes="conv" ;; esac for pass in $passes; do # The preopen pass in lib mode reverses $deplibs; put it back here # so that -L comes before libs that need it for instance... if test "$linkmode,$pass" = "lib,link"; then ## FIXME: Find the place where the list is rebuilt in the wrong ## order, and fix it there properly tmp_deplibs= for deplib in $deplibs; do tmp_deplibs="$deplib $tmp_deplibs" done deplibs="$tmp_deplibs" fi if test "$linkmode,$pass" = "lib,link" || test "$linkmode,$pass" = "prog,scan"; then libs="$deplibs" deplibs= fi if test "$linkmode" = prog; then case $pass in dlopen) libs="$dlfiles" ;; dlpreopen) libs="$dlprefiles" ;; link) libs="$deplibs %DEPLIBS%" test "X$link_all_deplibs" != Xno && libs="$libs $dependency_libs" ;; esac fi if test "$linkmode,$pass" = "lib,dlpreopen"; then # Collect and forward deplibs of preopened libtool libs for lib in $dlprefiles; do # Ignore non-libtool-libs dependency_libs= case $lib in *.la) func_source "$lib" ;; esac # Collect preopened libtool deplibs, except any this library # has declared as weak libs for deplib in $dependency_libs; do deplib_base=`$ECHO "X$deplib" | $Xsed -e "$basename"` case " $weak_libs " in *" $deplib_base "*) ;; *) deplibs="$deplibs $deplib" ;; esac done done libs="$dlprefiles" fi if test "$pass" = dlopen; then # Collect dlpreopened libraries save_deplibs="$deplibs" deplibs= fi for deplib in $libs; do lib= found=no case $deplib in -mt|-mthreads|-kthread|-Kthread|-pthread|-pthreads|--thread-safe|-threads) if test "$linkmode,$pass" = "prog,link"; then compile_deplibs="$deplib $compile_deplibs" finalize_deplibs="$deplib $finalize_deplibs" else compiler_flags="$compiler_flags $deplib" if test "$linkmode" = lib ; then case "$new_inherited_linker_flags " in *" $deplib "*) ;; * ) new_inherited_linker_flags="$new_inherited_linker_flags $deplib" ;; esac fi fi continue ;; -l*) if test "$linkmode" != lib && test "$linkmode" != prog; then func_warning "\`-l' is ignored for archives/objects" continue fi func_stripname '-l' '' "$deplib" name=$func_stripname_result if test "$linkmode" = lib; then searchdirs="$newlib_search_path $lib_search_path $compiler_lib_search_dirs $sys_lib_search_path $shlib_search_path" else searchdirs="$newlib_search_path $lib_search_path $sys_lib_search_path $shlib_search_path" fi for searchdir in $searchdirs; do for search_ext in .la $std_shrext .so .a; do # Search the libtool library lib="$searchdir/lib${name}${search_ext}" if test -f "$lib"; then if test "$search_ext" = ".la"; then found=yes else found=no fi break 2 fi done done if test "$found" != yes; then # deplib doesn't seem to be a libtool library if test "$linkmode,$pass" = "prog,link"; then compile_deplibs="$deplib $compile_deplibs" finalize_deplibs="$deplib $finalize_deplibs" else deplibs="$deplib $deplibs" test "$linkmode" = lib && newdependency_libs="$deplib $newdependency_libs" fi continue else # deplib is a libtool library # If $allow_libtool_libs_with_static_runtimes && $deplib is a stdlib, # We need to do some special things here, and not later. if test "X$allow_libtool_libs_with_static_runtimes" = "Xyes" ; then case " $predeps $postdeps " in *" $deplib "*) if func_lalib_p "$lib"; then library_names= old_library= func_source "$lib" for l in $old_library $library_names; do ll="$l" done if test "X$ll" = "X$old_library" ; then # only static version available found=no func_dirname "$lib" "" "." ladir="$func_dirname_result" lib=$ladir/$old_library if test "$linkmode,$pass" = "prog,link"; then compile_deplibs="$deplib $compile_deplibs" finalize_deplibs="$deplib $finalize_deplibs" else deplibs="$deplib $deplibs" test "$linkmode" = lib && newdependency_libs="$deplib $newdependency_libs" fi continue fi fi ;; *) ;; esac fi fi ;; # -l *.ltframework) if test "$linkmode,$pass" = "prog,link"; then compile_deplibs="$deplib $compile_deplibs" finalize_deplibs="$deplib $finalize_deplibs" else deplibs="$deplib $deplibs" if test "$linkmode" = lib ; then case "$new_inherited_linker_flags " in *" $deplib "*) ;; * ) new_inherited_linker_flags="$new_inherited_linker_flags $deplib" ;; esac fi fi continue ;; -L*) case $linkmode in lib) deplibs="$deplib $deplibs" test "$pass" = conv && continue newdependency_libs="$deplib $newdependency_libs" func_stripname '-L' '' "$deplib" newlib_search_path="$newlib_search_path $func_stripname_result" ;; prog) if test "$pass" = conv; then deplibs="$deplib $deplibs" continue fi if test "$pass" = scan; then deplibs="$deplib $deplibs" else compile_deplibs="$deplib $compile_deplibs" finalize_deplibs="$deplib $finalize_deplibs" fi func_stripname '-L' '' "$deplib" newlib_search_path="$newlib_search_path $func_stripname_result" ;; *) func_warning "\`-L' is ignored for archives/objects" ;; esac # linkmode continue ;; # -L -R*) if test "$pass" = link; then func_stripname '-R' '' "$deplib" dir=$func_stripname_result # Make sure the xrpath contains only unique directories. case "$xrpath " in *" $dir "*) ;; *) xrpath="$xrpath $dir" ;; esac fi deplibs="$deplib $deplibs" continue ;; *.la) lib="$deplib" ;; *.$libext) if test "$pass" = conv; then deplibs="$deplib $deplibs" continue fi case $linkmode in lib) # Linking convenience modules into shared libraries is allowed, # but linking other static libraries is non-portable. case " $dlpreconveniencelibs " in *" $deplib "*) ;; *) valid_a_lib=no case $deplibs_check_method in match_pattern*) set dummy $deplibs_check_method; shift match_pattern_regex=`expr "$deplibs_check_method" : "$1 \(.*\)"` if eval "\$ECHO \"X$deplib\"" 2>/dev/null | $Xsed -e 10q \ | $EGREP "$match_pattern_regex" > /dev/null; then valid_a_lib=yes fi ;; pass_all) valid_a_lib=yes ;; esac if test "$valid_a_lib" != yes; then $ECHO $ECHO "*** Warning: Trying to link with static lib archive $deplib." $ECHO "*** I have the capability to make that library automatically link in when" $ECHO "*** you link to this library. But I can only do this if you have a" $ECHO "*** shared version of the library, which you do not appear to have" $ECHO "*** because the file extensions .$libext of this argument makes me believe" $ECHO "*** that it is just a static archive that I should not use here." else $ECHO $ECHO "*** Warning: Linking the shared library $output against the" $ECHO "*** static library $deplib is not portable!" deplibs="$deplib $deplibs" fi ;; esac continue ;; prog) if test "$pass" != link; then deplibs="$deplib $deplibs" else compile_deplibs="$deplib $compile_deplibs" finalize_deplibs="$deplib $finalize_deplibs" fi continue ;; esac # linkmode ;; # *.$libext *.lo | *.$objext) if test "$pass" = conv; then deplibs="$deplib $deplibs" elif test "$linkmode" = prog; then if test "$pass" = dlpreopen || test "$dlopen_support" != yes || test "$build_libtool_libs" = no; then # If there is no dlopen support or we're linking statically, # we need to preload. newdlprefiles="$newdlprefiles $deplib" compile_deplibs="$deplib $compile_deplibs" finalize_deplibs="$deplib $finalize_deplibs" else newdlfiles="$newdlfiles $deplib" fi fi continue ;; %DEPLIBS%) alldeplibs=yes continue ;; esac # case $deplib if test "$found" = yes || test -f "$lib"; then : else func_fatal_error "cannot find the library \`$lib' or unhandled argument \`$deplib'" fi # Check to see that this really is a libtool archive. func_lalib_unsafe_p "$lib" \ || func_fatal_error "\`$lib' is not a valid libtool archive" func_dirname "$lib" "" "." ladir="$func_dirname_result" dlname= dlopen= dlpreopen= libdir= library_names= old_library= inherited_linker_flags= # If the library was installed with an old release of libtool, # it will not redefine variables installed, or shouldnotlink installed=yes shouldnotlink=no avoidtemprpath= # Read the .la file func_source "$lib" # Convert "-framework foo" to "foo.ltframework" if test -n "$inherited_linker_flags"; then tmp_inherited_linker_flags=`$ECHO "X$inherited_linker_flags" | $Xsed -e 's/-framework \([^ $]*\)/\1.ltframework/g'` for tmp_inherited_linker_flag in $tmp_inherited_linker_flags; do case " $new_inherited_linker_flags " in *" $tmp_inherited_linker_flag "*) ;; *) new_inherited_linker_flags="$new_inherited_linker_flags $tmp_inherited_linker_flag";; esac done fi dependency_libs=`$ECHO "X $dependency_libs" | $Xsed -e 's% \([^ $]*\).ltframework% -framework \1%g'` if test "$linkmode,$pass" = "lib,link" || test "$linkmode,$pass" = "prog,scan" || { test "$linkmode" != prog && test "$linkmode" != lib; }; then test -n "$dlopen" && dlfiles="$dlfiles $dlopen" test -n "$dlpreopen" && dlprefiles="$dlprefiles $dlpreopen" fi if test "$pass" = conv; then # Only check for convenience libraries deplibs="$lib $deplibs" if test -z "$libdir"; then if test -z "$old_library"; then func_fatal_error "cannot find name of link library for \`$lib'" fi # It is a libtool convenience library, so add in its objects. convenience="$convenience $ladir/$objdir/$old_library" old_convenience="$old_convenience $ladir/$objdir/$old_library" tmp_libs= for deplib in $dependency_libs; do deplibs="$deplib $deplibs" if $opt_duplicate_deps ; then case "$tmp_libs " in *" $deplib "*) specialdeplibs="$specialdeplibs $deplib" ;; esac fi tmp_libs="$tmp_libs $deplib" done elif test "$linkmode" != prog && test "$linkmode" != lib; then func_fatal_error "\`$lib' is not a convenience library" fi continue fi # $pass = conv # Get the name of the library we link against. linklib= for l in $old_library $library_names; do linklib="$l" done if test -z "$linklib"; then func_fatal_error "cannot find name of link library for \`$lib'" fi # This library was specified with -dlopen. if test "$pass" = dlopen; then if test -z "$libdir"; then func_fatal_error "cannot -dlopen a convenience library: \`$lib'" fi if test -z "$dlname" || test "$dlopen_support" != yes || test "$build_libtool_libs" = no; then # If there is no dlname, no dlopen support or we're linking # statically, we need to preload. We also need to preload any # dependent libraries so libltdl's deplib preloader doesn't # bomb out in the load deplibs phase. dlprefiles="$dlprefiles $lib $dependency_libs" else newdlfiles="$newdlfiles $lib" fi continue fi # $pass = dlopen # We need an absolute path. case $ladir in [\\/]* | [A-Za-z]:[\\/]*) abs_ladir="$ladir" ;; *) abs_ladir=`cd "$ladir" && pwd` if test -z "$abs_ladir"; then func_warning "cannot determine absolute directory name of \`$ladir'" func_warning "passing it literally to the linker, although it might fail" abs_ladir="$ladir" fi ;; esac func_basename "$lib" laname="$func_basename_result" # Find the relevant object directory and library name. if test "X$installed" = Xyes; then if test ! -f "$libdir/$linklib" && test -f "$abs_ladir/$linklib"; then func_warning "library \`$lib' was moved." dir="$ladir" absdir="$abs_ladir" libdir="$abs_ladir" else dir="$libdir" absdir="$libdir" fi test "X$hardcode_automatic" = Xyes && avoidtemprpath=yes else if test ! -f "$ladir/$objdir/$linklib" && test -f "$abs_ladir/$linklib"; then dir="$ladir" absdir="$abs_ladir" # Remove this search path later notinst_path="$notinst_path $abs_ladir" else dir="$ladir/$objdir" absdir="$abs_ladir/$objdir" # Remove this search path later notinst_path="$notinst_path $abs_ladir" fi fi # $installed = yes func_stripname 'lib' '.la' "$laname" name=$func_stripname_result # This library was specified with -dlpreopen. if test "$pass" = dlpreopen; then if test -z "$libdir" && test "$linkmode" = prog; then func_fatal_error "only libraries may -dlpreopen a convenience library: \`$lib'" fi # Prefer using a static library (so that no silly _DYNAMIC symbols # are required to link). if test -n "$old_library"; then newdlprefiles="$newdlprefiles $dir/$old_library" # Keep a list of preopened convenience libraries to check # that they are being used correctly in the link pass. test -z "$libdir" && \ dlpreconveniencelibs="$dlpreconveniencelibs $dir/$old_library" # Otherwise, use the dlname, so that lt_dlopen finds it. elif test -n "$dlname"; then newdlprefiles="$newdlprefiles $dir/$dlname" else newdlprefiles="$newdlprefiles $dir/$linklib" fi fi # $pass = dlpreopen if test -z "$libdir"; then # Link the convenience library if test "$linkmode" = lib; then deplibs="$dir/$old_library $deplibs" elif test "$linkmode,$pass" = "prog,link"; then compile_deplibs="$dir/$old_library $compile_deplibs" finalize_deplibs="$dir/$old_library $finalize_deplibs" else deplibs="$lib $deplibs" # used for prog,scan pass fi continue fi if test "$linkmode" = prog && test "$pass" != link; then newlib_search_path="$newlib_search_path $ladir" deplibs="$lib $deplibs" linkalldeplibs=no if test "$link_all_deplibs" != no || test -z "$library_names" || test "$build_libtool_libs" = no; then linkalldeplibs=yes fi tmp_libs= for deplib in $dependency_libs; do case $deplib in -L*) func_stripname '-L' '' "$deplib" newlib_search_path="$newlib_search_path $func_stripname_result" ;; esac # Need to link against all dependency_libs? if test "$linkalldeplibs" = yes; then deplibs="$deplib $deplibs" else # Need to hardcode shared library paths # or/and link against static libraries newdependency_libs="$deplib $newdependency_libs" fi if $opt_duplicate_deps ; then case "$tmp_libs " in *" $deplib "*) specialdeplibs="$specialdeplibs $deplib" ;; esac fi tmp_libs="$tmp_libs $deplib" done # for deplib continue fi # $linkmode = prog... if test "$linkmode,$pass" = "prog,link"; then if test -n "$library_names" && { { test "$prefer_static_libs" = no || test "$prefer_static_libs,$installed" = "built,yes"; } || test -z "$old_library"; }; then # We need to hardcode the library path if test -n "$shlibpath_var" && test -z "$avoidtemprpath" ; then # Make sure the rpath contains only unique directories. case "$temp_rpath:" in *"$absdir:"*) ;; *) temp_rpath="$temp_rpath$absdir:" ;; esac fi # Hardcode the library path. # Skip directories that are in the system default run-time # search path. case " $sys_lib_dlsearch_path " in *" $absdir "*) ;; *) case "$compile_rpath " in *" $absdir "*) ;; *) compile_rpath="$compile_rpath $absdir" esac ;; esac case " $sys_lib_dlsearch_path " in *" $libdir "*) ;; *) case "$finalize_rpath " in *" $libdir "*) ;; *) finalize_rpath="$finalize_rpath $libdir" esac ;; esac fi # $linkmode,$pass = prog,link... if test "$alldeplibs" = yes && { test "$deplibs_check_method" = pass_all || { test "$build_libtool_libs" = yes && test -n "$library_names"; }; }; then # We only need to search for static libraries continue fi fi link_static=no # Whether the deplib will be linked statically use_static_libs=$prefer_static_libs if test "$use_static_libs" = built && test "$installed" = yes; then use_static_libs=no fi if test -n "$library_names" && { test "$use_static_libs" = no || test -z "$old_library"; }; then case $host in *cygwin* | *mingw* | *cegcc*) # No point in relinking DLLs because paths are not encoded notinst_deplibs="$notinst_deplibs $lib" need_relink=no ;; *) if test "$installed" = no; then notinst_deplibs="$notinst_deplibs $lib" need_relink=yes fi ;; esac # This is a shared library # Warn about portability, can't link against -module's on some # systems (darwin). Don't bleat about dlopened modules though! dlopenmodule="" for dlpremoduletest in $dlprefiles; do if test "X$dlpremoduletest" = "X$lib"; then dlopenmodule="$dlpremoduletest" break fi done if test -z "$dlopenmodule" && test "$shouldnotlink" = yes && test "$pass" = link; then $ECHO if test "$linkmode" = prog; then $ECHO "*** Warning: Linking the executable $output against the loadable module" else $ECHO "*** Warning: Linking the shared library $output against the loadable module" fi $ECHO "*** $linklib is not portable!" fi if test "$linkmode" = lib && test "$hardcode_into_libs" = yes; then # Hardcode the library path. # Skip directories that are in the system default run-time # search path. case " $sys_lib_dlsearch_path " in *" $absdir "*) ;; *) case "$compile_rpath " in *" $absdir "*) ;; *) compile_rpath="$compile_rpath $absdir" esac ;; esac case " $sys_lib_dlsearch_path " in *" $libdir "*) ;; *) case "$finalize_rpath " in *" $libdir "*) ;; *) finalize_rpath="$finalize_rpath $libdir" esac ;; esac fi if test -n "$old_archive_from_expsyms_cmds"; then # figure out the soname set dummy $library_names shift realname="$1" shift libname=`eval "\\$ECHO \"$libname_spec\""` # use dlname if we got it. it's perfectly good, no? if test -n "$dlname"; then soname="$dlname" elif test -n "$soname_spec"; then # bleh windows case $host in *cygwin* | mingw* | *cegcc*) func_arith $current - $age major=$func_arith_result versuffix="-$major" ;; esac eval soname=\"$soname_spec\" else soname="$realname" fi # Make a new name for the extract_expsyms_cmds to use soroot="$soname" func_basename "$soroot" soname="$func_basename_result" func_stripname 'lib' '.dll' "$soname" newlib=libimp-$func_stripname_result.a # If the library has no export list, then create one now if test -f "$output_objdir/$soname-def"; then : else func_verbose "extracting exported symbol list from \`$soname'" func_execute_cmds "$extract_expsyms_cmds" 'exit $?' fi # Create $newlib if test -f "$output_objdir/$newlib"; then :; else func_verbose "generating import library for \`$soname'" func_execute_cmds "$old_archive_from_expsyms_cmds" 'exit $?' fi # make sure the library variables are pointing to the new library dir=$output_objdir linklib=$newlib fi # test -n "$old_archive_from_expsyms_cmds" if test "$linkmode" = prog || test "$mode" != relink; then add_shlibpath= add_dir= add= lib_linked=yes case $hardcode_action in immediate | unsupported) if test "$hardcode_direct" = no; then add="$dir/$linklib" case $host in *-*-sco3.2v5.0.[024]*) add_dir="-L$dir" ;; *-*-sysv4*uw2*) add_dir="-L$dir" ;; *-*-sysv5OpenUNIX* | *-*-sysv5UnixWare7.[01].[10]* | \ *-*-unixware7*) add_dir="-L$dir" ;; *-*-darwin* ) # if the lib is a (non-dlopened) module then we can not # link against it, someone is ignoring the earlier warnings if /usr/bin/file -L $add 2> /dev/null | $GREP ": [^:]* bundle" >/dev/null ; then if test "X$dlopenmodule" != "X$lib"; then $ECHO "*** Warning: lib $linklib is a module, not a shared library" if test -z "$old_library" ; then $ECHO $ECHO "*** And there doesn't seem to be a static archive available" $ECHO "*** The link will probably fail, sorry" else add="$dir/$old_library" fi elif test -n "$old_library"; then add="$dir/$old_library" fi fi esac elif test "$hardcode_minus_L" = no; then case $host in *-*-sunos*) add_shlibpath="$dir" ;; esac add_dir="-L$dir" add="-l$name" elif test "$hardcode_shlibpath_var" = no; then add_shlibpath="$dir" add="-l$name" else lib_linked=no fi ;; relink) if test "$hardcode_direct" = yes && test "$hardcode_direct_absolute" = no; then add="$dir/$linklib" elif test "$hardcode_minus_L" = yes; then add_dir="-L$dir" # Try looking first in the location we're being installed to. if test -n "$inst_prefix_dir"; then case $libdir in [\\/]*) add_dir="$add_dir -L$inst_prefix_dir$libdir" ;; esac fi add="-l$name" elif test "$hardcode_shlibpath_var" = yes; then add_shlibpath="$dir" add="-l$name" else lib_linked=no fi ;; *) lib_linked=no ;; esac if test "$lib_linked" != yes; then func_fatal_configuration "unsupported hardcode properties" fi if test -n "$add_shlibpath"; then case :$compile_shlibpath: in *":$add_shlibpath:"*) ;; *) compile_shlibpath="$compile_shlibpath$add_shlibpath:" ;; esac fi if test "$linkmode" = prog; then test -n "$add_dir" && compile_deplibs="$add_dir $compile_deplibs" test -n "$add" && compile_deplibs="$add $compile_deplibs" else test -n "$add_dir" && deplibs="$add_dir $deplibs" test -n "$add" && deplibs="$add $deplibs" if test "$hardcode_direct" != yes && test "$hardcode_minus_L" != yes && test "$hardcode_shlibpath_var" = yes; then case :$finalize_shlibpath: in *":$libdir:"*) ;; *) finalize_shlibpath="$finalize_shlibpath$libdir:" ;; esac fi fi fi if test "$linkmode" = prog || test "$mode" = relink; then add_shlibpath= add_dir= add= # Finalize command for both is simple: just hardcode it. if test "$hardcode_direct" = yes && test "$hardcode_direct_absolute" = no; then add="$libdir/$linklib" elif test "$hardcode_minus_L" = yes; then add_dir="-L$libdir" add="-l$name" elif test "$hardcode_shlibpath_var" = yes; then case :$finalize_shlibpath: in *":$libdir:"*) ;; *) finalize_shlibpath="$finalize_shlibpath$libdir:" ;; esac add="-l$name" elif test "$hardcode_automatic" = yes; then if test -n "$inst_prefix_dir" && test -f "$inst_prefix_dir$libdir/$linklib" ; then add="$inst_prefix_dir$libdir/$linklib" else add="$libdir/$linklib" fi else # We cannot seem to hardcode it, guess we'll fake it. add_dir="-L$libdir" # Try looking first in the location we're being installed to. if test -n "$inst_prefix_dir"; then case $libdir in [\\/]*) add_dir="$add_dir -L$inst_prefix_dir$libdir" ;; esac fi add="-l$name" fi if test "$linkmode" = prog; then test -n "$add_dir" && finalize_deplibs="$add_dir $finalize_deplibs" test -n "$add" && finalize_deplibs="$add $finalize_deplibs" else test -n "$add_dir" && deplibs="$add_dir $deplibs" test -n "$add" && deplibs="$add $deplibs" fi fi elif test "$linkmode" = prog; then # Here we assume that one of hardcode_direct or hardcode_minus_L # is not unsupported. This is valid on all known static and # shared platforms. if test "$hardcode_direct" != unsupported; then test -n "$old_library" && linklib="$old_library" compile_deplibs="$dir/$linklib $compile_deplibs" finalize_deplibs="$dir/$linklib $finalize_deplibs" else compile_deplibs="-l$name -L$dir $compile_deplibs" finalize_deplibs="-l$name -L$dir $finalize_deplibs" fi elif test "$build_libtool_libs" = yes; then # Not a shared library if test "$deplibs_check_method" != pass_all; then # We're trying link a shared library against a static one # but the system doesn't support it. # Just print a warning and add the library to dependency_libs so # that the program can be linked against the static library. $ECHO $ECHO "*** Warning: This system can not link to static lib archive $lib." $ECHO "*** I have the capability to make that library automatically link in when" $ECHO "*** you link to this library. But I can only do this if you have a" $ECHO "*** shared version of the library, which you do not appear to have." if test "$module" = yes; then $ECHO "*** But as you try to build a module library, libtool will still create " $ECHO "*** a static module, that should work as long as the dlopening application" $ECHO "*** is linked with the -dlopen flag to resolve symbols at runtime." if test -z "$global_symbol_pipe"; then $ECHO $ECHO "*** However, this would only work if libtool was able to extract symbol" $ECHO "*** lists from a program, using \`nm' or equivalent, but libtool could" $ECHO "*** not find such a program. So, this module is probably useless." $ECHO "*** \`nm' from GNU binutils and a full rebuild may help." fi if test "$build_old_libs" = no; then build_libtool_libs=module build_old_libs=yes else build_libtool_libs=no fi fi else deplibs="$dir/$old_library $deplibs" link_static=yes fi fi # link shared/static library? if test "$linkmode" = lib; then if test -n "$dependency_libs" && { test "$hardcode_into_libs" != yes || test "$build_old_libs" = yes || test "$link_static" = yes; }; then # Extract -R from dependency_libs temp_deplibs= for libdir in $dependency_libs; do case $libdir in -R*) func_stripname '-R' '' "$libdir" temp_xrpath=$func_stripname_result case " $xrpath " in *" $temp_xrpath "*) ;; *) xrpath="$xrpath $temp_xrpath";; esac;; *) temp_deplibs="$temp_deplibs $libdir";; esac done dependency_libs="$temp_deplibs" fi newlib_search_path="$newlib_search_path $absdir" # Link against this library test "$link_static" = no && newdependency_libs="$abs_ladir/$laname $newdependency_libs" # ... and its dependency_libs tmp_libs= for deplib in $dependency_libs; do newdependency_libs="$deplib $newdependency_libs" if $opt_duplicate_deps ; then case "$tmp_libs " in *" $deplib "*) specialdeplibs="$specialdeplibs $deplib" ;; esac fi tmp_libs="$tmp_libs $deplib" done if test "$link_all_deplibs" != no; then # Add the search paths of all dependency libraries for deplib in $dependency_libs; do path= case $deplib in -L*) path="$deplib" ;; *.la) func_dirname "$deplib" "" "." dir="$func_dirname_result" # We need an absolute path. case $dir in [\\/]* | [A-Za-z]:[\\/]*) absdir="$dir" ;; *) absdir=`cd "$dir" && pwd` if test -z "$absdir"; then func_warning "cannot determine absolute directory name of \`$dir'" absdir="$dir" fi ;; esac if $GREP "^installed=no" $deplib > /dev/null; then case $host in *-*-darwin*) depdepl= eval deplibrary_names=`${SED} -n -e 's/^library_names=\(.*\)$/\1/p' $deplib` if test -n "$deplibrary_names" ; then for tmp in $deplibrary_names ; do depdepl=$tmp done if test -f "$absdir/$objdir/$depdepl" ; then depdepl="$absdir/$objdir/$depdepl" darwin_install_name=`${OTOOL} -L $depdepl | awk '{if (NR == 2) {print $1;exit}}'` if test -z "$darwin_install_name"; then darwin_install_name=`${OTOOL64} -L $depdepl | awk '{if (NR == 2) {print $1;exit}}'` fi compiler_flags="$compiler_flags ${wl}-dylib_file ${wl}${darwin_install_name}:${depdepl}" linker_flags="$linker_flags -dylib_file ${darwin_install_name}:${depdepl}" path= fi fi ;; *) path="-L$absdir/$objdir" ;; esac else eval libdir=`${SED} -n -e 's/^libdir=\(.*\)$/\1/p' $deplib` test -z "$libdir" && \ func_fatal_error "\`$deplib' is not a valid libtool archive" test "$absdir" != "$libdir" && \ func_warning "\`$deplib' seems to be moved" path="-L$absdir" fi ;; esac case " $deplibs " in *" $path "*) ;; *) deplibs="$path $deplibs" ;; esac done fi # link_all_deplibs != no fi # linkmode = lib done # for deplib in $libs if test "$pass" = link; then if test "$linkmode" = "prog"; then compile_deplibs="$new_inherited_linker_flags $compile_deplibs" finalize_deplibs="$new_inherited_linker_flags $finalize_deplibs" else compiler_flags="$compiler_flags "`$ECHO "X $new_inherited_linker_flags" | $Xsed -e 's% \([^ $]*\).ltframework% -framework \1%g'` fi fi dependency_libs="$newdependency_libs" if test "$pass" = dlpreopen; then # Link the dlpreopened libraries before other libraries for deplib in $save_deplibs; do deplibs="$deplib $deplibs" done fi if test "$pass" != dlopen; then if test "$pass" != conv; then # Make sure lib_search_path contains only unique directories. lib_search_path= for dir in $newlib_search_path; do case "$lib_search_path " in *" $dir "*) ;; *) lib_search_path="$lib_search_path $dir" ;; esac done newlib_search_path= fi if test "$linkmode,$pass" != "prog,link"; then vars="deplibs" else vars="compile_deplibs finalize_deplibs" fi for var in $vars dependency_libs; do # Add libraries to $var in reverse order eval tmp_libs=\"\$$var\" new_libs= for deplib in $tmp_libs; do # FIXME: Pedantically, this is the right thing to do, so # that some nasty dependency loop isn't accidentally # broken: #new_libs="$deplib $new_libs" # Pragmatically, this seems to cause very few problems in # practice: case $deplib in -L*) new_libs="$deplib $new_libs" ;; -R*) ;; *) # And here is the reason: when a library appears more # than once as an explicit dependence of a library, or # is implicitly linked in more than once by the # compiler, it is considered special, and multiple # occurrences thereof are not removed. Compare this # with having the same library being listed as a # dependency of multiple other libraries: in this case, # we know (pedantically, we assume) the library does not # need to be listed more than once, so we keep only the # last copy. This is not always right, but it is rare # enough that we require users that really mean to play # such unportable linking tricks to link the library # using -Wl,-lname, so that libtool does not consider it # for duplicate removal. case " $specialdeplibs " in *" $deplib "*) new_libs="$deplib $new_libs" ;; *) case " $new_libs " in *" $deplib "*) ;; *) new_libs="$deplib $new_libs" ;; esac ;; esac ;; esac done tmp_libs= for deplib in $new_libs; do case $deplib in -L*) case " $tmp_libs " in *" $deplib "*) ;; *) tmp_libs="$tmp_libs $deplib" ;; esac ;; *) tmp_libs="$tmp_libs $deplib" ;; esac done eval $var=\"$tmp_libs\" done # for var fi # Last step: remove runtime libs from dependency_libs # (they stay in deplibs) tmp_libs= for i in $dependency_libs ; do case " $predeps $postdeps $compiler_lib_search_path " in *" $i "*) i="" ;; esac if test -n "$i" ; then tmp_libs="$tmp_libs $i" fi done dependency_libs=$tmp_libs done # for pass if test "$linkmode" = prog; then dlfiles="$newdlfiles" fi if test "$linkmode" = prog || test "$linkmode" = lib; then dlprefiles="$newdlprefiles" fi case $linkmode in oldlib) if test -n "$dlfiles$dlprefiles" || test "$dlself" != no; then func_warning "\`-dlopen' is ignored for archives" fi case " $deplibs" in *\ -l* | *\ -L*) func_warning "\`-l' and \`-L' are ignored for archives" ;; esac test -n "$rpath" && \ func_warning "\`-rpath' is ignored for archives" test -n "$xrpath" && \ func_warning "\`-R' is ignored for archives" test -n "$vinfo" && \ func_warning "\`-version-info/-version-number' is ignored for archives" test -n "$release" && \ func_warning "\`-release' is ignored for archives" test -n "$export_symbols$export_symbols_regex" && \ func_warning "\`-export-symbols' is ignored for archives" # Now set the variables for building old libraries. build_libtool_libs=no oldlibs="$output" objs="$objs$old_deplibs" ;; lib) # Make sure we only generate libraries of the form `libNAME.la'. case $outputname in lib*) func_stripname 'lib' '.la' "$outputname" name=$func_stripname_result eval shared_ext=\"$shrext_cmds\" eval libname=\"$libname_spec\" ;; *) test "$module" = no && \ func_fatal_help "libtool library \`$output' must begin with \`lib'" if test "$need_lib_prefix" != no; then # Add the "lib" prefix for modules if required func_stripname '' '.la' "$outputname" name=$func_stripname_result eval shared_ext=\"$shrext_cmds\" eval libname=\"$libname_spec\" else func_stripname '' '.la' "$outputname" libname=$func_stripname_result fi ;; esac if test -n "$objs"; then if test "$deplibs_check_method" != pass_all; then func_fatal_error "cannot build libtool library \`$output' from non-libtool objects on this host:$objs" else $ECHO $ECHO "*** Warning: Linking the shared library $output against the non-libtool" $ECHO "*** objects $objs is not portable!" libobjs="$libobjs $objs" fi fi test "$dlself" != no && \ func_warning "\`-dlopen self' is ignored for libtool libraries" set dummy $rpath shift test "$#" -gt 1 && \ func_warning "ignoring multiple \`-rpath's for a libtool library" install_libdir="$1" oldlibs= if test -z "$rpath"; then if test "$build_libtool_libs" = yes; then # Building a libtool convenience library. # Some compilers have problems with a `.al' extension so # convenience libraries should have the same extension an # archive normally would. oldlibs="$output_objdir/$libname.$libext $oldlibs" build_libtool_libs=convenience build_old_libs=yes fi test -n "$vinfo" && \ func_warning "\`-version-info/-version-number' is ignored for convenience libraries" test -n "$release" && \ func_warning "\`-release' is ignored for convenience libraries" else # Parse the version information argument. save_ifs="$IFS"; IFS=':' set dummy $vinfo 0 0 0 shift IFS="$save_ifs" test -n "$7" && \ func_fatal_help "too many parameters to \`-version-info'" # convert absolute version numbers to libtool ages # this retains compatibility with .la files and attempts # to make the code below a bit more comprehensible case $vinfo_number in yes) number_major="$1" number_minor="$2" number_revision="$3" # # There are really only two kinds -- those that # use the current revision as the major version # and those that subtract age and use age as # a minor version. But, then there is irix # which has an extra 1 added just for fun # case $version_type in darwin|linux|osf|windows|none) func_arith $number_major + $number_minor current=$func_arith_result age="$number_minor" revision="$number_revision" ;; freebsd-aout|freebsd-elf|sunos) current="$number_major" revision="$number_minor" age="0" ;; irix|nonstopux) func_arith $number_major + $number_minor current=$func_arith_result age="$number_minor" revision="$number_minor" lt_irix_increment=no ;; *) func_fatal_configuration "$modename: unknown library version type \`$version_type'" ;; esac ;; no) current="$1" revision="$2" age="$3" ;; esac # Check that each of the things are valid numbers. case $current in 0|[1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|[1-9][0-9][0-9][0-9][0-9]) ;; *) func_error "CURRENT \`$current' must be a nonnegative integer" func_fatal_error "\`$vinfo' is not valid version information" ;; esac case $revision in 0|[1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|[1-9][0-9][0-9][0-9][0-9]) ;; *) func_error "REVISION \`$revision' must be a nonnegative integer" func_fatal_error "\`$vinfo' is not valid version information" ;; esac case $age in 0|[1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|[1-9][0-9][0-9][0-9][0-9]) ;; *) func_error "AGE \`$age' must be a nonnegative integer" func_fatal_error "\`$vinfo' is not valid version information" ;; esac if test "$age" -gt "$current"; then func_error "AGE \`$age' is greater than the current interface number \`$current'" func_fatal_error "\`$vinfo' is not valid version information" fi # Calculate the version variables. major= versuffix= verstring= case $version_type in none) ;; darwin) # Like Linux, but with the current version available in # verstring for coding it into the library header func_arith $current - $age major=.$func_arith_result versuffix="$major.$age.$revision" # Darwin ld doesn't like 0 for these options... func_arith $current + 1 minor_current=$func_arith_result xlcverstring="${wl}-compatibility_version ${wl}$minor_current ${wl}-current_version ${wl}$minor_current.$revision" verstring="-compatibility_version $minor_current -current_version $minor_current.$revision" ;; freebsd-aout) major=".$current" versuffix=".$current.$revision"; ;; freebsd-elf) major=".$current" versuffix=".$current" ;; irix | nonstopux) if test "X$lt_irix_increment" = "Xno"; then func_arith $current - $age else func_arith $current - $age + 1 fi major=$func_arith_result case $version_type in nonstopux) verstring_prefix=nonstopux ;; *) verstring_prefix=sgi ;; esac verstring="$verstring_prefix$major.$revision" # Add in all the interfaces that we are compatible with. loop=$revision while test "$loop" -ne 0; do func_arith $revision - $loop iface=$func_arith_result func_arith $loop - 1 loop=$func_arith_result verstring="$verstring_prefix$major.$iface:$verstring" done # Before this point, $major must not contain `.'. major=.$major versuffix="$major.$revision" ;; linux) func_arith $current - $age major=.$func_arith_result versuffix="$major.$age.$revision" ;; osf) func_arith $current - $age major=.$func_arith_result versuffix=".$current.$age.$revision" verstring="$current.$age.$revision" # Add in all the interfaces that we are compatible with. loop=$age while test "$loop" -ne 0; do func_arith $current - $loop iface=$func_arith_result func_arith $loop - 1 loop=$func_arith_result verstring="$verstring:${iface}.0" done # Make executables depend on our current version. verstring="$verstring:${current}.0" ;; qnx) major=".$current" versuffix=".$current" ;; sunos) major=".$current" versuffix=".$current.$revision" ;; windows) # Use '-' rather than '.', since we only want one # extension on DOS 8.3 filesystems. func_arith $current - $age major=$func_arith_result versuffix="-$major" ;; *) func_fatal_configuration "unknown library version type \`$version_type'" ;; esac # Clear the version info if we defaulted, and they specified a release. if test -z "$vinfo" && test -n "$release"; then major= case $version_type in darwin) # we can't check for "0.0" in archive_cmds due to quoting # problems, so we reset it completely verstring= ;; *) verstring="0.0" ;; esac if test "$need_version" = no; then versuffix= else versuffix=".0.0" fi fi # Remove version info from name if versioning should be avoided if test "$avoid_version" = yes && test "$need_version" = no; then major= versuffix= verstring="" fi # Check to see if the archive will have undefined symbols. if test "$allow_undefined" = yes; then if test "$allow_undefined_flag" = unsupported; then func_warning "undefined symbols not allowed in $host shared libraries" build_libtool_libs=no build_old_libs=yes fi else # Don't allow undefined symbols. allow_undefined_flag="$no_undefined_flag" fi fi func_generate_dlsyms "$libname" "$libname" "yes" libobjs="$libobjs $symfileobj" test "X$libobjs" = "X " && libobjs= if test "$mode" != relink; then # Remove our outputs, but don't remove object files since they # may have been created when compiling PIC objects. removelist= tempremovelist=`$ECHO "$output_objdir/*"` for p in $tempremovelist; do case $p in *.$objext | *.gcno) ;; $output_objdir/$outputname | $output_objdir/$libname.* | $output_objdir/${libname}${release}.*) if test "X$precious_files_regex" != "X"; then if $ECHO "$p" | $EGREP -e "$precious_files_regex" >/dev/null 2>&1 then continue fi fi removelist="$removelist $p" ;; *) ;; esac done test -n "$removelist" && \ func_show_eval "${RM}r \$removelist" fi # Now set the variables for building old libraries. if test "$build_old_libs" = yes && test "$build_libtool_libs" != convenience ; then oldlibs="$oldlibs $output_objdir/$libname.$libext" # Transform .lo files to .o files. oldobjs="$objs "`$ECHO "X$libobjs" | $SP2NL | $Xsed -e '/\.'${libext}'$/d' -e "$lo2o" | $NL2SP` fi # Eliminate all temporary directories. #for path in $notinst_path; do # lib_search_path=`$ECHO "X$lib_search_path " | $Xsed -e "s% $path % %g"` # deplibs=`$ECHO "X$deplibs " | $Xsed -e "s% -L$path % %g"` # dependency_libs=`$ECHO "X$dependency_libs " | $Xsed -e "s% -L$path % %g"` #done if test -n "$xrpath"; then # If the user specified any rpath flags, then add them. temp_xrpath= for libdir in $xrpath; do temp_xrpath="$temp_xrpath -R$libdir" case "$finalize_rpath " in *" $libdir "*) ;; *) finalize_rpath="$finalize_rpath $libdir" ;; esac done if test "$hardcode_into_libs" != yes || test "$build_old_libs" = yes; then dependency_libs="$temp_xrpath $dependency_libs" fi fi # Make sure dlfiles contains only unique files that won't be dlpreopened old_dlfiles="$dlfiles" dlfiles= for lib in $old_dlfiles; do case " $dlprefiles $dlfiles " in *" $lib "*) ;; *) dlfiles="$dlfiles $lib" ;; esac done # Make sure dlprefiles contains only unique files old_dlprefiles="$dlprefiles" dlprefiles= for lib in $old_dlprefiles; do case "$dlprefiles " in *" $lib "*) ;; *) dlprefiles="$dlprefiles $lib" ;; esac done if test "$build_libtool_libs" = yes; then if test -n "$rpath"; then case $host in *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-*-beos* | *-cegcc*) # these systems don't actually have a c library (as such)! ;; *-*-rhapsody* | *-*-darwin1.[012]) # Rhapsody C library is in the System framework deplibs="$deplibs System.ltframework" ;; *-*-netbsd*) # Don't link with libc until the a.out ld.so is fixed. ;; *-*-openbsd* | *-*-freebsd* | *-*-dragonfly*) # Do not include libc due to us having libc/libc_r. ;; *-*-sco3.2v5* | *-*-sco5v6*) # Causes problems with __ctype ;; *-*-sysv4.2uw2* | *-*-sysv5* | *-*-unixware* | *-*-OpenUNIX*) # Compiler inserts libc in the correct place for threads to work ;; *) # Add libc to deplibs on all other systems if necessary. if test "$build_libtool_need_lc" = "yes"; then deplibs="$deplibs -lc" fi ;; esac fi # Transform deplibs into only deplibs that can be linked in shared. name_save=$name libname_save=$libname release_save=$release versuffix_save=$versuffix major_save=$major # I'm not sure if I'm treating the release correctly. I think # release should show up in the -l (ie -lgmp5) so we don't want to # add it in twice. Is that correct? release="" versuffix="" major="" newdeplibs= droppeddeps=no case $deplibs_check_method in pass_all) # Don't check for shared/static. Everything works. # This might be a little naive. We might want to check # whether the library exists or not. But this is on # osf3 & osf4 and I'm not really sure... Just # implementing what was already the behavior. newdeplibs=$deplibs ;; test_compile) # This code stresses the "libraries are programs" paradigm to its # limits. Maybe even breaks it. We compile a program, linking it # against the deplibs as a proxy for the library. Then we can check # whether they linked in statically or dynamically with ldd. $opt_dry_run || $RM conftest.c cat > conftest.c </dev/null` for potent_lib in $potential_libs; do # Follow soft links. if ls -lLd "$potent_lib" 2>/dev/null | $GREP " -> " >/dev/null; then continue fi # The statement above tries to avoid entering an # endless loop below, in case of cyclic links. # We might still enter an endless loop, since a link # loop can be closed while we follow links, # but so what? potlib="$potent_lib" while test -h "$potlib" 2>/dev/null; do potliblink=`ls -ld $potlib | ${SED} 's/.* -> //'` case $potliblink in [\\/]* | [A-Za-z]:[\\/]*) potlib="$potliblink";; *) potlib=`$ECHO "X$potlib" | $Xsed -e 's,[^/]*$,,'`"$potliblink";; esac done if eval $file_magic_cmd \"\$potlib\" 2>/dev/null | $SED -e 10q | $EGREP "$file_magic_regex" > /dev/null; then newdeplibs="$newdeplibs $a_deplib" a_deplib="" break 2 fi done done fi if test -n "$a_deplib" ; then droppeddeps=yes $ECHO $ECHO "*** Warning: linker path does not have real file for library $a_deplib." $ECHO "*** I have the capability to make that library automatically link in when" $ECHO "*** you link to this library. But I can only do this if you have a" $ECHO "*** shared version of the library, which you do not appear to have" $ECHO "*** because I did check the linker path looking for a file starting" if test -z "$potlib" ; then $ECHO "*** with $libname but no candidates were found. (...for file magic test)" else $ECHO "*** with $libname and none of the candidates passed a file format test" $ECHO "*** using a file magic. Last file checked: $potlib" fi fi ;; *) # Add a -L argument. newdeplibs="$newdeplibs $a_deplib" ;; esac done # Gone through all deplibs. ;; match_pattern*) set dummy $deplibs_check_method; shift match_pattern_regex=`expr "$deplibs_check_method" : "$1 \(.*\)"` for a_deplib in $deplibs; do case $a_deplib in -l*) func_stripname -l '' "$a_deplib" name=$func_stripname_result if test "X$allow_libtool_libs_with_static_runtimes" = "Xyes" ; then case " $predeps $postdeps " in *" $a_deplib "*) newdeplibs="$newdeplibs $a_deplib" a_deplib="" ;; esac fi if test -n "$a_deplib" ; then libname=`eval "\\$ECHO \"$libname_spec\""` for i in $lib_search_path $sys_lib_search_path $shlib_search_path; do potential_libs=`ls $i/$libname[.-]* 2>/dev/null` for potent_lib in $potential_libs; do potlib="$potent_lib" # see symlink-check above in file_magic test if eval "\$ECHO \"X$potent_lib\"" 2>/dev/null | $Xsed -e 10q | \ $EGREP "$match_pattern_regex" > /dev/null; then newdeplibs="$newdeplibs $a_deplib" a_deplib="" break 2 fi done done fi if test -n "$a_deplib" ; then droppeddeps=yes $ECHO $ECHO "*** Warning: linker path does not have real file for library $a_deplib." $ECHO "*** I have the capability to make that library automatically link in when" $ECHO "*** you link to this library. But I can only do this if you have a" $ECHO "*** shared version of the library, which you do not appear to have" $ECHO "*** because I did check the linker path looking for a file starting" if test -z "$potlib" ; then $ECHO "*** with $libname but no candidates were found. (...for regex pattern test)" else $ECHO "*** with $libname and none of the candidates passed a file format test" $ECHO "*** using a regex pattern. Last file checked: $potlib" fi fi ;; *) # Add a -L argument. newdeplibs="$newdeplibs $a_deplib" ;; esac done # Gone through all deplibs. ;; none | unknown | *) newdeplibs="" tmp_deplibs=`$ECHO "X $deplibs" | $Xsed \ -e 's/ -lc$//' -e 's/ -[LR][^ ]*//g'` if test "X$allow_libtool_libs_with_static_runtimes" = "Xyes" ; then for i in $predeps $postdeps ; do # can't use Xsed below, because $i might contain '/' tmp_deplibs=`$ECHO "X $tmp_deplibs" | $Xsed -e "s,$i,,"` done fi if $ECHO "X $tmp_deplibs" | $Xsed -e 's/[ ]//g' | $GREP . >/dev/null; then $ECHO if test "X$deplibs_check_method" = "Xnone"; then $ECHO "*** Warning: inter-library dependencies are not supported in this platform." else $ECHO "*** Warning: inter-library dependencies are not known to be supported." fi $ECHO "*** All declared inter-library dependencies are being dropped." droppeddeps=yes fi ;; esac versuffix=$versuffix_save major=$major_save release=$release_save libname=$libname_save name=$name_save case $host in *-*-rhapsody* | *-*-darwin1.[012]) # On Rhapsody replace the C library with the System framework newdeplibs=`$ECHO "X $newdeplibs" | $Xsed -e 's/ -lc / System.ltframework /'` ;; esac if test "$droppeddeps" = yes; then if test "$module" = yes; then $ECHO $ECHO "*** Warning: libtool could not satisfy all declared inter-library" $ECHO "*** dependencies of module $libname. Therefore, libtool will create" $ECHO "*** a static module, that should work as long as the dlopening" $ECHO "*** application is linked with the -dlopen flag." if test -z "$global_symbol_pipe"; then $ECHO $ECHO "*** However, this would only work if libtool was able to extract symbol" $ECHO "*** lists from a program, using \`nm' or equivalent, but libtool could" $ECHO "*** not find such a program. So, this module is probably useless." $ECHO "*** \`nm' from GNU binutils and a full rebuild may help." fi if test "$build_old_libs" = no; then oldlibs="$output_objdir/$libname.$libext" build_libtool_libs=module build_old_libs=yes else build_libtool_libs=no fi else $ECHO "*** The inter-library dependencies that have been dropped here will be" $ECHO "*** automatically added whenever a program is linked with this library" $ECHO "*** or is declared to -dlopen it." if test "$allow_undefined" = no; then $ECHO $ECHO "*** Since this library must not contain undefined symbols," $ECHO "*** because either the platform does not support them or" $ECHO "*** it was explicitly requested with -no-undefined," $ECHO "*** libtool will only create a static version of it." if test "$build_old_libs" = no; then oldlibs="$output_objdir/$libname.$libext" build_libtool_libs=module build_old_libs=yes else build_libtool_libs=no fi fi fi fi # Done checking deplibs! deplibs=$newdeplibs fi # Time to change all our "foo.ltframework" stuff back to "-framework foo" case $host in *-*-darwin*) newdeplibs=`$ECHO "X $newdeplibs" | $Xsed -e 's% \([^ $]*\).ltframework% -framework \1%g'` new_inherited_linker_flags=`$ECHO "X $new_inherited_linker_flags" | $Xsed -e 's% \([^ $]*\).ltframework% -framework \1%g'` deplibs=`$ECHO "X $deplibs" | $Xsed -e 's% \([^ $]*\).ltframework% -framework \1%g'` ;; esac # move library search paths that coincide with paths to not yet # installed libraries to the beginning of the library search list new_libs= for path in $notinst_path; do case " $new_libs " in *" -L$path/$objdir "*) ;; *) case " $deplibs " in *" -L$path/$objdir "*) new_libs="$new_libs -L$path/$objdir" ;; esac ;; esac done for deplib in $deplibs; do case $deplib in -L*) case " $new_libs " in *" $deplib "*) ;; *) new_libs="$new_libs $deplib" ;; esac ;; *) new_libs="$new_libs $deplib" ;; esac done deplibs="$new_libs" # All the library-specific variables (install_libdir is set above). library_names= old_library= dlname= # Test again, we may have decided not to build it any more if test "$build_libtool_libs" = yes; then if test "$hardcode_into_libs" = yes; then # Hardcode the library paths hardcode_libdirs= dep_rpath= rpath="$finalize_rpath" test "$mode" != relink && rpath="$compile_rpath$rpath" for libdir in $rpath; do if test -n "$hardcode_libdir_flag_spec"; then if test -n "$hardcode_libdir_separator"; then if test -z "$hardcode_libdirs"; then hardcode_libdirs="$libdir" else # Just accumulate the unique libdirs. case $hardcode_libdir_separator$hardcode_libdirs$hardcode_libdir_separator in *"$hardcode_libdir_separator$libdir$hardcode_libdir_separator"*) ;; *) hardcode_libdirs="$hardcode_libdirs$hardcode_libdir_separator$libdir" ;; esac fi else eval flag=\"$hardcode_libdir_flag_spec\" dep_rpath="$dep_rpath $flag" fi elif test -n "$runpath_var"; then case "$perm_rpath " in *" $libdir "*) ;; *) perm_rpath="$perm_rpath $libdir" ;; esac fi done # Substitute the hardcoded libdirs into the rpath. if test -n "$hardcode_libdir_separator" && test -n "$hardcode_libdirs"; then libdir="$hardcode_libdirs" if test -n "$hardcode_libdir_flag_spec_ld"; then eval dep_rpath=\"$hardcode_libdir_flag_spec_ld\" else eval dep_rpath=\"$hardcode_libdir_flag_spec\" fi fi if test -n "$runpath_var" && test -n "$perm_rpath"; then # We should set the runpath_var. rpath= for dir in $perm_rpath; do rpath="$rpath$dir:" done eval "$runpath_var='$rpath\$$runpath_var'; export $runpath_var" fi test -n "$dep_rpath" && deplibs="$dep_rpath $deplibs" fi shlibpath="$finalize_shlibpath" test "$mode" != relink && shlibpath="$compile_shlibpath$shlibpath" if test -n "$shlibpath"; then eval "$shlibpath_var='$shlibpath\$$shlibpath_var'; export $shlibpath_var" fi # Get the real and link names of the library. eval shared_ext=\"$shrext_cmds\" eval library_names=\"$library_names_spec\" set dummy $library_names shift realname="$1" shift if test -n "$soname_spec"; then eval soname=\"$soname_spec\" else soname="$realname" fi if test -z "$dlname"; then dlname=$soname fi lib="$output_objdir/$realname" linknames= for link do linknames="$linknames $link" done # Use standard objects if they are pic test -z "$pic_flag" && libobjs=`$ECHO "X$libobjs" | $SP2NL | $Xsed -e "$lo2o" | $NL2SP` test "X$libobjs" = "X " && libobjs= delfiles= if test -n "$export_symbols" && test -n "$include_expsyms"; then $opt_dry_run || cp "$export_symbols" "$output_objdir/$libname.uexp" export_symbols="$output_objdir/$libname.uexp" delfiles="$delfiles $export_symbols" fi orig_export_symbols= case $host_os in cygwin* | mingw* | cegcc*) if test -n "$export_symbols" && test -z "$export_symbols_regex"; then # exporting using user supplied symfile if test "x`$SED 1q $export_symbols`" != xEXPORTS; then # and it's NOT already a .def file. Must figure out # which of the given symbols are data symbols and tag # them as such. So, trigger use of export_symbols_cmds. # export_symbols gets reassigned inside the "prepare # the list of exported symbols" if statement, so the # include_expsyms logic still works. orig_export_symbols="$export_symbols" export_symbols= always_export_symbols=yes fi fi ;; esac # Prepare the list of exported symbols if test -z "$export_symbols"; then if test "$always_export_symbols" = yes || test -n "$export_symbols_regex"; then func_verbose "generating symbol list for \`$libname.la'" export_symbols="$output_objdir/$libname.exp" $opt_dry_run || $RM $export_symbols cmds=$export_symbols_cmds save_ifs="$IFS"; IFS='~' for cmd in $cmds; do IFS="$save_ifs" eval cmd=\"$cmd\" func_len " $cmd" len=$func_len_result if test "$len" -lt "$max_cmd_len" || test "$max_cmd_len" -le -1; then func_show_eval "$cmd" 'exit $?' skipped_export=false else # The command line is too long to execute in one step. func_verbose "using reloadable object file for export list..." skipped_export=: # Break out early, otherwise skipped_export may be # set to false by a later but shorter cmd. break fi done IFS="$save_ifs" if test -n "$export_symbols_regex" && test "X$skipped_export" != "X:"; then func_show_eval '$EGREP -e "$export_symbols_regex" "$export_symbols" > "${export_symbols}T"' func_show_eval '$MV "${export_symbols}T" "$export_symbols"' fi fi fi if test -n "$export_symbols" && test -n "$include_expsyms"; then tmp_export_symbols="$export_symbols" test -n "$orig_export_symbols" && tmp_export_symbols="$orig_export_symbols" $opt_dry_run || eval '$ECHO "X$include_expsyms" | $Xsed | $SP2NL >> "$tmp_export_symbols"' fi if test "X$skipped_export" != "X:" && test -n "$orig_export_symbols"; then # The given exports_symbols file has to be filtered, so filter it. func_verbose "filter symbol list for \`$libname.la' to tag DATA exports" # FIXME: $output_objdir/$libname.filter potentially contains lots of # 's' commands which not all seds can handle. GNU sed should be fine # though. Also, the filter scales superlinearly with the number of # global variables. join(1) would be nice here, but unfortunately # isn't a blessed tool. $opt_dry_run || $SED -e '/[ ,]DATA/!d;s,\(.*\)\([ \,].*\),s|^\1$|\1\2|,' < $export_symbols > $output_objdir/$libname.filter delfiles="$delfiles $export_symbols $output_objdir/$libname.filter" export_symbols=$output_objdir/$libname.def $opt_dry_run || $SED -f $output_objdir/$libname.filter < $orig_export_symbols > $export_symbols fi tmp_deplibs= for test_deplib in $deplibs; do case " $convenience " in *" $test_deplib "*) ;; *) tmp_deplibs="$tmp_deplibs $test_deplib" ;; esac done deplibs="$tmp_deplibs" if test -n "$convenience"; then if test -n "$whole_archive_flag_spec" && test "$compiler_needs_object" = yes && test -z "$libobjs"; then # extract the archives, so we have objects to list. # TODO: could optimize this to just extract one archive. whole_archive_flag_spec= fi if test -n "$whole_archive_flag_spec"; then save_libobjs=$libobjs eval libobjs=\"\$libobjs $whole_archive_flag_spec\" test "X$libobjs" = "X " && libobjs= else gentop="$output_objdir/${outputname}x" generated="$generated $gentop" func_extract_archives $gentop $convenience libobjs="$libobjs $func_extract_archives_result" test "X$libobjs" = "X " && libobjs= fi fi if test "$thread_safe" = yes && test -n "$thread_safe_flag_spec"; then eval flag=\"$thread_safe_flag_spec\" linker_flags="$linker_flags $flag" fi # Make a backup of the uninstalled library when relinking if test "$mode" = relink; then $opt_dry_run || eval '(cd $output_objdir && $RM ${realname}U && $MV $realname ${realname}U)' || exit $? fi # Do each of the archive commands. if test "$module" = yes && test -n "$module_cmds" ; then if test -n "$export_symbols" && test -n "$module_expsym_cmds"; then eval test_cmds=\"$module_expsym_cmds\" cmds=$module_expsym_cmds else eval test_cmds=\"$module_cmds\" cmds=$module_cmds fi else if test -n "$export_symbols" && test -n "$archive_expsym_cmds"; then eval test_cmds=\"$archive_expsym_cmds\" cmds=$archive_expsym_cmds else eval test_cmds=\"$archive_cmds\" cmds=$archive_cmds fi fi if test "X$skipped_export" != "X:" && func_len " $test_cmds" && len=$func_len_result && test "$len" -lt "$max_cmd_len" || test "$max_cmd_len" -le -1; then : else # The command line is too long to link in one step, link piecewise # or, if using GNU ld and skipped_export is not :, use a linker # script. # Save the value of $output and $libobjs because we want to # use them later. If we have whole_archive_flag_spec, we # want to use save_libobjs as it was before # whole_archive_flag_spec was expanded, because we can't # assume the linker understands whole_archive_flag_spec. # This may have to be revisited, in case too many # convenience libraries get linked in and end up exceeding # the spec. if test -z "$convenience" || test -z "$whole_archive_flag_spec"; then save_libobjs=$libobjs fi save_output=$output output_la=`$ECHO "X$output" | $Xsed -e "$basename"` # Clear the reloadable object creation command queue and # initialize k to one. test_cmds= concat_cmds= objlist= last_robj= k=1 if test -n "$save_libobjs" && test "X$skipped_export" != "X:" && test "$with_gnu_ld" = yes; then output=${output_objdir}/${output_la}.lnkscript func_verbose "creating GNU ld script: $output" $ECHO 'INPUT (' > $output for obj in $save_libobjs do $ECHO "$obj" >> $output done $ECHO ')' >> $output delfiles="$delfiles $output" elif test -n "$save_libobjs" && test "X$skipped_export" != "X:" && test "X$file_list_spec" != X; then output=${output_objdir}/${output_la}.lnk func_verbose "creating linker input file list: $output" : > $output set x $save_libobjs shift firstobj= if test "$compiler_needs_object" = yes; then firstobj="$1 " shift fi for obj do $ECHO "$obj" >> $output done delfiles="$delfiles $output" output=$firstobj\"$file_list_spec$output\" else if test -n "$save_libobjs"; then func_verbose "creating reloadable object files..." output=$output_objdir/$output_la-${k}.$objext eval test_cmds=\"$reload_cmds\" func_len " $test_cmds" len0=$func_len_result len=$len0 # Loop over the list of objects to be linked. for obj in $save_libobjs do func_len " $obj" func_arith $len + $func_len_result len=$func_arith_result if test "X$objlist" = X || test "$len" -lt "$max_cmd_len"; then func_append objlist " $obj" else # The command $test_cmds is almost too long, add a # command to the queue. if test "$k" -eq 1 ; then # The first file doesn't have a previous command to add. eval concat_cmds=\"$reload_cmds $objlist $last_robj\" else # All subsequent reloadable object files will link in # the last one created. eval concat_cmds=\"\$concat_cmds~$reload_cmds $objlist $last_robj~\$RM $last_robj\" fi last_robj=$output_objdir/$output_la-${k}.$objext func_arith $k + 1 k=$func_arith_result output=$output_objdir/$output_la-${k}.$objext objlist=$obj func_len " $last_robj" func_arith $len0 + $func_len_result len=$func_arith_result fi done # Handle the remaining objects by creating one last # reloadable object file. All subsequent reloadable object # files will link in the last one created. test -z "$concat_cmds" || concat_cmds=$concat_cmds~ eval concat_cmds=\"\${concat_cmds}$reload_cmds $objlist $last_robj\" if test -n "$last_robj"; then eval concat_cmds=\"\${concat_cmds}~\$RM $last_robj\" fi delfiles="$delfiles $output" else output= fi if ${skipped_export-false}; then func_verbose "generating symbol list for \`$libname.la'" export_symbols="$output_objdir/$libname.exp" $opt_dry_run || $RM $export_symbols libobjs=$output # Append the command to create the export file. test -z "$concat_cmds" || concat_cmds=$concat_cmds~ eval concat_cmds=\"\$concat_cmds$export_symbols_cmds\" if test -n "$last_robj"; then eval concat_cmds=\"\$concat_cmds~\$RM $last_robj\" fi fi test -n "$save_libobjs" && func_verbose "creating a temporary reloadable object file: $output" # Loop through the commands generated above and execute them. save_ifs="$IFS"; IFS='~' for cmd in $concat_cmds; do IFS="$save_ifs" $opt_silent || { func_quote_for_expand "$cmd" eval "func_echo $func_quote_for_expand_result" } $opt_dry_run || eval "$cmd" || { lt_exit=$? # Restore the uninstalled library and exit if test "$mode" = relink; then ( cd "$output_objdir" && \ $RM "${realname}T" && \ $MV "${realname}U" "$realname" ) fi exit $lt_exit } done IFS="$save_ifs" if test -n "$export_symbols_regex" && ${skipped_export-false}; then func_show_eval '$EGREP -e "$export_symbols_regex" "$export_symbols" > "${export_symbols}T"' func_show_eval '$MV "${export_symbols}T" "$export_symbols"' fi fi if ${skipped_export-false}; then if test -n "$export_symbols" && test -n "$include_expsyms"; then tmp_export_symbols="$export_symbols" test -n "$orig_export_symbols" && tmp_export_symbols="$orig_export_symbols" $opt_dry_run || eval '$ECHO "X$include_expsyms" | $Xsed | $SP2NL >> "$tmp_export_symbols"' fi if test -n "$orig_export_symbols"; then # The given exports_symbols file has to be filtered, so filter it. func_verbose "filter symbol list for \`$libname.la' to tag DATA exports" # FIXME: $output_objdir/$libname.filter potentially contains lots of # 's' commands which not all seds can handle. GNU sed should be fine # though. Also, the filter scales superlinearly with the number of # global variables. join(1) would be nice here, but unfortunately # isn't a blessed tool. $opt_dry_run || $SED -e '/[ ,]DATA/!d;s,\(.*\)\([ \,].*\),s|^\1$|\1\2|,' < $export_symbols > $output_objdir/$libname.filter delfiles="$delfiles $export_symbols $output_objdir/$libname.filter" export_symbols=$output_objdir/$libname.def $opt_dry_run || $SED -f $output_objdir/$libname.filter < $orig_export_symbols > $export_symbols fi fi libobjs=$output # Restore the value of output. output=$save_output if test -n "$convenience" && test -n "$whole_archive_flag_spec"; then eval libobjs=\"\$libobjs $whole_archive_flag_spec\" test "X$libobjs" = "X " && libobjs= fi # Expand the library linking commands again to reset the # value of $libobjs for piecewise linking. # Do each of the archive commands. if test "$module" = yes && test -n "$module_cmds" ; then if test -n "$export_symbols" && test -n "$module_expsym_cmds"; then cmds=$module_expsym_cmds else cmds=$module_cmds fi else if test -n "$export_symbols" && test -n "$archive_expsym_cmds"; then cmds=$archive_expsym_cmds else cmds=$archive_cmds fi fi fi if test -n "$delfiles"; then # Append the command to remove temporary files to $cmds. eval cmds=\"\$cmds~\$RM $delfiles\" fi # Add any objects from preloaded convenience libraries if test -n "$dlprefiles"; then gentop="$output_objdir/${outputname}x" generated="$generated $gentop" func_extract_archives $gentop $dlprefiles libobjs="$libobjs $func_extract_archives_result" test "X$libobjs" = "X " && libobjs= fi save_ifs="$IFS"; IFS='~' for cmd in $cmds; do IFS="$save_ifs" eval cmd=\"$cmd\" $opt_silent || { func_quote_for_expand "$cmd" eval "func_echo $func_quote_for_expand_result" } $opt_dry_run || eval "$cmd" || { lt_exit=$? # Restore the uninstalled library and exit if test "$mode" = relink; then ( cd "$output_objdir" && \ $RM "${realname}T" && \ $MV "${realname}U" "$realname" ) fi exit $lt_exit } done IFS="$save_ifs" # Restore the uninstalled library and exit if test "$mode" = relink; then $opt_dry_run || eval '(cd $output_objdir && $RM ${realname}T && $MV $realname ${realname}T && $MV ${realname}U $realname)' || exit $? if test -n "$convenience"; then if test -z "$whole_archive_flag_spec"; then func_show_eval '${RM}r "$gentop"' fi fi exit $EXIT_SUCCESS fi # Create links to the real library. for linkname in $linknames; do if test "$realname" != "$linkname"; then func_show_eval '(cd "$output_objdir" && $RM "$linkname" && $LN_S "$realname" "$linkname")' 'exit $?' fi done # If -module or -export-dynamic was specified, set the dlname. if test "$module" = yes || test "$export_dynamic" = yes; then # On all known operating systems, these are identical. dlname="$soname" fi fi ;; obj) if test -n "$dlfiles$dlprefiles" || test "$dlself" != no; then func_warning "\`-dlopen' is ignored for objects" fi case " $deplibs" in *\ -l* | *\ -L*) func_warning "\`-l' and \`-L' are ignored for objects" ;; esac test -n "$rpath" && \ func_warning "\`-rpath' is ignored for objects" test -n "$xrpath" && \ func_warning "\`-R' is ignored for objects" test -n "$vinfo" && \ func_warning "\`-version-info' is ignored for objects" test -n "$release" && \ func_warning "\`-release' is ignored for objects" case $output in *.lo) test -n "$objs$old_deplibs" && \ func_fatal_error "cannot build library object \`$output' from non-libtool objects" libobj=$output func_lo2o "$libobj" obj=$func_lo2o_result ;; *) libobj= obj="$output" ;; esac # Delete the old objects. $opt_dry_run || $RM $obj $libobj # Objects from convenience libraries. This assumes # single-version convenience libraries. Whenever we create # different ones for PIC/non-PIC, this we'll have to duplicate # the extraction. reload_conv_objs= gentop= # reload_cmds runs $LD directly, so let us get rid of # -Wl from whole_archive_flag_spec and hope we can get by with # turning comma into space.. wl= if test -n "$convenience"; then if test -n "$whole_archive_flag_spec"; then eval tmp_whole_archive_flags=\"$whole_archive_flag_spec\" reload_conv_objs=$reload_objs\ `$ECHO "X$tmp_whole_archive_flags" | $Xsed -e 's|,| |g'` else gentop="$output_objdir/${obj}x" generated="$generated $gentop" func_extract_archives $gentop $convenience reload_conv_objs="$reload_objs $func_extract_archives_result" fi fi # Create the old-style object. reload_objs="$objs$old_deplibs "`$ECHO "X$libobjs" | $SP2NL | $Xsed -e '/\.'${libext}$'/d' -e '/\.lib$/d' -e "$lo2o" | $NL2SP`" $reload_conv_objs" ### testsuite: skip nested quoting test output="$obj" func_execute_cmds "$reload_cmds" 'exit $?' # Exit if we aren't doing a library object file. if test -z "$libobj"; then if test -n "$gentop"; then func_show_eval '${RM}r "$gentop"' fi exit $EXIT_SUCCESS fi if test "$build_libtool_libs" != yes; then if test -n "$gentop"; then func_show_eval '${RM}r "$gentop"' fi # Create an invalid libtool object if no PIC, so that we don't # accidentally link it into a program. # $show "echo timestamp > $libobj" # $opt_dry_run || eval "echo timestamp > $libobj" || exit $? exit $EXIT_SUCCESS fi if test -n "$pic_flag" || test "$pic_mode" != default; then # Only do commands if we really have different PIC objects. reload_objs="$libobjs $reload_conv_objs" output="$libobj" func_execute_cmds "$reload_cmds" 'exit $?' fi if test -n "$gentop"; then func_show_eval '${RM}r "$gentop"' fi exit $EXIT_SUCCESS ;; prog) case $host in *cygwin*) func_stripname '' '.exe' "$output" output=$func_stripname_result.exe;; esac test -n "$vinfo" && \ func_warning "\`-version-info' is ignored for programs" test -n "$release" && \ func_warning "\`-release' is ignored for programs" test "$preload" = yes \ && test "$dlopen_support" = unknown \ && test "$dlopen_self" = unknown \ && test "$dlopen_self_static" = unknown && \ func_warning "\`LT_INIT([dlopen])' not used. Assuming no dlopen support." case $host in *-*-rhapsody* | *-*-darwin1.[012]) # On Rhapsody replace the C library is the System framework compile_deplibs=`$ECHO "X $compile_deplibs" | $Xsed -e 's/ -lc / System.ltframework /'` finalize_deplibs=`$ECHO "X $finalize_deplibs" | $Xsed -e 's/ -lc / System.ltframework /'` ;; esac case $host in *-*-darwin*) # Don't allow lazy linking, it breaks C++ global constructors # But is supposedly fixed on 10.4 or later (yay!). if test "$tagname" = CXX ; then case ${MACOSX_DEPLOYMENT_TARGET-10.0} in 10.[0123]) compile_command="$compile_command ${wl}-bind_at_load" finalize_command="$finalize_command ${wl}-bind_at_load" ;; esac fi # Time to change all our "foo.ltframework" stuff back to "-framework foo" compile_deplibs=`$ECHO "X $compile_deplibs" | $Xsed -e 's% \([^ $]*\).ltframework% -framework \1%g'` finalize_deplibs=`$ECHO "X $finalize_deplibs" | $Xsed -e 's% \([^ $]*\).ltframework% -framework \1%g'` ;; esac # move library search paths that coincide with paths to not yet # installed libraries to the beginning of the library search list new_libs= for path in $notinst_path; do case " $new_libs " in *" -L$path/$objdir "*) ;; *) case " $compile_deplibs " in *" -L$path/$objdir "*) new_libs="$new_libs -L$path/$objdir" ;; esac ;; esac done for deplib in $compile_deplibs; do case $deplib in -L*) case " $new_libs " in *" $deplib "*) ;; *) new_libs="$new_libs $deplib" ;; esac ;; *) new_libs="$new_libs $deplib" ;; esac done compile_deplibs="$new_libs" compile_command="$compile_command $compile_deplibs" finalize_command="$finalize_command $finalize_deplibs" if test -n "$rpath$xrpath"; then # If the user specified any rpath flags, then add them. for libdir in $rpath $xrpath; do # This is the magic to use -rpath. case "$finalize_rpath " in *" $libdir "*) ;; *) finalize_rpath="$finalize_rpath $libdir" ;; esac done fi # Now hardcode the library paths rpath= hardcode_libdirs= for libdir in $compile_rpath $finalize_rpath; do if test -n "$hardcode_libdir_flag_spec"; then if test -n "$hardcode_libdir_separator"; then if test -z "$hardcode_libdirs"; then hardcode_libdirs="$libdir" else # Just accumulate the unique libdirs. case $hardcode_libdir_separator$hardcode_libdirs$hardcode_libdir_separator in *"$hardcode_libdir_separator$libdir$hardcode_libdir_separator"*) ;; *) hardcode_libdirs="$hardcode_libdirs$hardcode_libdir_separator$libdir" ;; esac fi else eval flag=\"$hardcode_libdir_flag_spec\" rpath="$rpath $flag" fi elif test -n "$runpath_var"; then case "$perm_rpath " in *" $libdir "*) ;; *) perm_rpath="$perm_rpath $libdir" ;; esac fi case $host in *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-cegcc*) testbindir=`${ECHO} "$libdir" | ${SED} -e 's*/lib$*/bin*'` case :$dllsearchpath: in *":$libdir:"*) ;; ::) dllsearchpath=$libdir;; *) dllsearchpath="$dllsearchpath:$libdir";; esac case :$dllsearchpath: in *":$testbindir:"*) ;; ::) dllsearchpath=$testbindir;; *) dllsearchpath="$dllsearchpath:$testbindir";; esac ;; esac done # Substitute the hardcoded libdirs into the rpath. if test -n "$hardcode_libdir_separator" && test -n "$hardcode_libdirs"; then libdir="$hardcode_libdirs" eval rpath=\" $hardcode_libdir_flag_spec\" fi compile_rpath="$rpath" rpath= hardcode_libdirs= for libdir in $finalize_rpath; do if test -n "$hardcode_libdir_flag_spec"; then if test -n "$hardcode_libdir_separator"; then if test -z "$hardcode_libdirs"; then hardcode_libdirs="$libdir" else # Just accumulate the unique libdirs. case $hardcode_libdir_separator$hardcode_libdirs$hardcode_libdir_separator in *"$hardcode_libdir_separator$libdir$hardcode_libdir_separator"*) ;; *) hardcode_libdirs="$hardcode_libdirs$hardcode_libdir_separator$libdir" ;; esac fi else eval flag=\"$hardcode_libdir_flag_spec\" rpath="$rpath $flag" fi elif test -n "$runpath_var"; then case "$finalize_perm_rpath " in *" $libdir "*) ;; *) finalize_perm_rpath="$finalize_perm_rpath $libdir" ;; esac fi done # Substitute the hardcoded libdirs into the rpath. if test -n "$hardcode_libdir_separator" && test -n "$hardcode_libdirs"; then libdir="$hardcode_libdirs" eval rpath=\" $hardcode_libdir_flag_spec\" fi finalize_rpath="$rpath" if test -n "$libobjs" && test "$build_old_libs" = yes; then # Transform all the library objects into standard objects. compile_command=`$ECHO "X$compile_command" | $SP2NL | $Xsed -e "$lo2o" | $NL2SP` finalize_command=`$ECHO "X$finalize_command" | $SP2NL | $Xsed -e "$lo2o" | $NL2SP` fi func_generate_dlsyms "$outputname" "@PROGRAM@" "no" # template prelinking step if test -n "$prelink_cmds"; then func_execute_cmds "$prelink_cmds" 'exit $?' fi wrappers_required=yes case $host in *cygwin* | *mingw* ) if test "$build_libtool_libs" != yes; then wrappers_required=no fi ;; *cegcc) # Disable wrappers for cegcc, we are cross compiling anyway. wrappers_required=no ;; *) if test "$need_relink" = no || test "$build_libtool_libs" != yes; then wrappers_required=no fi ;; esac if test "$wrappers_required" = no; then # Replace the output file specification. compile_command=`$ECHO "X$compile_command" | $Xsed -e 's%@OUTPUT@%'"$output"'%g'` link_command="$compile_command$compile_rpath" # We have no uninstalled library dependencies, so finalize right now. exit_status=0 func_show_eval "$link_command" 'exit_status=$?' # Delete the generated files. if test -f "$output_objdir/${outputname}S.${objext}"; then func_show_eval '$RM "$output_objdir/${outputname}S.${objext}"' fi exit $exit_status fi if test -n "$compile_shlibpath$finalize_shlibpath"; then compile_command="$shlibpath_var=\"$compile_shlibpath$finalize_shlibpath\$$shlibpath_var\" $compile_command" fi if test -n "$finalize_shlibpath"; then finalize_command="$shlibpath_var=\"$finalize_shlibpath\$$shlibpath_var\" $finalize_command" fi compile_var= finalize_var= if test -n "$runpath_var"; then if test -n "$perm_rpath"; then # We should set the runpath_var. rpath= for dir in $perm_rpath; do rpath="$rpath$dir:" done compile_var="$runpath_var=\"$rpath\$$runpath_var\" " fi if test -n "$finalize_perm_rpath"; then # We should set the runpath_var. rpath= for dir in $finalize_perm_rpath; do rpath="$rpath$dir:" done finalize_var="$runpath_var=\"$rpath\$$runpath_var\" " fi fi if test "$no_install" = yes; then # We don't need to create a wrapper script. link_command="$compile_var$compile_command$compile_rpath" # Replace the output file specification. link_command=`$ECHO "X$link_command" | $Xsed -e 's%@OUTPUT@%'"$output"'%g'` # Delete the old output file. $opt_dry_run || $RM $output # Link the executable and exit func_show_eval "$link_command" 'exit $?' exit $EXIT_SUCCESS fi if test "$hardcode_action" = relink; then # Fast installation is not supported link_command="$compile_var$compile_command$compile_rpath" relink_command="$finalize_var$finalize_command$finalize_rpath" func_warning "this platform does not like uninstalled shared libraries" func_warning "\`$output' will be relinked during installation" else if test "$fast_install" != no; then link_command="$finalize_var$compile_command$finalize_rpath" if test "$fast_install" = yes; then relink_command=`$ECHO "X$compile_var$compile_command$compile_rpath" | $Xsed -e 's%@OUTPUT@%\$progdir/\$file%g'` else # fast_install is set to needless relink_command= fi else link_command="$compile_var$compile_command$compile_rpath" relink_command="$finalize_var$finalize_command$finalize_rpath" fi fi # Replace the output file specification. link_command=`$ECHO "X$link_command" | $Xsed -e 's%@OUTPUT@%'"$output_objdir/$outputname"'%g'` # Delete the old output files. $opt_dry_run || $RM $output $output_objdir/$outputname $output_objdir/lt-$outputname func_show_eval "$link_command" 'exit $?' # Now create the wrapper script. func_verbose "creating $output" # Quote the relink command for shipping. if test -n "$relink_command"; then # Preserve any variables that may affect compiler behavior for var in $variables_saved_for_relink; do if eval test -z \"\${$var+set}\"; then relink_command="{ test -z \"\${$var+set}\" || $lt_unset $var || { $var=; export $var; }; }; $relink_command" elif eval var_value=\$$var; test -z "$var_value"; then relink_command="$var=; export $var; $relink_command" else func_quote_for_eval "$var_value" relink_command="$var=$func_quote_for_eval_result; export $var; $relink_command" fi done relink_command="(cd `pwd`; $relink_command)" relink_command=`$ECHO "X$relink_command" | $Xsed -e "$sed_quote_subst"` fi # Quote $ECHO for shipping. if test "X$ECHO" = "X$SHELL $progpath --fallback-echo"; then case $progpath in [\\/]* | [A-Za-z]:[\\/]*) qecho="$SHELL $progpath --fallback-echo";; *) qecho="$SHELL `pwd`/$progpath --fallback-echo";; esac qecho=`$ECHO "X$qecho" | $Xsed -e "$sed_quote_subst"` else qecho=`$ECHO "X$ECHO" | $Xsed -e "$sed_quote_subst"` fi # Only actually do things if not in dry run mode. $opt_dry_run || { # win32 will think the script is a binary if it has # a .exe suffix, so we strip it off here. case $output in *.exe) func_stripname '' '.exe' "$output" output=$func_stripname_result ;; esac # test for cygwin because mv fails w/o .exe extensions case $host in *cygwin*) exeext=.exe func_stripname '' '.exe' "$outputname" outputname=$func_stripname_result ;; *) exeext= ;; esac case $host in *cygwin* | *mingw* ) func_dirname_and_basename "$output" "" "." output_name=$func_basename_result output_path=$func_dirname_result cwrappersource="$output_path/$objdir/lt-$output_name.c" cwrapper="$output_path/$output_name.exe" $RM $cwrappersource $cwrapper trap "$RM $cwrappersource $cwrapper; exit $EXIT_FAILURE" 1 2 15 func_emit_cwrapperexe_src > $cwrappersource # The wrapper executable is built using the $host compiler, # because it contains $host paths and files. If cross- # compiling, it, like the target executable, must be # executed on the $host or under an emulation environment. $opt_dry_run || { $LTCC $LTCFLAGS -o $cwrapper $cwrappersource $STRIP $cwrapper } # Now, create the wrapper script for func_source use: func_ltwrapper_scriptname $cwrapper $RM $func_ltwrapper_scriptname_result trap "$RM $func_ltwrapper_scriptname_result; exit $EXIT_FAILURE" 1 2 15 $opt_dry_run || { # note: this script will not be executed, so do not chmod. if test "x$build" = "x$host" ; then $cwrapper --lt-dump-script > $func_ltwrapper_scriptname_result else func_emit_wrapper no > $func_ltwrapper_scriptname_result fi } ;; * ) $RM $output trap "$RM $output; exit $EXIT_FAILURE" 1 2 15 func_emit_wrapper no > $output chmod +x $output ;; esac } exit $EXIT_SUCCESS ;; esac # See if we need to build an old-fashioned archive. for oldlib in $oldlibs; do if test "$build_libtool_libs" = convenience; then oldobjs="$libobjs_save $symfileobj" addlibs="$convenience" build_libtool_libs=no else if test "$build_libtool_libs" = module; then oldobjs="$libobjs_save" build_libtool_libs=no else oldobjs="$old_deplibs $non_pic_objects" if test "$preload" = yes && test -f "$symfileobj"; then oldobjs="$oldobjs $symfileobj" fi fi addlibs="$old_convenience" fi if test -n "$addlibs"; then gentop="$output_objdir/${outputname}x" generated="$generated $gentop" func_extract_archives $gentop $addlibs oldobjs="$oldobjs $func_extract_archives_result" fi # Do each command in the archive commands. if test -n "$old_archive_from_new_cmds" && test "$build_libtool_libs" = yes; then cmds=$old_archive_from_new_cmds else # Add any objects from preloaded convenience libraries if test -n "$dlprefiles"; then gentop="$output_objdir/${outputname}x" generated="$generated $gentop" func_extract_archives $gentop $dlprefiles oldobjs="$oldobjs $func_extract_archives_result" fi # POSIX demands no paths to be encoded in archives. We have # to avoid creating archives with duplicate basenames if we # might have to extract them afterwards, e.g., when creating a # static archive out of a convenience library, or when linking # the entirety of a libtool archive into another (currently # not supported by libtool). if (for obj in $oldobjs do func_basename "$obj" $ECHO "$func_basename_result" done | sort | sort -uc >/dev/null 2>&1); then : else $ECHO "copying selected object files to avoid basename conflicts..." gentop="$output_objdir/${outputname}x" generated="$generated $gentop" func_mkdir_p "$gentop" save_oldobjs=$oldobjs oldobjs= counter=1 for obj in $save_oldobjs do func_basename "$obj" objbase="$func_basename_result" case " $oldobjs " in " ") oldobjs=$obj ;; *[\ /]"$objbase "*) while :; do # Make sure we don't pick an alternate name that also # overlaps. newobj=lt$counter-$objbase func_arith $counter + 1 counter=$func_arith_result case " $oldobjs " in *[\ /]"$newobj "*) ;; *) if test ! -f "$gentop/$newobj"; then break; fi ;; esac done func_show_eval "ln $obj $gentop/$newobj || cp $obj $gentop/$newobj" oldobjs="$oldobjs $gentop/$newobj" ;; *) oldobjs="$oldobjs $obj" ;; esac done fi eval cmds=\"$old_archive_cmds\" func_len " $cmds" len=$func_len_result if test "$len" -lt "$max_cmd_len" || test "$max_cmd_len" -le -1; then cmds=$old_archive_cmds else # the command line is too long to link in one step, link in parts func_verbose "using piecewise archive linking..." save_RANLIB=$RANLIB RANLIB=: objlist= concat_cmds= save_oldobjs=$oldobjs oldobjs= # Is there a better way of finding the last object in the list? for obj in $save_oldobjs do last_oldobj=$obj done eval test_cmds=\"$old_archive_cmds\" func_len " $test_cmds" len0=$func_len_result len=$len0 for obj in $save_oldobjs do func_len " $obj" func_arith $len + $func_len_result len=$func_arith_result func_append objlist " $obj" if test "$len" -lt "$max_cmd_len"; then : else # the above command should be used before it gets too long oldobjs=$objlist if test "$obj" = "$last_oldobj" ; then RANLIB=$save_RANLIB fi test -z "$concat_cmds" || concat_cmds=$concat_cmds~ eval concat_cmds=\"\${concat_cmds}$old_archive_cmds\" objlist= len=$len0 fi done RANLIB=$save_RANLIB oldobjs=$objlist if test "X$oldobjs" = "X" ; then eval cmds=\"\$concat_cmds\" else eval cmds=\"\$concat_cmds~\$old_archive_cmds\" fi fi fi func_execute_cmds "$cmds" 'exit $?' done test -n "$generated" && \ func_show_eval "${RM}r$generated" # Now create the libtool archive. case $output in *.la) old_library= test "$build_old_libs" = yes && old_library="$libname.$libext" func_verbose "creating $output" # Preserve any variables that may affect compiler behavior for var in $variables_saved_for_relink; do if eval test -z \"\${$var+set}\"; then relink_command="{ test -z \"\${$var+set}\" || $lt_unset $var || { $var=; export $var; }; }; $relink_command" elif eval var_value=\$$var; test -z "$var_value"; then relink_command="$var=; export $var; $relink_command" else func_quote_for_eval "$var_value" relink_command="$var=$func_quote_for_eval_result; export $var; $relink_command" fi done # Quote the link command for shipping. relink_command="(cd `pwd`; $SHELL $progpath $preserve_args --mode=relink $libtool_args @inst_prefix_dir@)" relink_command=`$ECHO "X$relink_command" | $Xsed -e "$sed_quote_subst"` if test "$hardcode_automatic" = yes ; then relink_command= fi # Only create the output if not a dry run. $opt_dry_run || { for installed in no yes; do if test "$installed" = yes; then if test -z "$install_libdir"; then break fi output="$output_objdir/$outputname"i # Replace all uninstalled libtool libraries with the installed ones newdependency_libs= for deplib in $dependency_libs; do case $deplib in *.la) func_basename "$deplib" name="$func_basename_result" eval libdir=`${SED} -n -e 's/^libdir=\(.*\)$/\1/p' $deplib` test -z "$libdir" && \ func_fatal_error "\`$deplib' is not a valid libtool archive" newdependency_libs="$newdependency_libs $libdir/$name" ;; *) newdependency_libs="$newdependency_libs $deplib" ;; esac done dependency_libs="$newdependency_libs" newdlfiles= for lib in $dlfiles; do case $lib in *.la) func_basename "$lib" name="$func_basename_result" eval libdir=`${SED} -n -e 's/^libdir=\(.*\)$/\1/p' $lib` test -z "$libdir" && \ func_fatal_error "\`$lib' is not a valid libtool archive" newdlfiles="$newdlfiles $libdir/$name" ;; *) newdlfiles="$newdlfiles $lib" ;; esac done dlfiles="$newdlfiles" newdlprefiles= for lib in $dlprefiles; do case $lib in *.la) # Only pass preopened files to the pseudo-archive (for # eventual linking with the app. that links it) if we # didn't already link the preopened objects directly into # the library: func_basename "$lib" name="$func_basename_result" eval libdir=`${SED} -n -e 's/^libdir=\(.*\)$/\1/p' $lib` test -z "$libdir" && \ func_fatal_error "\`$lib' is not a valid libtool archive" newdlprefiles="$newdlprefiles $libdir/$name" ;; esac done dlprefiles="$newdlprefiles" else newdlfiles= for lib in $dlfiles; do case $lib in [\\/]* | [A-Za-z]:[\\/]*) abs="$lib" ;; *) abs=`pwd`"/$lib" ;; esac newdlfiles="$newdlfiles $abs" done dlfiles="$newdlfiles" newdlprefiles= for lib in $dlprefiles; do case $lib in [\\/]* | [A-Za-z]:[\\/]*) abs="$lib" ;; *) abs=`pwd`"/$lib" ;; esac newdlprefiles="$newdlprefiles $abs" done dlprefiles="$newdlprefiles" fi $RM $output # place dlname in correct position for cygwin tdlname=$dlname case $host,$output,$installed,$module,$dlname in *cygwin*,*lai,yes,no,*.dll | *mingw*,*lai,yes,no,*.dll | *cegcc*,*lai,yes,no,*.dll) tdlname=../bin/$dlname ;; esac $ECHO > $output "\ # $outputname - a libtool library file # Generated by $PROGRAM (GNU $PACKAGE$TIMESTAMP) $VERSION # # Please DO NOT delete this file! # It is necessary for linking the library. # The name that we can dlopen(3). dlname='$tdlname' # Names of this library. library_names='$library_names' # The name of the static archive. old_library='$old_library' # Linker flags that can not go in dependency_libs. inherited_linker_flags='$new_inherited_linker_flags' # Libraries that this one depends upon. dependency_libs='$dependency_libs' # Names of additional weak libraries provided by this library weak_library_names='$weak_libs' # Version information for $libname. current=$current age=$age revision=$revision # Is this an already installed library? installed=$installed # Should we warn about portability when linking against -modules? shouldnotlink=$module # Files to dlopen/dlpreopen dlopen='$dlfiles' dlpreopen='$dlprefiles' # Directory that this library needs to be installed in: libdir='$install_libdir'" if test "$installed" = no && test "$need_relink" = yes; then $ECHO >> $output "\ relink_command=\"$relink_command\"" fi done } # Do a symbolic link so that the libtool archive can be found in # LD_LIBRARY_PATH before the program is installed. func_show_eval '( cd "$output_objdir" && $RM "$outputname" && $LN_S "../$outputname" "$outputname" )' 'exit $?' ;; esac exit $EXIT_SUCCESS } { test "$mode" = link || test "$mode" = relink; } && func_mode_link ${1+"$@"} # func_mode_uninstall arg... func_mode_uninstall () { $opt_debug RM="$nonopt" files= rmforce= exit_status=0 # This variable tells wrapper scripts just to set variables rather # than running their programs. libtool_install_magic="$magic" for arg do case $arg in -f) RM="$RM $arg"; rmforce=yes ;; -*) RM="$RM $arg" ;; *) files="$files $arg" ;; esac done test -z "$RM" && \ func_fatal_help "you must specify an RM program" rmdirs= origobjdir="$objdir" for file in $files; do func_dirname "$file" "" "." dir="$func_dirname_result" if test "X$dir" = X.; then objdir="$origobjdir" else objdir="$dir/$origobjdir" fi func_basename "$file" name="$func_basename_result" test "$mode" = uninstall && objdir="$dir" # Remember objdir for removal later, being careful to avoid duplicates if test "$mode" = clean; then case " $rmdirs " in *" $objdir "*) ;; *) rmdirs="$rmdirs $objdir" ;; esac fi # Don't error if the file doesn't exist and rm -f was used. if { test -L "$file"; } >/dev/null 2>&1 || { test -h "$file"; } >/dev/null 2>&1 || test -f "$file"; then : elif test -d "$file"; then exit_status=1 continue elif test "$rmforce" = yes; then continue fi rmfiles="$file" case $name in *.la) # Possibly a libtool archive, so verify it. if func_lalib_p "$file"; then func_source $dir/$name # Delete the libtool libraries and symlinks. for n in $library_names; do rmfiles="$rmfiles $objdir/$n" done test -n "$old_library" && rmfiles="$rmfiles $objdir/$old_library" case "$mode" in clean) case " $library_names " in # " " in the beginning catches empty $dlname *" $dlname "*) ;; *) rmfiles="$rmfiles $objdir/$dlname" ;; esac test -n "$libdir" && rmfiles="$rmfiles $objdir/$name $objdir/${name}i" ;; uninstall) if test -n "$library_names"; then # Do each command in the postuninstall commands. func_execute_cmds "$postuninstall_cmds" 'test "$rmforce" = yes || exit_status=1' fi if test -n "$old_library"; then # Do each command in the old_postuninstall commands. func_execute_cmds "$old_postuninstall_cmds" 'test "$rmforce" = yes || exit_status=1' fi # FIXME: should reinstall the best remaining shared library. ;; esac fi ;; *.lo) # Possibly a libtool object, so verify it. if func_lalib_p "$file"; then # Read the .lo file func_source $dir/$name # Add PIC object to the list of files to remove. if test -n "$pic_object" && test "$pic_object" != none; then rmfiles="$rmfiles $dir/$pic_object" fi # Add non-PIC object to the list of files to remove. if test -n "$non_pic_object" && test "$non_pic_object" != none; then rmfiles="$rmfiles $dir/$non_pic_object" fi fi ;; *) if test "$mode" = clean ; then noexename=$name case $file in *.exe) func_stripname '' '.exe' "$file" file=$func_stripname_result func_stripname '' '.exe' "$name" noexename=$func_stripname_result # $file with .exe has already been added to rmfiles, # add $file without .exe rmfiles="$rmfiles $file" ;; esac # Do a test to see if this is a libtool program. if func_ltwrapper_p "$file"; then if func_ltwrapper_executable_p "$file"; then func_ltwrapper_scriptname "$file" relink_command= func_source $func_ltwrapper_scriptname_result rmfiles="$rmfiles $func_ltwrapper_scriptname_result" else relink_command= func_source $dir/$noexename fi # note $name still contains .exe if it was in $file originally # as does the version of $file that was added into $rmfiles rmfiles="$rmfiles $objdir/$name $objdir/${name}S.${objext}" if test "$fast_install" = yes && test -n "$relink_command"; then rmfiles="$rmfiles $objdir/lt-$name" fi if test "X$noexename" != "X$name" ; then rmfiles="$rmfiles $objdir/lt-${noexename}.c" fi fi fi ;; esac func_show_eval "$RM $rmfiles" 'exit_status=1' done objdir="$origobjdir" # Try to remove the ${objdir}s in the directories where we deleted files for dir in $rmdirs; do if test -d "$dir"; then func_show_eval "rmdir $dir >/dev/null 2>&1" fi done exit $exit_status } { test "$mode" = uninstall || test "$mode" = clean; } && func_mode_uninstall ${1+"$@"} test -z "$mode" && { help="$generic_help" func_fatal_help "you must specify a MODE" } test -z "$exec_cmd" && \ func_fatal_help "invalid operation mode \`$mode'" if test -n "$exec_cmd"; then eval exec "$exec_cmd" exit $EXIT_FAILURE fi exit $exit_status # The TAGs below are defined such that we never get into a situation # in which we disable both kinds of libraries. Given conflicting # choices, we go for a static library, that is the most portable, # since we can't tell whether shared libraries were disabled because # the user asked for that or because the platform doesn't support # them. This is particularly important on AIX, because we don't # support having both static and shared libraries enabled at the same # time on that platform, so we default to a shared-only configuration. # If a disable-shared tag is given, we'll fallback to a static-only # configuration. But we'll never go from static-only to shared-only. # ### BEGIN LIBTOOL TAG CONFIG: disable-shared build_libtool_libs=no build_old_libs=yes # ### END LIBTOOL TAG CONFIG: disable-shared # ### BEGIN LIBTOOL TAG CONFIG: disable-static build_old_libs=`case $build_libtool_libs in yes) echo no;; *) echo yes;; esac` # ### END LIBTOOL TAG CONFIG: disable-static # Local Variables: # mode:shell-script # sh-indentation:2 # End: # vi:sw=2 gmerlin-1.2.0~dfsg/TODO0000644000175000017500000000000111764363414014561 0ustar alessioalessio gmerlin-1.2.0~dfsg/config.rpath0000755000175000017500000003744411764363414016426 0ustar alessioalessio#! /bin/sh # Output a system dependent set of variables, describing how to set the # run time search path of shared libraries in an executable. # # Copyright 1996-2006 Free Software Foundation, Inc. # Taken from GNU libtool, 2001 # Originally by Gordon Matzigkeit , 1996 # # This file is free software; the Free Software Foundation gives # unlimited permission to copy and/or distribute it, with or without # modifications, as long as this notice is preserved. # # The first argument passed to this file is the canonical host specification, # CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM # or # CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM # The environment variables CC, GCC, LDFLAGS, LD, with_gnu_ld # should be set by the caller. # # The set of defined variables is at the end of this script. # Known limitations: # - On IRIX 6.5 with CC="cc", the run time search patch must not be longer # than 256 bytes, otherwise the compiler driver will dump core. The only # known workaround is to choose shorter directory names for the build # directory and/or the installation directory. # All known linkers require a `.a' archive for static linking (except MSVC, # which needs '.lib'). libext=a shrext=.so host="$1" host_cpu=`echo "$host" | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\1/'` host_vendor=`echo "$host" | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\2/'` host_os=`echo "$host" | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\3/'` # Code taken from libtool.m4's _LT_CC_BASENAME. for cc_temp in $CC""; do case $cc_temp in compile | *[\\/]compile | ccache | *[\\/]ccache ) ;; distcc | *[\\/]distcc | purify | *[\\/]purify ) ;; \-*) ;; *) break;; esac done cc_basename=`echo "$cc_temp" | sed -e 's%^.*/%%'` # Code taken from libtool.m4's AC_LIBTOOL_PROG_COMPILER_PIC. wl= if test "$GCC" = yes; then wl='-Wl,' else case "$host_os" in aix*) wl='-Wl,' ;; darwin*) case $cc_basename in xlc*) wl='-Wl,' ;; esac ;; mingw* | pw32* | os2*) ;; hpux9* | hpux10* | hpux11*) wl='-Wl,' ;; irix5* | irix6* | nonstopux*) wl='-Wl,' ;; newsos6) ;; linux*) case $cc_basename in icc* | ecc*) wl='-Wl,' ;; pgcc | pgf77 | pgf90) wl='-Wl,' ;; ccc*) wl='-Wl,' ;; como) wl='-lopt=' ;; *) case `$CC -V 2>&1 | sed 5q` in *Sun\ C*) wl='-Wl,' ;; esac ;; esac ;; osf3* | osf4* | osf5*) wl='-Wl,' ;; sco3.2v5*) ;; solaris*) wl='-Wl,' ;; sunos4*) wl='-Qoption ld ' ;; sysv4 | sysv4.2uw2* | sysv4.3* | sysv5*) wl='-Wl,' ;; sysv4*MP*) ;; unicos*) wl='-Wl,' ;; uts4*) ;; esac fi # Code taken from libtool.m4's AC_LIBTOOL_PROG_LD_SHLIBS. hardcode_libdir_flag_spec= hardcode_libdir_separator= hardcode_direct=no hardcode_minus_L=no case "$host_os" in cygwin* | mingw* | pw32*) # FIXME: the MSVC++ port hasn't been tested in a loooong time # When not using gcc, we currently assume that we are using # Microsoft Visual C++. if test "$GCC" != yes; then with_gnu_ld=no fi ;; interix*) # we just hope/assume this is gcc and not c89 (= MSVC++) with_gnu_ld=yes ;; openbsd*) with_gnu_ld=no ;; esac ld_shlibs=yes if test "$with_gnu_ld" = yes; then # Set some defaults for GNU ld with shared library support. These # are reset later if shared libraries are not supported. Putting them # here allows them to be overridden if necessary. # Unlike libtool, we use -rpath here, not --rpath, since the documented # option of GNU ld is called -rpath, not --rpath. hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' case "$host_os" in aix3* | aix4* | aix5*) # On AIX/PPC, the GNU linker is very broken if test "$host_cpu" != ia64; then ld_shlibs=no fi ;; amigaos*) hardcode_libdir_flag_spec='-L$libdir' hardcode_minus_L=yes # Samuel A. Falvo II reports # that the semantics of dynamic libraries on AmigaOS, at least up # to version 4, is to share data among multiple programs linked # with the same dynamic library. Since this doesn't match the # behavior of shared libraries on other platforms, we cannot use # them. ld_shlibs=no ;; beos*) if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then : else ld_shlibs=no fi ;; cygwin* | mingw* | pw32*) # hardcode_libdir_flag_spec is actually meaningless, as there is # no search path for DLLs. hardcode_libdir_flag_spec='-L$libdir' if $LD --help 2>&1 | grep 'auto-import' > /dev/null; then : else ld_shlibs=no fi ;; interix3*) hardcode_direct=no hardcode_libdir_flag_spec='${wl}-rpath,$libdir' ;; linux*) if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then : else ld_shlibs=no fi ;; netbsd*) ;; solaris*) if $LD -v 2>&1 | grep 'BFD 2\.8' > /dev/null; then ld_shlibs=no elif $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then : else ld_shlibs=no fi ;; sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX*) case `$LD -v 2>&1` in *\ [01].* | *\ 2.[0-9].* | *\ 2.1[0-5].*) ld_shlibs=no ;; *) if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then hardcode_libdir_flag_spec='`test -z "$SCOABSPATH" && echo ${wl}-rpath,$libdir`' else ld_shlibs=no fi ;; esac ;; sunos4*) hardcode_direct=yes ;; *) if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then : else ld_shlibs=no fi ;; esac if test "$ld_shlibs" = no; then hardcode_libdir_flag_spec= fi else case "$host_os" in aix3*) # Note: this linker hardcodes the directories in LIBPATH if there # are no directories specified by -L. hardcode_minus_L=yes if test "$GCC" = yes; then # Neither direct hardcoding nor static linking is supported with a # broken collect2. hardcode_direct=unsupported fi ;; aix4* | aix5*) if test "$host_cpu" = ia64; then # On IA64, the linker does run time linking by default, so we don't # have to do anything special. aix_use_runtimelinking=no else aix_use_runtimelinking=no # Test if we are trying to use run time linking or normal # AIX style linking. If -brtl is somewhere in LDFLAGS, we # need to do runtime linking. case $host_os in aix4.[23]|aix4.[23].*|aix5*) for ld_flag in $LDFLAGS; do if (test $ld_flag = "-brtl" || test $ld_flag = "-Wl,-brtl"); then aix_use_runtimelinking=yes break fi done ;; esac fi hardcode_direct=yes hardcode_libdir_separator=':' if test "$GCC" = yes; then case $host_os in aix4.[012]|aix4.[012].*) collect2name=`${CC} -print-prog-name=collect2` if test -f "$collect2name" && \ strings "$collect2name" | grep resolve_lib_name >/dev/null then # We have reworked collect2 hardcode_direct=yes else # We have old collect2 hardcode_direct=unsupported hardcode_minus_L=yes hardcode_libdir_flag_spec='-L$libdir' hardcode_libdir_separator= fi ;; esac fi # Begin _LT_AC_SYS_LIBPATH_AIX. echo 'int main () { return 0; }' > conftest.c ${CC} ${LDFLAGS} conftest.c -o conftest aix_libpath=`dump -H conftest 2>/dev/null | sed -n -e '/Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/; p; } }'` if test -z "$aix_libpath"; then aix_libpath=`dump -HX64 conftest 2>/dev/null | sed -n -e '/Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/; p; } }'` fi if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib" fi rm -f conftest.c conftest # End _LT_AC_SYS_LIBPATH_AIX. if test "$aix_use_runtimelinking" = yes; then hardcode_libdir_flag_spec='${wl}-blibpath:$libdir:'"$aix_libpath" else if test "$host_cpu" = ia64; then hardcode_libdir_flag_spec='${wl}-R $libdir:/usr/lib:/lib' else hardcode_libdir_flag_spec='${wl}-blibpath:$libdir:'"$aix_libpath" fi fi ;; amigaos*) hardcode_libdir_flag_spec='-L$libdir' hardcode_minus_L=yes # see comment about different semantics on the GNU ld section ld_shlibs=no ;; bsdi[45]*) ;; cygwin* | mingw* | pw32*) # When not using gcc, we currently assume that we are using # Microsoft Visual C++. # hardcode_libdir_flag_spec is actually meaningless, as there is # no search path for DLLs. hardcode_libdir_flag_spec=' ' libext=lib ;; darwin* | rhapsody*) hardcode_direct=no if test "$GCC" = yes ; then : else case $cc_basename in xlc*) ;; *) ld_shlibs=no ;; esac fi ;; dgux*) hardcode_libdir_flag_spec='-L$libdir' ;; freebsd1*) ld_shlibs=no ;; freebsd2.2*) hardcode_libdir_flag_spec='-R$libdir' hardcode_direct=yes ;; freebsd2*) hardcode_direct=yes hardcode_minus_L=yes ;; freebsd* | kfreebsd*-gnu | dragonfly*) hardcode_libdir_flag_spec='-R$libdir' hardcode_direct=yes ;; hpux9*) hardcode_libdir_flag_spec='${wl}+b ${wl}$libdir' hardcode_libdir_separator=: hardcode_direct=yes # hardcode_minus_L: Not really in the search PATH, # but as the default location of the library. hardcode_minus_L=yes ;; hpux10*) if test "$with_gnu_ld" = no; then hardcode_libdir_flag_spec='${wl}+b ${wl}$libdir' hardcode_libdir_separator=: hardcode_direct=yes # hardcode_minus_L: Not really in the search PATH, # but as the default location of the library. hardcode_minus_L=yes fi ;; hpux11*) if test "$with_gnu_ld" = no; then hardcode_libdir_flag_spec='${wl}+b ${wl}$libdir' hardcode_libdir_separator=: case $host_cpu in hppa*64*|ia64*) hardcode_direct=no ;; *) hardcode_direct=yes # hardcode_minus_L: Not really in the search PATH, # but as the default location of the library. hardcode_minus_L=yes ;; esac fi ;; irix5* | irix6* | nonstopux*) hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' hardcode_libdir_separator=: ;; netbsd*) hardcode_libdir_flag_spec='-R$libdir' hardcode_direct=yes ;; newsos6) hardcode_direct=yes hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' hardcode_libdir_separator=: ;; openbsd*) hardcode_direct=yes if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then hardcode_libdir_flag_spec='${wl}-rpath,$libdir' else case "$host_os" in openbsd[01].* | openbsd2.[0-7] | openbsd2.[0-7].*) hardcode_libdir_flag_spec='-R$libdir' ;; *) hardcode_libdir_flag_spec='${wl}-rpath,$libdir' ;; esac fi ;; os2*) hardcode_libdir_flag_spec='-L$libdir' hardcode_minus_L=yes ;; osf3*) hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' hardcode_libdir_separator=: ;; osf4* | osf5*) if test "$GCC" = yes; then hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' else # Both cc and cxx compiler support -rpath directly hardcode_libdir_flag_spec='-rpath $libdir' fi hardcode_libdir_separator=: ;; solaris*) hardcode_libdir_flag_spec='-R$libdir' ;; sunos4*) hardcode_libdir_flag_spec='-L$libdir' hardcode_direct=yes hardcode_minus_L=yes ;; sysv4) case $host_vendor in sni) hardcode_direct=yes # is this really true??? ;; siemens) hardcode_direct=no ;; motorola) hardcode_direct=no #Motorola manual says yes, but my tests say they lie ;; esac ;; sysv4.3*) ;; sysv4*MP*) if test -d /usr/nec; then ld_shlibs=yes fi ;; sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[01].[10]* | unixware7*) ;; sysv5* | sco3.2v5* | sco5v6*) hardcode_libdir_flag_spec='`test -z "$SCOABSPATH" && echo ${wl}-R,$libdir`' hardcode_libdir_separator=':' ;; uts4*) hardcode_libdir_flag_spec='-L$libdir' ;; *) ld_shlibs=no ;; esac fi # Check dynamic linker characteristics # Code taken from libtool.m4's AC_LIBTOOL_SYS_DYNAMIC_LINKER. libname_spec='lib$name' case "$host_os" in aix3*) ;; aix4* | aix5*) ;; amigaos*) ;; beos*) ;; bsdi[45]*) ;; cygwin* | mingw* | pw32*) shrext=.dll ;; darwin* | rhapsody*) shrext=.dylib ;; dgux*) ;; freebsd1*) ;; kfreebsd*-gnu) ;; freebsd* | dragonfly*) ;; gnu*) ;; hpux9* | hpux10* | hpux11*) case $host_cpu in ia64*) shrext=.so ;; hppa*64*) shrext=.sl ;; *) shrext=.sl ;; esac ;; interix3*) ;; irix5* | irix6* | nonstopux*) case "$host_os" in irix5* | nonstopux*) libsuff= shlibsuff= ;; *) case $LD in *-32|*"-32 "|*-melf32bsmip|*"-melf32bsmip ") libsuff= shlibsuff= ;; *-n32|*"-n32 "|*-melf32bmipn32|*"-melf32bmipn32 ") libsuff=32 shlibsuff=N32 ;; *-64|*"-64 "|*-melf64bmip|*"-melf64bmip ") libsuff=64 shlibsuff=64 ;; *) libsuff= shlibsuff= ;; esac ;; esac ;; linux*oldld* | linux*aout* | linux*coff*) ;; linux*) ;; knetbsd*-gnu) ;; netbsd*) ;; newsos6) ;; nto-qnx*) ;; openbsd*) ;; os2*) libname_spec='$name' shrext=.dll ;; osf3* | osf4* | osf5*) ;; solaris*) ;; sunos4*) ;; sysv4 | sysv4.3*) ;; sysv4*MP*) ;; sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*) ;; uts4*) ;; esac sed_quote_subst='s/\(["`$\\]\)/\\\1/g' escaped_wl=`echo "X$wl" | sed -e 's/^X//' -e "$sed_quote_subst"` shlibext=`echo "$shrext" | sed -e 's,^\.,,'` escaped_hardcode_libdir_flag_spec=`echo "X$hardcode_libdir_flag_spec" | sed -e 's/^X//' -e "$sed_quote_subst"` LC_ALL=C sed -e 's/^\([a-zA-Z0-9_]*\)=/acl_cv_\1=/' <&2 exit 1;; esac shift;; -o) chowncmd="$chownprog $2" shift;; -s) stripcmd=$stripprog;; -t) dst_arg=$2 shift;; -T) no_target_directory=true;; --version) echo "$0 $scriptversion"; exit $?;; --) shift break;; -*) echo "$0: invalid option: $1" >&2 exit 1;; *) break;; esac shift done if test $# -ne 0 && test -z "$dir_arg$dst_arg"; then # When -d is used, all remaining arguments are directories to create. # When -t is used, the destination is already specified. # Otherwise, the last argument is the destination. Remove it from $@. for arg do if test -n "$dst_arg"; then # $@ is not empty: it contains at least $arg. set fnord "$@" "$dst_arg" shift # fnord fi shift # arg dst_arg=$arg done fi if test $# -eq 0; then if test -z "$dir_arg"; then echo "$0: no input file specified." >&2 exit 1 fi # It's OK to call `install-sh -d' without argument. # This can happen when creating conditional directories. exit 0 fi if test -z "$dir_arg"; then trap '(exit $?); exit' 1 2 13 15 # Set umask so as not to create temps with too-generous modes. # However, 'strip' requires both read and write access to temps. case $mode in # Optimize common cases. *644) cp_umask=133;; *755) cp_umask=22;; *[0-7]) if test -z "$stripcmd"; then u_plus_rw= else u_plus_rw='% 200' fi cp_umask=`expr '(' 777 - $mode % 1000 ')' $u_plus_rw`;; *) if test -z "$stripcmd"; then u_plus_rw= else u_plus_rw=,u+rw fi cp_umask=$mode$u_plus_rw;; esac fi for src do # Protect names starting with `-'. case $src in -*) src=./$src;; esac if test -n "$dir_arg"; then dst=$src dstdir=$dst test -d "$dstdir" dstdir_status=$? else # Waiting for this to be detected by the "$cpprog $src $dsttmp" command # might cause directories to be created, which would be especially bad # if $src (and thus $dsttmp) contains '*'. if test ! -f "$src" && test ! -d "$src"; then echo "$0: $src does not exist." >&2 exit 1 fi if test -z "$dst_arg"; then echo "$0: no destination specified." >&2 exit 1 fi dst=$dst_arg # Protect names starting with `-'. case $dst in -*) dst=./$dst;; esac # If destination is a directory, append the input filename; won't work # if double slashes aren't ignored. if test -d "$dst"; then if test -n "$no_target_directory"; then echo "$0: $dst_arg: Is a directory" >&2 exit 1 fi dstdir=$dst dst=$dstdir/`basename "$src"` dstdir_status=0 else # Prefer dirname, but fall back on a substitute if dirname fails. dstdir=` (dirname "$dst") 2>/dev/null || expr X"$dst" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$dst" : 'X\(//\)[^/]' \| \ X"$dst" : 'X\(//\)$' \| \ X"$dst" : 'X\(/\)' \| . 2>/dev/null || echo X"$dst" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q' ` test -d "$dstdir" dstdir_status=$? fi fi obsolete_mkdir_used=false if test $dstdir_status != 0; then case $posix_mkdir in '') # Create intermediate dirs using mode 755 as modified by the umask. # This is like FreeBSD 'install' as of 1997-10-28. umask=`umask` case $stripcmd.$umask in # Optimize common cases. *[2367][2367]) mkdir_umask=$umask;; .*0[02][02] | .[02][02] | .[02]) mkdir_umask=22;; *[0-7]) mkdir_umask=`expr $umask + 22 \ - $umask % 100 % 40 + $umask % 20 \ - $umask % 10 % 4 + $umask % 2 `;; *) mkdir_umask=$umask,go-w;; esac # With -d, create the new directory with the user-specified mode. # Otherwise, rely on $mkdir_umask. if test -n "$dir_arg"; then mkdir_mode=-m$mode else mkdir_mode= fi posix_mkdir=false case $umask in *[123567][0-7][0-7]) # POSIX mkdir -p sets u+wx bits regardless of umask, which # is incompatible with FreeBSD 'install' when (umask & 300) != 0. ;; *) tmpdir=${TMPDIR-/tmp}/ins$RANDOM-$$ trap 'ret=$?; rmdir "$tmpdir/d" "$tmpdir" 2>/dev/null; exit $ret' 0 if (umask $mkdir_umask && exec $mkdirprog $mkdir_mode -p -- "$tmpdir/d") >/dev/null 2>&1 then if test -z "$dir_arg" || { # Check for POSIX incompatibilities with -m. # HP-UX 11.23 and IRIX 6.5 mkdir -m -p sets group- or # other-writeable bit of parent directory when it shouldn't. # FreeBSD 6.1 mkdir -m -p sets mode of existing directory. ls_ld_tmpdir=`ls -ld "$tmpdir"` case $ls_ld_tmpdir in d????-?r-*) different_mode=700;; d????-?--*) different_mode=755;; *) false;; esac && $mkdirprog -m$different_mode -p -- "$tmpdir" && { ls_ld_tmpdir_1=`ls -ld "$tmpdir"` test "$ls_ld_tmpdir" = "$ls_ld_tmpdir_1" } } then posix_mkdir=: fi rmdir "$tmpdir/d" "$tmpdir" else # Remove any dirs left behind by ancient mkdir implementations. rmdir ./$mkdir_mode ./-p ./-- 2>/dev/null fi trap '' 0;; esac;; esac if $posix_mkdir && ( umask $mkdir_umask && $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir" ) then : else # The umask is ridiculous, or mkdir does not conform to POSIX, # or it failed possibly due to a race condition. Create the # directory the slow way, step by step, checking for races as we go. case $dstdir in /*) prefix='/';; -*) prefix='./';; *) prefix='';; esac eval "$initialize_posix_glob" oIFS=$IFS IFS=/ $posix_glob set -f set fnord $dstdir shift $posix_glob set +f IFS=$oIFS prefixes= for d do test -z "$d" && continue prefix=$prefix$d if test -d "$prefix"; then prefixes= else if $posix_mkdir; then (umask=$mkdir_umask && $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir") && break # Don't fail if two instances are running concurrently. test -d "$prefix" || exit 1 else case $prefix in *\'*) qprefix=`echo "$prefix" | sed "s/'/'\\\\\\\\''/g"`;; *) qprefix=$prefix;; esac prefixes="$prefixes '$qprefix'" fi fi prefix=$prefix/ done if test -n "$prefixes"; then # Don't fail if two instances are running concurrently. (umask $mkdir_umask && eval "\$doit_exec \$mkdirprog $prefixes") || test -d "$dstdir" || exit 1 obsolete_mkdir_used=true fi fi fi if test -n "$dir_arg"; then { test -z "$chowncmd" || $doit $chowncmd "$dst"; } && { test -z "$chgrpcmd" || $doit $chgrpcmd "$dst"; } && { test "$obsolete_mkdir_used$chowncmd$chgrpcmd" = false || test -z "$chmodcmd" || $doit $chmodcmd $mode "$dst"; } || exit 1 else # Make a couple of temp file names in the proper directory. dsttmp=$dstdir/_inst.$$_ rmtmp=$dstdir/_rm.$$_ # Trap to clean up those temp files at exit. trap 'ret=$?; rm -f "$dsttmp" "$rmtmp" && exit $ret' 0 # Copy the file name to the temp name. (umask $cp_umask && $doit_exec $cpprog "$src" "$dsttmp") && # and set any options; do chmod last to preserve setuid bits. # # If any of these fail, we abort the whole thing. If we want to # ignore errors from any of these, just make sure not to ignore # errors from the above "$doit $cpprog $src $dsttmp" command. # { test -z "$chowncmd" || $doit $chowncmd "$dsttmp"; } && { test -z "$chgrpcmd" || $doit $chgrpcmd "$dsttmp"; } && { test -z "$stripcmd" || $doit $stripcmd "$dsttmp"; } && { test -z "$chmodcmd" || $doit $chmodcmd $mode "$dsttmp"; } && # If -C, don't bother to copy if it wouldn't change the file. if $copy_on_change && old=`LC_ALL=C ls -dlL "$dst" 2>/dev/null` && new=`LC_ALL=C ls -dlL "$dsttmp" 2>/dev/null` && eval "$initialize_posix_glob" && $posix_glob set -f && set X $old && old=:$2:$4:$5:$6 && set X $new && new=:$2:$4:$5:$6 && $posix_glob set +f && test "$old" = "$new" && $cmpprog "$dst" "$dsttmp" >/dev/null 2>&1 then rm -f "$dsttmp" else # Rename the file to the real destination. $doit $mvcmd -f "$dsttmp" "$dst" 2>/dev/null || # The rename failed, perhaps because mv can't rename something else # to itself, or perhaps because mv is so ancient that it does not # support -f. { # Now remove or move aside any old file at destination location. # We try this two ways since rm can't unlink itself on some # systems and the destination file might be busy for other # reasons. In this case, the final cleanup might fail but the new # file should still install successfully. { test ! -f "$dst" || $doit $rmcmd -f "$dst" 2>/dev/null || { $doit $mvcmd -f "$dst" "$rmtmp" 2>/dev/null && { $doit $rmcmd -f "$rmtmp" 2>/dev/null; :; } } || { echo "$0: cannot unlink or rename $dst" >&2 (exit 1); exit 1 } } && # Now rename the file to the real destination. $doit $mvcmd "$dsttmp" "$dst" } fi || exit 1 trap '' 0 fi done # Local variables: # eval: (add-hook 'write-file-hooks 'time-stamp) # time-stamp-start: "scriptversion=" # time-stamp-format: "%:y-%02m-%02d.%02H" # time-stamp-time-zone: "UTC" # time-stamp-end: "; # UTC" # End: gmerlin-1.2.0~dfsg/cpuinfo.sh0000755000175000017500000001725111764363414016112 0ustar alessioalessio#!/bin/sh if test x"$CC" = x; then CC=gcc fi if test $# -ne 1; then echo "Please give the arch (ppc or x86) as an argument!" 1>&2 exit 1 fi if test `uname -s` = Darwin; then IsDarwin=yes else IsDarwin=no fi target=$1 cc_version=`$CC -dumpversion` _cc_major=`echo $cc_version | cut -d'.' -f1` _cc_minor=`echo $cc_version | cut -d'.' -f2` if test $_cc_major -ge 4; then _opt_mcpu="-mtune" elif test $_cc_major -ge 3 -a $_cc_minor -ge 4; then _opt_mcpu="-mtune" else _opt_mcpu="-mcpu" fi do_cc() { $CC -o conftest conftest.c $@ >/dev/null 2>&1 } extcheck() { cat > conftest.c < void catch() { exit(1); } int main(void){ signal(SIGILL, catch); __asm__ __volatile__ ("$1":::"memory"); exit(0); } EOF do_cc if test -x ./conftest; then ./conftest if test $? -ne 0; then return 1 fi return 0 else return 1 fi } do_x86() { CFLAGS=-O if test $IsDarwin = yes; then CFLAGS="$CFLAGS -fno-pic -Wl,-read_only_relocs -Wl,suppress" fi if test -r /proc/cpuinfo; then _cpuinfo="cat /proc/cpuinfo" else $CC $CFLAGS -o cpuinfo utils/cpuinfo.c _cpuinfo="./cpuinfo" fi # Cpu determination logic adapted from the MPlayer configure script. pname=`$_cpuinfo | grep 'model name' | cut -d ':' -f 2 | head -n 1` pvendor=`$_cpuinfo | grep 'vendor_id' | cut -d':' -f2 | cut -d' ' -f2 | head -n 1` pfamily=`$_cpuinfo | grep 'cpu family' | cut -d':' -f2 | cut -d' ' -f2 | head -n 1` pmodel=`$_cpuinfo | grep -v 'model name' | grep 'model' | cut -d':' -f2 | cut -d' ' -f2 | head -n 1` pstep=`$_cpuinfo | grep 'stepping' | cut -d':' -f2 | cut -d' ' -f2 | head -n 1` pparam=`$_cpuinfo | grep 'features' | cut -d':' -f2 | head -n 1` if test -z "$pparam" ; then pparam=`$_cpuinfo | grep 'flags' | cut -d ':' -f 2 | head -n 1` fi _mmx=no _3dnow=no _3dnowex=no _mmx2=no _sse=no _sse2=no _mtrr=no for i in $pparam ; do case "$i" in 3dnow) _3dnow=yes ;; 3dnowext) _3dnow=yes _3dnowex=yes ;; mmx) _mmx=yes ;; mmxext) _mmx2=yes ;; mtrr|k6_mtrr|cyrix_arr) _mtrr=yes ;; xmm|sse|kni) _sse=yes _mmx2=yes ;; sse2) _sse2=yes ;; esac done case "$pvendor" in AuthenticAMD) case "$pfamily" in 3)proc=i386 ;; 4) proc=i486 ;; 5) iproc=586 # models are: K5/SSA5 K5 K5 K5 ? ? K6 K6 K6-2 K6-3 # K6 model 13 are the K6-2+ and K6-III+ if test "$pmodel" -eq 9 -o "$pmodel" -eq 13; then proc=k6-3 elif test "$pmodel" -ge 8; then proc=k6-2 elif test "$pmodel" -ge 6; then proc=k6 else proc=i586 fi ;; 6) iproc=686 if test "$pmodel" -ge 7; then proc=athlon-4 elif test "$pmodel" -ge 6; then if test "$_sse" = yes && test "$pstep" -ge 2; then proc=athlon-xp else proc=athlon-4 fi elif test "$pmodel" -ge 4; then proc=athlon-tbird else proc=athlon fi ;; 15) # Despite what the gcc into says 'athlon64' is not accepted as # synonym for 'k8' proc=k8 ;; *) proc=athlon-xp ;; esac ;; GenuineIntel) case "$pfamily" in 3) proc=i386 ;; 4) proc=i486 ;; 5) iproc=586 if test "$pmodel" -eq 4 || test "$pmodel" -eq 8; then proc=pentium-mmx # 4 is desktop, 8 is mobile else proc=i586 fi ;; 6) iproc=686 if test "$pmodel" -ge 15; then proc=nocona elif test "$pmodel" -ge 13; then proc=pentium-m elif test "$pmodel" -ge 7; then proc=pentium3 elif test "$pmodel" -ge 3; then proc=pentium2 else proc=i686 fi ;; 15) proc=pentium4 ;; *) proc=pentium4 ;; esac ;; unknown) case "$pfamily" in 3) proc=i386 ;; 4) proc=i486 ;; *) proc=i586 ;; esac ;; *) proc=i586 ;; esac # check that gcc supports our CPU, if not, fall back to earlier ones cat > conftest.c << EOF int main(void) { return 0; } EOF if test "$proc" = "athlon64" ; then do_cc -march=$proc $_opt_mcpu=$proc || proc=athlon-xp fi if test "$proc" = "athlon-xp" || test "$proc" = "athlon-4" || test "$proc" = "athlon-tbird"; then do_cc -march=$proc $_opt_mcpu=$proc || proc=athlon fi if test "$proc" = "k6-3" || test "$proc" = "k6-2"; then do_cc -march=$proc $_opt_mcpu=$proc || proc=k6 fi if test "$proc" = "k6"; then do_cc -march=$proc $_opt_mcpu=$proc if test $? -ne 0; then if do_cc -march=i586 $_opt_mcpu=i686; then proc=i586-i686 else proc=i586 fi fi fi if test "$proc" = "pentium4" || test "$proc" = "pentium3" || test "$proc" = "pentium2" || test "$proc" = "athlon"; then do_cc -march=$proc $_opt_mcpu=$proc || proc=i686 fi if test "$proc" = "i686" || test "$proc" = "pentium-mmx"; then do_cc -march=$proc $_opt_mcpu=$proc || proc=i586 fi if test "$proc" = "i586" ; then do_cc -march=$proc $_opt_mcpu=$proc || proc=i486 fi if test "$proc" = "i486" ; then do_cc -march=$proc $_opt_mcpu=$proc || proc=i386 fi if test "$proc" = "i386" ; then do_cc -march=$proc $_opt_mcpu=$proc || proc=error fi if test "$proc" = "error" ; then echo "Your $_cc does not even support \"i386\" for '-march' and $_opt_mcpu." _mcpu="" _march="" elif test "$proc" = "i586-i686"; then _march="-march=i586" _mcpu="$_opt_mcpu=i686" else _march="-march=$proc" _mcpu="$_opt_mcpu=$proc" fi if test $_cc_major -ge 3; then extcheck "xorps %%xmm0, %%xmm0" || _gcc3_ext="$_gcc3_ext -mno-sse" extcheck "xorpd %%xmm0, %%xmm0" || _gcc3_ext="$_gcc3_ext -mno-sse2" if test x"$_gcc3_ext" != "x"; then # if we had to disable sse/sse2 because the active kernel does not # support this instruction set extension, we also have to tell # gcc3 to not generate sse/sse2 instructions for normal C code cat > conftest.c << EOF int main(void) { return 0; } EOF do_cc $_march $_gcc3_ext && _march="$_march $_gcc3_ext" fi fi echo $_march $_mcpu rm -f conftest.c conftest cpuinfo return 0 } do_ppc() { # Linux on a PPC has /proc/info # Darwin (OS/X) has the hostinfo command # If neither of those we have no idea what to do - so do nothing. if test -r /proc/cpuinfo; then proc=`grep cpu /proc/cpuinfo | cut -d':' -f2 | cut -d',' -f1 | cut -b 2- | head -n 1` elif test $IsDarwin = yes; then proc=`hostinfo | grep "Processor type" | cut -f3 -d' ' | sed 's/ppc//'` else return 0 fi case "$proc" in 601) _march="$_opt_mcpu=601" _mcpu='-mtune=601' ;; 603) _march="$_opt_mcpu=603" _mcpu='-mtune=603' ;; 603e|603ev) _march="$_opt_mcpu=603e" _mcpu='-mtune=603e' ;; 604|604e|604r|604ev) _march="$_opt_mcpu=604" _mcpu='-mtune=604' ;; 740|740/750|745/755) _march="$_opt_mcpu=740" _mcpu='-mtune=740' ;; 750|750CX) _march="$_opt_mcpu=750" _mcpu='-mtune=750' ;; *) ;; esac # gcc 3.1(.1) and up supports 7400 and 7450 if test "$_cc_major" -ge "3" && test "$_cc_minor" -ge "1" || test "$_cc_major" -ge "4"; then case "$proc" in 7400*|7410*) _march="$_opt_mcpu=7400" _mcpu='-mtune=7400' ;; 7450*|7455*) _march="$_opt_mcpu=7450" _mcpu='-mtune=7450' ;; *) ;; esac fi # gcc 3.2 and up supports 970 if test "$_cc_major" -ge "3" && test "$_cc_minor" -ge "3" || test "$_cc_major" -ge "4"; then case "$proc" in 970*) if test $IsDarwin = yes; then _march="$_opt_mcpu=G5 -mpowerpc64 -mpowerpc-gpopt -falign-loops=16" _mcpu='-mtune=G5' else _march="$_opt_mcpu=970" _mcpu='-mtune=970' fi ;; *) ;; esac fi echo $_march $_mcpu return 0 } # # The script that runs the various functions above # if test $target = x86; then do_x86 elif test $target = ppc; then do_ppc fi gmerlin-1.2.0~dfsg/gmerlin-gtk.pc.in0000644000175000017500000000037611764363414017261 0ustar alessioalessioprefix=@prefix@ exec_prefix=@exec_prefix@ libdir=@libdir@ includedir=@includedir@ Name: Gmerlin-gtk Description: Gmerlin Gtk support library Version: @VERSION@ Requires.private: gmerlin gtk+-2.0 Libs: -L${libdir} -lgmerlin_gtk Cflags: -I${includedir} gmerlin-1.2.0~dfsg/apps/0000755000175000017500000000000011764363443015047 5ustar alessioalessiogmerlin-1.2.0~dfsg/apps/Makefile.am0000644000175000017500000000200611764363403017075 0ustar alessioalessio if HAVE_PLAYER player_subdirs = player else player_subdirs = endif if HAVE_PLUGINCFG plugincfg_subdirs = plugincfg else plugincfg_subdirs = endif if HAVE_ALSAMIXER alsamixer_subdirs = alsamixer else alsamixer_subdirs = endif #if HAVE_CAMELOT #camelot_subdirs = camelot #else #camelot_subdirs = #endif if HAVE_TRANSCODER transcoder_subdirs = transcoder else transcoder_subdirs = endif if HAVE_RECORDER recorder_subdirs = recorder else recorder_subdirs = endif if HAVE_KBD kbd_subdirs = kbd else kbd_subdirs = endif if HAVE_VISUALIZER visualizer_subdirs = visualizer else visualizer_subdirs = endif if HAVE_THUMBNAILER thumbnailer_subdirs = thumbnailer else thumbnailer_subdirs = endif if HAVE_NMJEDIT nmjedit_subdirs = nmjedit else nmjedit_subdirs = endif SUBDIRS = $(player_subdirs) \ cmdlineplayer \ cmdlinerecorder \ $(plugincfg_subdirs) \ $(alsamixer_subdirs) \ $(nmjedit_subdirs) \ $(camelot_subdirs) \ $(recorder_subdirs) \ $(transcoder_subdirs) \ $(thumbnailer_subdirs) \ $(kbd_subdirs) \ $(visualizer_subdirs) gmerlin-1.2.0~dfsg/apps/player/0000755000175000017500000000000011764363443016343 5ustar alessioalessiogmerlin-1.2.0~dfsg/apps/player/gmerlin.10000644000175000017500000000173611764363403020065 0ustar alessioalessio.TH GMERLIN 1 "March 2012" Gmerlin "User Manuals" .SH NAME gmerlin .SH SYNOPSIS .B gmerlin .I [options] .I [gmls .I ...] .SH DESCRIPTION Gmerlin GUI Player .SH GENERIC OPTIONS The following generic options are available for all gmerlin applications .B -help .RS 2 Print this help message and exit .RE .B -help-man .RS 2 Print this help message as a manual page and exit .RE .B -help-texi .RS 2 Print this help message in texinfo format and exit .RE .B -version .RS 2 Print version info and exit .RE .SH ENVIRONMENT VARIABLES .B GMERLIN_PLAYER_REMOTE_PORT .RS 2 Default port for the remote control .RE .SH FILES .B ~/.gmerlin/plugins.xml .RS 2 Cache of the plugin registry (shared by all applicatons) .RE .P .B ~/.gmerlin/player/config.xml .RS 2 Used for configuration data. Delete this file if you think you goofed something up. .RE .P .B ~/.gmerlin/player/tree/tree.xml .RS 2 Media tree is saved here. The albums are saved as separate files in the same directory. .RE .P gmerlin-1.2.0~dfsg/apps/player/Makefile.am0000644000175000017500000000157411764363403020402 0ustar alessioalessioplugindir=$(pkglibdir)/plugins INCLUDES = -I$(top_srcdir)/include AM_CFLAGS = \ @XML2_CFLAGS@ \ @GTK_CFLAGS@ \ -DLOCALE_DIR=\"$(localedir)\" \ -DPLUGIN_DIR=\"$(plugindir)\" \ -DDOC_DIR=\"$(docdir)\" \ -DDATA_DIR=\"$(pkgdatadir)\" Desktopdir = $(datadir)/applications Desktop_DATA = gmerlin-player.desktop bin_PROGRAMS = gmerlin gmerlin_remote dist_man_MANS = gmerlin.1 gmerlin_remote.1 bin_SCRIPTS = gmerlin_launcher gmerlin_SOURCES = \ cfgdialog.c \ display.c \ gmerlin.c \ main.c \ mainmenu.c \ playerwindow.c \ remote.c \ skin.c \ skinbrowser.c gmerlin_remote_SOURCES = \ gmerlin_remote.c noinst_HEADERS = \ display.h \ gmerlin.h \ player_remote.h \ playerwindow.h gmerlin_LDADD = $(top_builddir)/lib/libgmerlin.la $(top_builddir)/lib/gtk/libgmerlin_gtk.la @XML2_LIBS@ gmerlin_remote_LDADD = $(top_builddir)/lib/libgmerlin.la EXTRA_DIST = gmerlin_launcher gmerlin-player.desktop gmerlin-1.2.0~dfsg/apps/player/main.c0000644000175000017500000000633211764363403017433 0ustar alessioalessio/***************************************************************** * gmerlin - a general purpose multimedia framework and applications * * Copyright (c) 2001 - 2011 Members of the Gmerlin project * gmerlin-general@lists.sourceforge.net * http://gmerlin.sourceforge.net * * 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 of the License, 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 this program. If not, see . * *****************************************************************/ /* System includes */ #include #include #include /* Gmerlin includes */ #include #include #include "gmerlin.h" #include "player_remote.h" #include #include #include // #define MTRACE #ifdef MTRACE #include #endif const bg_cmdline_app_data_t app_data = { .package = PACKAGE, .version = VERSION, .name = "gmerlin", .synopsis = TRS("[options] [gmls ...]\n"), .help_before = TRS("Gmerlin GUI Player"), .args = (bg_cmdline_arg_array_t[]) { { } }, .env = (bg_cmdline_ext_doc_t[]) { { PLAYER_REMOTE_ENV, TRS("Default port for the remote control") }, { /* End */ } }, .files = (bg_cmdline_ext_doc_t[]) { { "~/.gmerlin/plugins.xml", TRS("Cache of the plugin registry (shared by all applicatons)") }, { "~/.gmerlin/player/config.xml", TRS("Used for configuration data. Delete this file if you think you goofed something up.") }, { "~/.gmerlin/player/tree/tree.xml", TRS("Media tree is saved here. The albums are saved as separate files in the same directory.") }, { /* End */ } }, }; int main(int argc, char ** argv) { gmerlin_t * gmerlin; bg_cfg_registry_t * cfg_reg; char * tmp_path; char ** locations; #ifdef MTRACE mtrace(); #endif /* Initialize random generator (for shuffle) */ srand(time(NULL)); bg_translation_init(); bg_gtk_init(&argc, &argv, WINDOW_ICON, WINDOW_NAME, WINDOW_CLASS); cfg_reg = bg_cfg_registry_create(); tmp_path = bg_search_file_read("player", "config.xml"); bg_cfg_registry_load(cfg_reg, tmp_path); if(tmp_path) free(tmp_path); /* Fire up the actual player */ gmerlin = gmerlin_create(cfg_reg); /* Get locations from the commandline */ bg_cmdline_init(&app_data); bg_cmdline_parse(NULL, &argc, &argv, NULL); locations = bg_cmdline_get_locations_from_args(&argc, &argv); gmerlin_run(gmerlin, locations); gmerlin_destroy(gmerlin); tmp_path = bg_search_file_write("player", "config.xml"); bg_cfg_registry_save(cfg_reg, tmp_path); if(tmp_path) free(tmp_path); bg_cfg_registry_destroy(cfg_reg); return 0; } gmerlin-1.2.0~dfsg/apps/player/remote.c0000644000175000017500000001101011764363403017767 0ustar alessioalessio/***************************************************************** * gmerlin - a general purpose multimedia framework and applications * * Copyright (c) 2001 - 2011 Members of the Gmerlin project * gmerlin-general@lists.sourceforge.net * http://gmerlin.sourceforge.net * * 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 of the License, 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 this program. If not, see . * *****************************************************************/ #include "gmerlin.h" #include "player_remote.h" void gmerlin_handle_remote(gmerlin_t * g, bg_msg_t * msg) { int id; gavl_time_t arg_time; char * arg_str; // gavl_time_t arg_time; float arg_f; char * locations[2]; int arg_i; id = bg_msg_get_id(msg); switch(id) { case PLAYER_COMMAND_PLAY: gmerlin_play(g, BG_PLAY_FLAG_IGNORE_IF_PLAYING | BG_PLAY_FLAG_RESUME); break; case PLAYER_COMMAND_STOP: bg_player_stop(g->player); break; case PLAYER_COMMAND_NEXT: bg_media_tree_next(g->tree, 1, g->shuffle_mode); gmerlin_play(g, BG_PLAY_FLAG_IGNORE_IF_STOPPED); break; case PLAYER_COMMAND_PREV: bg_media_tree_previous(g->tree, 1, g->shuffle_mode); gmerlin_play(g, BG_PLAY_FLAG_IGNORE_IF_STOPPED); break; case PLAYER_COMMAND_PAUSE: gmerlin_pause(g); break; case PLAYER_COMMAND_ADD_LOCATION: arg_str = bg_msg_get_arg_string(msg, 0); locations[0] = arg_str; locations[1] = NULL; gmerlin_add_locations(g, locations); free(arg_str); break; case PLAYER_COMMAND_PLAY_LOCATION: arg_str = bg_msg_get_arg_string(msg, 0); locations[0] = arg_str; locations[1] = NULL; gmerlin_play_locations(g, locations); free(arg_str); break; case PLAYER_COMMAND_OPEN_DEVICE: arg_str = bg_msg_get_arg_string(msg, 0); gmerlin_open_device(g, arg_str); free(arg_str); break; case PLAYER_COMMAND_PLAY_DEVICE: arg_str = bg_msg_get_arg_string(msg, 0); gmerlin_play_device(g, arg_str); free(arg_str); break; /* Volume control (arg: Volume in dB) */ case PLAYER_COMMAND_SET_VOLUME: arg_f = bg_msg_get_arg_float(msg, 0); bg_player_set_volume(g->player, arg_f); break; case PLAYER_COMMAND_SET_VOLUME_REL: arg_f = bg_msg_get_arg_float(msg, 0); bg_player_set_volume_rel(g->player, arg_f); break; /* Seek */ case PLAYER_COMMAND_SEEK: break; case PLAYER_COMMAND_SEEK_REL: arg_time = bg_msg_get_arg_time(msg, 0); bg_player_seek_rel(g->player, arg_time); break; /* Mute */ case PLAYER_COMMAND_TOGGLE_MUTE: bg_player_toggle_mute(g->player); break; /* Chapters */ case PLAYER_COMMAND_SET_CHAPTER: arg_i = bg_msg_get_arg_int(msg, 0); bg_player_set_chapter(g->player, arg_i); break; case PLAYER_COMMAND_NEXT_CHAPTER: bg_player_next_chapter(g->player); break; case PLAYER_COMMAND_PREV_CHAPTER: bg_player_prev_chapter(g->player); break; case PLAYER_COMMAND_GET_NAME: msg = bg_remote_server_get_msg_write(g->remote); bg_msg_set_id(msg, PLAYER_RESPONSE_GET_NAME); /* Set name */ bg_msg_set_arg_string(msg, 0, g->remote_data.name); bg_remote_server_done_msg_write(g->remote); break; case PLAYER_COMMAND_GET_METADATA: msg = bg_remote_server_get_msg_write(g->remote); bg_msg_set_id(msg, PLAYER_RESPONSE_GET_METADATA); /* Set Metadata */ bg_msg_set_arg_metadata(msg, 0, &g->remote_data.metadata); bg_remote_server_done_msg_write(g->remote); break; case PLAYER_COMMAND_GET_TIME: msg = bg_remote_server_get_msg_write(g->remote); bg_msg_set_id(msg, PLAYER_RESPONSE_GET_TIME); /* Set Time */ bg_msg_set_arg_time(msg, 0, g->remote_data.time); bg_msg_set_arg_time(msg, 1, g->remote_data.duration); bg_remote_server_done_msg_write(g->remote); break; } } gmerlin-1.2.0~dfsg/apps/player/skin.c0000644000175000017500000000471611764363403017457 0ustar alessioalessio/***************************************************************** * gmerlin - a general purpose multimedia framework and applications * * Copyright (c) 2001 - 2011 Members of the Gmerlin project * gmerlin-general@lists.sourceforge.net * http://gmerlin.sourceforge.net * * 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 of the License, 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 this program. If not, see . * *****************************************************************/ #include #include #include #include "gmerlin.h" #include #include static const char * default_skin_directory = DATA_DIR"/skins/Default"; char * gmerlin_skin_load(gmerlin_skin_t * s, char * directory) { xmlNodePtr node; xmlNodePtr child; char * filename = NULL; xmlDocPtr doc = NULL; filename = bg_sprintf("%s/skin.xml", directory); doc = xmlParseFile(filename); if(!doc) { free(filename); directory = bg_strdup(directory, default_skin_directory); filename = bg_sprintf("%s/skin.xml", directory); doc = xmlParseFile(filename); } if(!doc) { goto fail; } s->directory = bg_strdup(s->directory, directory); node = doc->children; if(BG_XML_STRCMP(node->name, "SKIN")) { goto fail; } node = node->children; while(node) { if(!node->name) { node = node->next; continue; } child = node->children; /* Main window */ if(!BG_XML_STRCMP(node->name, "PLAYERWIN")) player_window_skin_load(&s->playerwindow, doc, node); node = node->next; } fail: if(doc) xmlFreeDoc(doc); if(filename) free(filename); return directory; } void gmerlin_skin_set(gmerlin_t * g) { player_window_set_skin(g->player_window, &g->skin.playerwindow, g->skin.directory); } void gmerlin_skin_free(gmerlin_skin_t * s) { } gmerlin-1.2.0~dfsg/apps/player/gmerlin.h0000644000175000017500000001432411764363403020151 0ustar alessioalessio/***************************************************************** * gmerlin - a general purpose multimedia framework and applications * * Copyright (c) 2001 - 2011 Members of the Gmerlin project * gmerlin-general@lists.sourceforge.net * http://gmerlin.sourceforge.net * * 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 of the License, 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 this program. If not, see . * *****************************************************************/ #include #include #include #include #include #include #include #include #include #include #include typedef struct gmerlin_s gmerlin_t; #include "display.h" #include "playerwindow.h" /* Class hints */ #define WINDOW_NAME "Gmerlin" #define WINDOW_CLASS "gmerlin" #define WINDOW_ICON "player_icon.png" /* Repeat mode */ typedef enum { REPEAT_MODE_NONE = 0, REPEAT_MODE_1 = 1, REPEAT_MODE_ALL = 2, NUM_REPEAT_MODES = 3, } repeat_mode_t; /* Accelerators */ #define ACCEL_VOLUME_DOWN 1 #define ACCEL_VOLUME_UP 2 #define ACCEL_SEEK_BACKWARD 3 #define ACCEL_SEEK_FORWARD 4 #define ACCEL_SEEK_START 5 #define ACCEL_PAUSE 6 #define ACCEL_MUTE 7 #define ACCEL_NEXT_CHAPTER 8 #define ACCEL_PREV_CHAPTER 9 #define ACCEL_NEXT 10 #define ACCEL_PREV 11 #define ACCEL_QUIT 12 #define ACCEL_OPTIONS 13 #define ACCEL_GOTO_CURRENT 15 #define ACCEL_CURRENT_TO_FAVOURITES 16 typedef struct { char * directory; player_window_skin_t playerwindow; } gmerlin_skin_t; void gmerlin_skin_destroy(gmerlin_skin_t * s); typedef struct gmerlin_skin_browser_s gmerlin_skin_browser_t; #define PLAYBACK_SKIP_ERROR (1<<0) #define PLAYBACK_NOADVANCE (1<<1) struct gmerlin_s { int playback_flags; repeat_mode_t repeat_mode; bg_shuffle_mode_t shuffle_mode; /* Core stuff */ bg_cfg_registry_t * cfg_reg; bg_plugin_registry_t * plugin_reg; bg_player_t * player; bg_media_tree_t * tree; /* GUI */ bg_dialog_t * cfg_dialog; bg_dialog_t * audio_dialog; bg_dialog_t * audio_filter_dialog; bg_dialog_t * video_dialog; bg_dialog_t * video_filter_dialog; bg_dialog_t * subtitle_dialog; bg_dialog_t * visualization_dialog; bg_gtk_tree_window_t * tree_window; player_window_t * player_window; bg_gtk_info_window_t * info_window; bg_gtk_log_window_t * log_window; gmerlin_skin_t skin; char * skin_dir; gmerlin_skin_browser_t * skin_browser; int tree_error; /* Configuration stuff */ bg_cfg_section_t * display_section; bg_cfg_section_t * tree_section; bg_cfg_section_t * general_section; bg_cfg_section_t * audio_section; bg_cfg_section_t * audio_filter_section; bg_cfg_section_t * video_section; bg_cfg_section_t * video_filter_section; bg_cfg_section_t * subtitle_section; bg_cfg_section_t * osd_section; bg_cfg_section_t * input_section; bg_cfg_section_t * lcdproc_section; bg_cfg_section_t * remote_section; bg_cfg_section_t * logwindow_section; bg_cfg_section_t * infowindow_section; bg_cfg_section_t * visualization_section; bg_parameter_info_t * input_plugin_parameters; bg_parameter_info_t * image_reader_parameters; int show_info_window; int show_log_window; int show_tree_window; bg_lcdproc_t * lcdproc; /* Remote control */ bg_remote_server_t * remote; int player_state; /* For all windows */ GtkAccelGroup *accel_group; /* The following can be queried remotely */ struct { gavl_metadata_t metadata; char * name; gavl_time_t time; gavl_time_t duration; } remote_data; }; gmerlin_t * gmerlin_create(bg_cfg_registry_t * cfg_reg); /* Right after creating, urls can be added */ void gmerlin_add_locations(gmerlin_t * g, char ** locations); void gmerlin_play_locations(gmerlin_t * g, char ** locations); void gmerlin_open_device(gmerlin_t * g, char * device); void gmerlin_play_device(gmerlin_t * g, char * device); void gmerlin_destroy(gmerlin_t*); void gmerlin_run(gmerlin_t*, char ** locations); /* Skin stuff */ /* Load a skin from directory. Return the default dierectory if the skin could not be found */ char * gmerlin_skin_load(gmerlin_skin_t *, char * directory); void gmerlin_skin_set(gmerlin_t*); void gmerlin_skin_free(gmerlin_skin_t*); /* Skin browser */ gmerlin_skin_browser_t * gmerlin_skin_browser_create(gmerlin_t *); void gmerlin_skin_browser_destroy(gmerlin_skin_browser_t *); void gmerlin_skin_browser_show(gmerlin_skin_browser_t *); /* Run the main config dialog */ void gmerlin_create_dialog(gmerlin_t * g); void gmerlin_configure(gmerlin_t * g); int gmerlin_play(gmerlin_t * g, int ignore_flags); void gmerlin_pause(gmerlin_t * g); /* This is called when the player signals that it wants a new track */ void gmerlin_next_track(gmerlin_t * g); /* Check if the next track in the tree has the index specified by track */ void gmerlin_check_next_track(gmerlin_t * g, int track); void gmerlin_tree_close_callback(bg_gtk_tree_window_t * win, void * data); const bg_parameter_info_t * gmerlin_get_parameters(gmerlin_t * g); void gmerlin_set_parameter(void * data, const char * name, const bg_parameter_value_t * val); int gmerlin_get_parameter(void * data, const char * name, bg_parameter_value_t * val); /* Handle remote command */ void gmerlin_handle_remote(gmerlin_t * g, bg_msg_t * msg); gmerlin-1.2.0~dfsg/apps/player/display.h0000644000175000017500000000501411764363403020155 0ustar alessioalessio/***************************************************************** * gmerlin - a general purpose multimedia framework and applications * * Copyright (c) 2001 - 2011 Members of the Gmerlin project * gmerlin-general@lists.sourceforge.net * http://gmerlin.sourceforge.net * * 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 of the License, 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 this program. If not, see . * *****************************************************************/ #include #include #define DISPLAY_WIDTH 232 #define DISPLAY_HEIGHT 59 typedef struct display_s display_t; typedef struct display_skin_s { int x, y; float background[3]; float foreground_normal[3]; float foreground_error[3]; } display_skin_t; display_t * display_create(gmerlin_t * gmerlin); const bg_parameter_info_t * display_get_parameters(display_t * display); void display_set_parameter(void * data, const char * name, const bg_parameter_value_t * v); int display_get_parameter(void * data, const char * name, bg_parameter_value_t * v); void display_destroy(display_t *); void display_set_playlist_times(display_t *, gavl_time_t duration_before, gavl_time_t duration_current, gavl_time_t duration_after); void display_set_time(display_t *, gavl_time_t time); void display_set_mute(display_t *, int mute); GtkWidget * display_get_widget(display_t *); void display_get_coords(display_t *, int * x, int * y); /* Set state to something defined in playermsg.h */ void display_set_state(display_t *, int state, const void * arg); /* Set track name to be displayed */ void display_set_track_name(display_t * d, char * name); void display_set_error_msg(display_t * d, char * msg); void display_set_skin(display_t * d, display_skin_t * s); void display_skin_load(display_skin_t * s, xmlDocPtr doc, xmlNodePtr node); gmerlin-1.2.0~dfsg/apps/player/playerwindow.h0000644000175000017500000001167611764363403021247 0ustar alessioalessio/***************************************************************** * gmerlin - a general purpose multimedia framework and applications * * Copyright (c) 2001 - 2011 Members of the Gmerlin project * gmerlin-general@lists.sourceforge.net * http://gmerlin.sourceforge.net * * 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 of the License, 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 this program. If not, see . * *****************************************************************/ #include #include #include typedef struct { char * background; char * background_highlight; bg_gtk_button_skin_t play_button; bg_gtk_button_skin_t pause_button; bg_gtk_button_skin_t prev_button; bg_gtk_button_skin_t next_button; bg_gtk_button_skin_t stop_button; bg_gtk_button_skin_t menu_button; bg_gtk_button_skin_t close_button; bg_gtk_slider_skin_t seek_slider; bg_gtk_slider_skin_t volume_slider; display_skin_t display; } player_window_skin_t; void player_window_skin_load(player_window_skin_t *, xmlDocPtr doc, xmlNodePtr node); void player_window_skin_destroy(player_window_skin_t *); /* Player window */ typedef struct main_menu_s main_menu_t; main_menu_t * main_menu_create(gmerlin_t * gmerlin); /* Set the plugins and send everything to the player */ void main_menu_finalize(main_menu_t * ret, gmerlin_t * gmerlin); void main_menu_destroy(main_menu_t *); GtkWidget * main_menu_get_widget(main_menu_t *); void main_menu_set_num_chapters(main_menu_t * m, int num, int scale); void main_menu_set_num_streams(main_menu_t *, int audio_streams, int video_streams, int subtitle_streams); void main_menu_set_chapter_info(main_menu_t * m, int chapter, const char * name, gavl_time_t time); void main_menu_chapter_changed(main_menu_t * m, int chapter); void main_menu_set_audio_info(main_menu_t *, int stream, const gavl_metadata_t * m); void main_menu_set_video_info(main_menu_t *, int stream, const gavl_metadata_t * m); void main_menu_set_subtitle_info(main_menu_t *, int stream, const gavl_metadata_t * m); void main_menu_update_streams(main_menu_t *, int num_audio_streams, int num_video_streams, int num_subpicture_streams, int num_programs); void main_menu_set_audio_index(main_menu_t *, int); void main_menu_set_video_index(main_menu_t *, int); void main_menu_set_subtitle_index(main_menu_t *, int); void main_menu_set_tree_window_item(main_menu_t * m, int state); void main_menu_set_info_window_item(main_menu_t * m, int state); void main_menu_set_log_window_item(main_menu_t * m, int state); void main_menu_set_plugin_window_item(main_menu_t * m, int state); typedef struct player_window_s { bg_msg_queue_t * cmd_queue; bg_msg_queue_t * msg_queue; gmerlin_t * gmerlin; /* Window stuff */ GtkWidget * window; GtkWidget * layout; /* For moving the window */ int mouse_x; int mouse_y; int window_x; int window_y; /* Background */ GdkPixbuf * background_pixbuf; GdkPixbuf * background_pixbuf_highlight; int mouse_inside; /* GUI Elements */ bg_gtk_button_t * play_button; bg_gtk_button_t * stop_button; bg_gtk_button_t * pause_button; bg_gtk_button_t * next_button; bg_gtk_button_t * prev_button; bg_gtk_button_t * close_button; bg_gtk_button_t * menu_button; bg_gtk_slider_t * seek_slider; bg_gtk_slider_t * volume_slider; main_menu_t * main_menu; display_t * display; gavl_time_t duration; int seek_active; float volume; int msg_queue_locked; /* For the player window only (NOT for album windows) */ GtkAccelGroup *accel_group; /* For avoiding infinite recursions */ guint enter_notify_id; guint leave_notify_id; } player_window_t; void player_window_create(gmerlin_t*); void player_window_push_accel(player_window_t * w, int accel); void player_window_show(player_window_t * win); void player_window_set_skin(player_window_t * win, player_window_skin_t*, const char * directory); void player_window_destroy(player_window_t * win); gmerlin-1.2.0~dfsg/apps/player/gmerlin_remote.10000644000175000017500000000375211764363403021440 0ustar alessioalessio.TH GMERLIN_REMOTE 1 "March 2012" Gmerlin "User Manuals" .SH NAME gmerlin_remote .SH SYNOPSIS .B gmerlin_remote .I [options] .I command .SH DESCRIPTION Remote control command for the Gmerlin GUI Player .SH GLOBAL OPTIONS .B -host .I .RS 2 Host to connect to, default is localhost .RE .B -port .I .RS 2 Port to connect to .RE .B -launch .RS 2 Launch new player if necessary .RE .SH COMMANDS .B -play .RS 2 Play current track .RE .B -next .RS 2 Switch to next track .RE .B -prev .RS 2 Switch to previous track .RE .B -stop .RS 2 Stop playback .RE .B -pause .RS 2 Pause playback .RE .B -mute .RS 2 Toggle mute .RE .B -add .I .RS 2 Add to the incoming album .RE .B -addplay .I .RS 2 Add to the incoming album and play it .RE .B -open .I .RS 2 Open album for . Device must be a GML (e.g. dvd:///dev/hdd). .RE .B -openplay .I .RS 2 Open album for and play first track. Device must be a GML (e.g. dvd:///dev/hdd). .RE .B -volume .I .RS 2 Set player volume. is in dB, 0.0 is max .RE .B -volume-rel .I .RS 2 In- or decrease player volume. is in dB .RE .B -seek-rel .I .RS 2 Seek relative. is in seconds. .RE .B -chapter .I [num|+|-] .RS 2 Go to the specified chapter. Use '+' and '-' to go to the next or previous chapter respectively .RE .B -get-name .RS 2 Print name of the current track .RE .B -get-metadata .RS 2 Print metadata of the current track .RE .B -get-time .RS 2 Print time of the current track .RE .SH GENERIC OPTIONS The following generic options are available for all gmerlin applications .B -help .RS 2 Print this help message and exit .RE .B -help-man .RS 2 Print this help message as a manual page and exit .RE .B -help-texi .RS 2 Print this help message in texinfo format and exit .RE .B -version .RS 2 Print version info and exit .RE .SH ENVIRONMENT VARIABLES .B GMERLIN_PLAYER_REMOTE_PORT .RS 2 Default port for the remote control .RE gmerlin-1.2.0~dfsg/apps/player/gmerlin_remote.c0000644000175000017500000003661011764363403021521 0ustar alessioalessio/***************************************************************** * gmerlin - a general purpose multimedia framework and applications * * Copyright (c) 2001 - 2011 Members of the Gmerlin project * gmerlin-general@lists.sourceforge.net * http://gmerlin.sourceforge.net * * 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 of the License, 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 this program. If not, see . * *****************************************************************/ #include #include #include #include #include #include #include #include "player_remote.h" #include #define LOG_DOMAIN "gmerlin_remote" static void cmd_get_name(void * data, int * argc, char *** _argv, int arg) { bg_msg_t * msg; bg_remote_client_t * remote; char * str; remote = (bg_remote_client_t *)data; msg = bg_remote_client_get_msg_write(remote); bg_msg_set_id(msg, PLAYER_COMMAND_GET_NAME); bg_remote_client_done_msg_write(remote); msg = bg_remote_client_get_msg_read(remote); if(!msg) return; str = bg_msg_get_arg_string(msg, 0); if(str) { printf("Name: %s\n", str); free(str); } } static void cmd_get_metadata(void * data, int * argc, char *** _argv, int arg) { char * str; gavl_metadata_t m; bg_msg_t * msg; bg_remote_client_t * remote; remote = (bg_remote_client_t *)data; msg = bg_remote_client_get_msg_write(remote); bg_msg_set_id(msg, PLAYER_COMMAND_GET_METADATA); bg_remote_client_done_msg_write(remote); msg = bg_remote_client_get_msg_read(remote); if(!msg) return; memset(&m, 0, sizeof(m)); bg_msg_get_arg_metadata(msg, 0, &m); str = bg_metadata_to_string(&m, 0); if(str) { printf("%s\n", str); free(str); } gavl_metadata_free(&m); } static void cmd_get_time(void * data, int * argc, char *** _argv, int arg) { gavl_time_t time; gavl_time_t duration; bg_msg_t * msg; bg_remote_client_t * remote; char str[GAVL_TIME_STRING_LEN]; remote = (bg_remote_client_t *)data; msg = bg_remote_client_get_msg_write(remote); bg_msg_set_id(msg, PLAYER_COMMAND_GET_TIME); bg_remote_client_done_msg_write(remote); msg = bg_remote_client_get_msg_read(remote); if(!msg) return; time = bg_msg_get_arg_time(msg, 0); duration = bg_msg_get_arg_time(msg, 1); gavl_time_prettyprint(time, str); printf("Time: %s\n", str); gavl_time_prettyprint(duration, str); printf("Duration: %s\n", str); } static void cmd_play(void * data, int * argc, char *** _argv, int arg) { bg_msg_t * msg; bg_remote_client_t * remote; remote = (bg_remote_client_t *)data; msg = bg_remote_client_get_msg_write(remote); bg_msg_set_id(msg, PLAYER_COMMAND_PLAY); bg_remote_client_done_msg_write(remote); } static void cmd_next(void * data, int * argc, char *** _argv, int arg) { bg_msg_t * msg; bg_remote_client_t * remote; remote = (bg_remote_client_t *)data; msg = bg_remote_client_get_msg_write(remote); bg_msg_set_id(msg, PLAYER_COMMAND_NEXT); bg_remote_client_done_msg_write(remote); } static void cmd_prev(void * data, int * argc, char *** _argv, int arg) { bg_msg_t * msg; bg_remote_client_t * remote; remote = (bg_remote_client_t *)data; msg = bg_remote_client_get_msg_write(remote); bg_msg_set_id(msg, PLAYER_COMMAND_PREV); bg_remote_client_done_msg_write(remote); } static void cmd_stop(void * data, int * argc, char *** _argv, int arg) { bg_msg_t * msg; bg_remote_client_t * remote; remote = (bg_remote_client_t *)data; msg = bg_remote_client_get_msg_write(remote); bg_msg_set_id(msg, PLAYER_COMMAND_STOP); bg_remote_client_done_msg_write(remote); } static void cmd_toggle_mute(void * data, int * argc, char *** _argv, int arg) { bg_msg_t * msg; bg_remote_client_t * remote; remote = (bg_remote_client_t *)data; msg = bg_remote_client_get_msg_write(remote); bg_msg_set_id(msg, PLAYER_COMMAND_TOGGLE_MUTE); bg_remote_client_done_msg_write(remote); } static void cmd_pause(void * data, int * argc, char *** _argv, int arg) { bg_msg_t * msg; bg_remote_client_t * remote; remote = (bg_remote_client_t *)data; msg = bg_remote_client_get_msg_write(remote); bg_msg_set_id(msg, PLAYER_COMMAND_PAUSE); bg_remote_client_done_msg_write(remote); } static void cmd_addplay(void * data, int * argc, char *** _argv, int arg) { bg_msg_t * msg; bg_remote_client_t * remote; char ** argv = *_argv; remote = (bg_remote_client_t *)data; if(arg >= *argc) { bg_log(BG_LOG_ERROR, LOG_DOMAIN, "Option -addplay requires an argument\n"); exit(-1); } msg = bg_remote_client_get_msg_write(remote); bg_msg_set_id(msg, PLAYER_COMMAND_PLAY_LOCATION); bg_msg_set_arg_string(msg, 0, argv[arg]); bg_cmdline_remove_arg(argc, _argv, arg); bg_remote_client_done_msg_write(remote); } static void cmd_add(void * data, int * argc, char *** _argv, int arg) { bg_msg_t * msg; bg_remote_client_t * remote; char ** argv = *_argv; remote = (bg_remote_client_t *)data; if(arg >= *argc) { bg_log(BG_LOG_ERROR, LOG_DOMAIN, "Option -add requires an argument\n"); exit(-1); } msg = bg_remote_client_get_msg_write(remote); bg_msg_set_id(msg, PLAYER_COMMAND_ADD_LOCATION); bg_msg_set_arg_string(msg, 0, argv[arg]); bg_cmdline_remove_arg(argc, _argv, arg); bg_remote_client_done_msg_write(remote); } static void cmd_openplay(void * data, int * argc, char *** _argv, int arg) { bg_msg_t * msg; bg_remote_client_t * remote; char ** argv = *_argv; remote = (bg_remote_client_t *)data; if(arg >= *argc) { bg_log(BG_LOG_ERROR, LOG_DOMAIN, "Option -openplay requires an argument\n"); exit(-1); } msg = bg_remote_client_get_msg_write(remote); bg_msg_set_id(msg, PLAYER_COMMAND_PLAY_DEVICE); bg_msg_set_arg_string(msg, 0, argv[arg]); bg_cmdline_remove_arg(argc, _argv, arg); bg_remote_client_done_msg_write(remote); } static void cmd_open(void * data, int * argc, char *** _argv, int arg) { bg_msg_t * msg; bg_remote_client_t * remote; char ** argv = *_argv; remote = (bg_remote_client_t *)data; if(arg >= *argc) { bg_log(BG_LOG_ERROR, LOG_DOMAIN, "Option -open requires an argument\n"); exit(-1); } msg = bg_remote_client_get_msg_write(remote); bg_msg_set_id(msg, PLAYER_COMMAND_OPEN_DEVICE); bg_msg_set_arg_string(msg, 0, argv[arg]); bg_cmdline_remove_arg(argc, _argv, arg); bg_remote_client_done_msg_write(remote); } static void cmd_volume(void * data, int * argc, char *** _argv, int arg) { bg_msg_t * msg; bg_remote_client_t * remote; char ** argv = *_argv; float vol; remote = (bg_remote_client_t *)data; if(arg >= *argc) { bg_log(BG_LOG_ERROR, LOG_DOMAIN, "Option -volume requires an argument\n"); exit(-1); } vol = strtod(argv[arg], NULL); msg = bg_remote_client_get_msg_write(remote); bg_msg_set_id(msg, PLAYER_COMMAND_SET_VOLUME); bg_msg_set_arg_float(msg, 0, vol); bg_remote_client_done_msg_write(remote); } static void cmd_volume_rel(void * data, int * argc, char *** _argv, int arg) { bg_msg_t * msg; bg_remote_client_t * remote; char ** argv = *_argv; float vol; remote = (bg_remote_client_t *)data; if(arg >= *argc) { bg_log(BG_LOG_ERROR, LOG_DOMAIN, "Option -volume_rel requires an argument\n"); exit(-1); } vol = strtod(argv[arg], NULL); msg = bg_remote_client_get_msg_write(remote); bg_msg_set_id(msg, PLAYER_COMMAND_SET_VOLUME_REL); bg_msg_set_arg_float(msg, 0, vol); bg_remote_client_done_msg_write(remote); } static void cmd_seek_rel(void * data, int * argc, char *** _argv, int arg) { bg_msg_t * msg; bg_remote_client_t * remote; char ** argv = *_argv; float diff; remote = (bg_remote_client_t *)data; if(arg >= *argc) { bg_log(BG_LOG_ERROR, LOG_DOMAIN, "Option -seek_rel requires an argument\n"); exit(-1); } diff = strtod(argv[arg], NULL); msg = bg_remote_client_get_msg_write(remote); bg_msg_set_id(msg, PLAYER_COMMAND_SEEK_REL); bg_msg_set_arg_time(msg, 0, gavl_seconds_to_time(diff)); bg_remote_client_done_msg_write(remote); } static void cmd_chapter(void * data, int * argc, char *** _argv, int arg) { bg_msg_t * msg; bg_remote_client_t * remote; char ** argv = *_argv; int index; remote = (bg_remote_client_t *)data; if(arg >= *argc) { bg_log(BG_LOG_ERROR, LOG_DOMAIN, "Option -chapter requires an argument\n"); exit(-1); } msg = bg_remote_client_get_msg_write(remote); if(!strcmp(argv[arg], "+")) bg_msg_set_id(msg, PLAYER_COMMAND_NEXT_CHAPTER); else if(!strcmp(argv[arg], "-")) bg_msg_set_id(msg, PLAYER_COMMAND_PREV_CHAPTER); else { index = atoi(argv[arg]); bg_msg_set_id(msg, PLAYER_COMMAND_SET_CHAPTER); bg_msg_set_arg_int(msg, 0, index); } bg_remote_client_done_msg_write(remote); } bg_cmdline_arg_t commands[] = { { .arg = "-play", .help_string = TRS("Play current track"), .callback = cmd_play, }, { .arg = "-next", .help_string = TRS("Switch to next track"), .callback = cmd_next, }, { .arg = "-prev", .help_string = TRS("Switch to previous track"), .callback = cmd_prev, }, { .arg = "-stop", .help_string = TRS("Stop playback"), .callback = cmd_stop, }, { .arg = "-pause", .help_string = TRS("Pause playback"), .callback = cmd_pause, }, { .arg = "-mute", .help_string = TRS("Toggle mute"), .callback = cmd_toggle_mute, }, { .arg = "-add", .help_arg = TRS(""), .help_string = TRS("Add to the incoming album"), .callback = cmd_add, }, { .arg = "-addplay", .help_arg = TRS(""), .help_string = TRS("Add to the incoming album and play it"), .callback = cmd_addplay, }, { .arg = "-open", .help_arg = TRS(""), .help_string = TRS("Open album for . Device must be a GML (e.g. dvd:///dev/hdd)."), .callback = cmd_open, }, { .arg = "-openplay", .help_arg = TRS(""), .help_string = TRS("Open album for and play first track. Device must be a GML (e.g. dvd:///dev/hdd)."), .callback = cmd_openplay, }, { .arg = "-volume", .help_arg = TRS(""), .help_string = TRS("Set player volume. is in dB, 0.0 is max"), .callback = cmd_volume, }, { .arg = "-volume-rel", .help_arg = TRS(""), .help_string = TRS("In- or decrease player volume. is in dB"), .callback = cmd_volume_rel, }, { .arg = "-seek-rel", .help_arg = TRS(""), .help_string = TRS("Seek relative. is in seconds."), .callback = cmd_seek_rel, }, { .arg = "-chapter", .help_arg = "[num|+|-]", .help_string = TRS("Go to the specified chapter. Use '+' and '-' to go to the next or previous chapter respectively"), .callback = cmd_chapter, }, { .arg = "-get-name", .help_string = TRS("Print name of the current track"), .callback = cmd_get_name, }, { .arg = "-get-metadata", .help_string = TRS("Print metadata of the current track"), .callback = cmd_get_metadata, }, { .arg = "-get-time", .help_string = TRS("Print time of the current track"), .callback = cmd_get_time, }, { /* End of options */ } }; char * host = NULL; int port; int launch = 0; static void opt_host(void * data, int * argc, char *** argv, int arg) { if(arg >= *argc) { bg_log(BG_LOG_ERROR, LOG_DOMAIN, "Option -host requires an argument"); exit(-1); } host = bg_strdup(host, (*argv)[arg]); bg_cmdline_remove_arg(argc, argv, arg); } static void opt_port(void * data, int * argc, char *** argv, int arg) { if(arg >= *argc) { bg_log(BG_LOG_ERROR, LOG_DOMAIN, "Option -port requires an argument"); exit(-1); } port = atoi((*argv)[arg]); bg_cmdline_remove_arg(argc, argv, arg); } static void opt_launch(void * data, int * argc, char *** argv, int arg) { launch = 1; } static bg_cmdline_arg_t global_options[] = { { .arg = "-host", .help_arg = "", .help_string = TRS("Host to connect to, default is localhost"), .callback = opt_host, }, { .arg = "-port", .help_arg = "", .help_string = TRS("Port to connect to"), .callback = opt_port, }, { .arg = "-launch", .help_string = TRS("Launch new player if necessary"), .callback = opt_launch, }, { /* End of options */ } }; #if 0 static void opt_help(void * data, int * argc, char *** argv, int arg) { FILE * out = stderr; fprintf(out, "Usage: %s [options] command\n\n", (*argv)[0]); fprintf(out, "Options:\n\n"); bg_cmdline_print_help(global_options); fprintf(out, "\ncommand is of the following:\n\n"); bg_cmdline_print_help(commands); exit(0); } #endif const bg_cmdline_app_data_t app_data = { .package = PACKAGE, .version = VERSION, .name = "gmerlin_remote", .synopsis = TRS("[options] command\n"), .help_before = TRS("Remote control command for the Gmerlin GUI Player\n"), .args = (bg_cmdline_arg_array_t[]) { { TRS("Global options"), global_options }, { TRS("Commands"), commands }, { } }, .env = (bg_cmdline_ext_doc_t[]) { { PLAYER_REMOTE_ENV, TRS("Default port for the remote control") }, { /* End */ } }, }; int main(int argc, char ** argv) { char * env; int i; gavl_time_t delay_time = GAVL_TIME_SCALE / 50; bg_remote_client_t * remote; bg_cmdline_init(&app_data); if(argc < 2) bg_cmdline_print_help(argv[0], 0); port = PLAYER_REMOTE_PORT; env = getenv(PLAYER_REMOTE_ENV); if(env) port = atoi(env); bg_cmdline_init(&app_data); bg_cmdline_parse(global_options, &argc, &argv, NULL); remote = bg_remote_client_create(PLAYER_REMOTE_ID, 0); if(!host) host = bg_strdup(host, "localhost"); if(!bg_remote_client_init(remote, host, port, 1000)) { if(launch) { if(system("gmerlin &")) { bg_log(BG_LOG_ERROR, LOG_DOMAIN, "Cannot launch gmerlin process"); return -1; } for(i = 0; i < 50; i++) { if(bg_remote_client_init(remote, host, port, 1000)) break; gavl_time_delay(&delay_time); } } else return -1; } bg_cmdline_parse(commands, &argc, &argv, remote); bg_remote_client_destroy(remote); return 0; } gmerlin-1.2.0~dfsg/apps/player/gmerlin_launcher0000755000175000017500000000005711764363403021605 0ustar alessioalessio#!/bin/sh gmerlin_remote -launch -addplay "$1" gmerlin-1.2.0~dfsg/apps/player/gmerlin.c0000644000175000017500000007166411764363403020156 0ustar alessioalessio/***************************************************************** * gmerlin - a general purpose multimedia framework and applications * * Copyright (c) 2001 - 2011 Members of the Gmerlin project * gmerlin-general@lists.sourceforge.net * http://gmerlin.sourceforge.net * * 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 of the License, 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 this program. If not, see . * *****************************************************************/ #include #include #include #include #include #include #include "gmerlin.h" #include "player_remote.h" #include #include #include static bg_accelerator_t accels[] = { { BG_KEY_LEFT, BG_KEY_SHIFT_MASK, ACCEL_VOLUME_DOWN }, { BG_KEY_RIGHT, BG_KEY_SHIFT_MASK, ACCEL_VOLUME_UP }, { BG_KEY_LEFT, BG_KEY_CONTROL_MASK, ACCEL_SEEK_BACKWARD }, { BG_KEY_RIGHT, BG_KEY_CONTROL_MASK, ACCEL_SEEK_FORWARD }, { BG_KEY_0, 0, ACCEL_SEEK_START }, { BG_KEY_SPACE, 0, ACCEL_PAUSE }, { BG_KEY_m, BG_KEY_CONTROL_MASK, ACCEL_MUTE }, { BG_KEY_PAGE_UP, BG_KEY_CONTROL_MASK|BG_KEY_SHIFT_MASK, ACCEL_NEXT_CHAPTER }, { BG_KEY_PAGE_DOWN, BG_KEY_CONTROL_MASK|BG_KEY_SHIFT_MASK, ACCEL_PREV_CHAPTER }, { BG_KEY_PAGE_DOWN, BG_KEY_CONTROL_MASK, ACCEL_NEXT }, { BG_KEY_PAGE_UP, BG_KEY_CONTROL_MASK, ACCEL_PREV }, { BG_KEY_q, BG_KEY_CONTROL_MASK, ACCEL_QUIT }, { BG_KEY_o, BG_KEY_CONTROL_MASK, ACCEL_OPTIONS }, { BG_KEY_g, BG_KEY_CONTROL_MASK, ACCEL_GOTO_CURRENT }, { BG_KEY_F9, 0, ACCEL_CURRENT_TO_FAVOURITES }, { BG_KEY_NONE, 0, 0 }, }; static void tree_play_callback(void * data) { gmerlin_t * g = (gmerlin_t*)data; gmerlin_play(g, 0); } static void gmerlin_apply_config(gmerlin_t * g) { const bg_parameter_info_t * parameters; parameters = display_get_parameters(g->player_window->display); bg_cfg_section_apply(g->display_section, parameters, display_set_parameter, (void*)(g->player_window->display)); #if 0 parameters = bg_media_tree_get_parameters(g->tree); bg_cfg_section_apply(g->tree_section, parameters, bg_media_tree_set_parameter, (void*)(g->tree)); #endif parameters = bg_remote_server_get_parameters(g->remote); bg_cfg_section_apply(g->remote_section, parameters, bg_remote_server_set_parameter, (void*)(g->remote)); parameters = bg_player_get_audio_parameters(g->player); bg_cfg_section_apply(g->audio_section, parameters, bg_player_set_audio_parameter, (void*)(g->player)); parameters = bg_player_get_audio_filter_parameters(g->player); bg_cfg_section_apply(g->audio_filter_section, parameters, bg_player_set_audio_filter_parameter, (void*)(g->player)); parameters = bg_player_get_video_parameters(g->player); bg_cfg_section_apply(g->video_section, parameters, bg_player_set_video_parameter, (void*)(g->player)); parameters = bg_player_get_video_filter_parameters(g->player); bg_cfg_section_apply(g->video_filter_section, parameters, bg_player_set_video_filter_parameter, (void*)(g->player)); parameters = bg_player_get_subtitle_parameters(g->player); bg_cfg_section_apply(g->subtitle_section, parameters, bg_player_set_subtitle_parameter, (void*)(g->player)); parameters = bg_player_get_osd_parameters(g->player); bg_cfg_section_apply(g->osd_section, parameters, bg_player_set_osd_parameter, (void*)(g->player)); parameters = bg_player_get_input_parameters(g->player); bg_cfg_section_apply(g->input_section, parameters, bg_player_set_input_parameter, (void*)(g->player)); parameters = gmerlin_get_parameters(g); bg_cfg_section_apply(g->general_section, parameters, gmerlin_set_parameter, (void*)(g)); parameters = bg_lcdproc_get_parameters(g->lcdproc); bg_cfg_section_apply(g->lcdproc_section, parameters, bg_lcdproc_set_parameter, (void*)(g->lcdproc)); parameters = bg_gtk_log_window_get_parameters(g->log_window); bg_cfg_section_apply(g->logwindow_section, parameters, bg_gtk_log_window_set_parameter, (void*)(g->log_window)); parameters = bg_gtk_info_window_get_parameters(g->info_window); bg_cfg_section_apply(g->infowindow_section, parameters, bg_gtk_info_window_set_parameter, (void*)(g->info_window)); parameters = bg_player_get_visualization_parameters(g->player); bg_cfg_section_apply(g->visualization_section, parameters, bg_player_set_visualization_parameter, (void*)(g->player)); } static void gmerlin_get_config(gmerlin_t * g) { const bg_parameter_info_t * parameters; #if 0 parameters = display_get_parameters(g->player_window->display); bg_cfg_section_apply(g->display_section, parameters, display_set_parameter, (void*)(g->player_window->display)); parameters = bg_media_tree_get_parameters(g->tree); bg_cfg_section_apply(g->tree_section, parameters, bg_media_tree_set_parameter, (void*)(g->tree)); parameters = bg_player_get_audio_parameters(g->player); bg_cfg_section_apply(g->audio_section, parameters, bg_player_set_audio_parameter, (void*)(g->player)); parameters = bg_player_get_audio_filter_parameters(g->player); bg_cfg_section_apply(g->audio_filter_section, parameters, bg_player_set_audio_filter_parameter, (void*)(g->player)); parameters = bg_player_get_video_parameters(g->player); bg_cfg_section_apply(g->video_section, parameters, bg_player_set_video_parameter, (void*)(g->player)); parameters = bg_player_get_video_filter_parameters(g->player); bg_cfg_section_apply(g->video_filter_section, parameters, bg_player_set_video_filter_parameter, (void*)(g->player)); parameters = bg_player_get_subtitle_parameters(g->player); bg_cfg_section_apply(g->subtitle_section, parameters, bg_player_set_subtitle_parameter, (void*)(g->player)); #endif parameters = gmerlin_get_parameters(g); bg_cfg_section_get(g->general_section, parameters, gmerlin_get_parameter, (void*)(g)); } static void infowindow_close_callback(bg_gtk_info_window_t * w, void * data) { gmerlin_t * g; g = (gmerlin_t*)data; main_menu_set_info_window_item(g->player_window->main_menu, 0); g->show_info_window = 0; } static void logwindow_close_callback(bg_gtk_log_window_t * w, void * data) { gmerlin_t * g; g = (gmerlin_t*)data; main_menu_set_log_window_item(g->player_window->main_menu, 0); g->show_log_window = 0; } static void treewindow_close_callback(bg_gtk_tree_window_t * win, void * data) { gmerlin_t * g; g = (gmerlin_t*)data; main_menu_set_tree_window_item(g->player_window->main_menu, 0); g->show_tree_window = 0; } static const bg_parameter_info_t input_plugin_parameters[] = { { .name = "input_plugins", .long_name = "Input plugins", .flags = BG_PARAMETER_PLUGIN, }, { /* */ }, }; static const bg_parameter_info_t image_reader_parameters[] = { { .name = "image_readers", .long_name = "Image readers", .flags = BG_PARAMETER_PLUGIN, }, { /* */ }, }; gmerlin_t * gmerlin_create(bg_cfg_registry_t * cfg_reg) { int remote_port; char * remote_env; bg_album_t * album; gavl_time_t duration_before, duration_current, duration_after; char * tmp_string; gmerlin_t * ret; bg_cfg_section_t * cfg_section; ret = calloc(1, sizeof(*ret)); ret->cfg_reg = cfg_reg; /* Create plugin registry */ cfg_section = bg_cfg_registry_find_section(cfg_reg, "plugins"); ret->plugin_reg = bg_plugin_registry_create(cfg_section); ret->display_section = bg_cfg_registry_find_section(cfg_reg, "Display"); ret->tree_section = bg_cfg_registry_find_section(cfg_reg, "Tree"); ret->general_section = bg_cfg_registry_find_section(cfg_reg, "General"); ret->input_section = bg_cfg_registry_find_section(cfg_reg, "Input"); ret->audio_section = bg_cfg_registry_find_section(cfg_reg, "Audio"); ret->audio_filter_section = bg_cfg_registry_find_section(cfg_reg, "AudioFilter"); ret->video_section = bg_cfg_registry_find_section(cfg_reg, "Video"); ret->video_filter_section = bg_cfg_registry_find_section(cfg_reg, "VideoFilter"); ret->subtitle_section = bg_cfg_registry_find_section(cfg_reg, "Subtitles"); ret->osd_section = bg_cfg_registry_find_section(cfg_reg, "OSD"); ret->lcdproc_section = bg_cfg_registry_find_section(cfg_reg, "LCDproc"); ret->remote_section = bg_cfg_registry_find_section(cfg_reg, "Remote"); ret->logwindow_section = bg_cfg_registry_find_section(cfg_reg, "Logwindow"); ret->infowindow_section = bg_cfg_registry_find_section(cfg_reg, "Infowindow"); ret->visualization_section = bg_cfg_registry_find_section(cfg_reg, "Visualization"); ret->input_plugin_parameters = bg_parameter_info_copy_array(input_plugin_parameters); bg_plugin_registry_set_parameter_info_input(ret->plugin_reg, BG_PLUGIN_INPUT, BG_PLUGIN_FILE| BG_PLUGIN_URL| BG_PLUGIN_REMOVABLE| BG_PLUGIN_TUNER, ret->input_plugin_parameters); ret->image_reader_parameters = bg_parameter_info_copy_array(image_reader_parameters); bg_plugin_registry_set_parameter_info_input(ret->plugin_reg, BG_PLUGIN_IMAGE_READER, BG_PLUGIN_FILE, ret->image_reader_parameters); /* Log window should be created quite early so we can catch messages during startup */ ret->log_window = bg_gtk_log_window_create(logwindow_close_callback, ret, TR("Gmerlin player")); bg_cfg_section_apply(ret->logwindow_section, bg_gtk_log_window_get_parameters(ret->log_window), bg_gtk_log_window_set_parameter, (void*)ret->log_window); /* Create player instance */ ret->player = bg_player_create(ret->plugin_reg); bg_player_add_accelerators(ret->player, accels); /* Create media tree */ tmp_string = bg_search_file_write("player/tree", "tree.xml"); if(!tmp_string) { goto fail; } ret->tree = bg_media_tree_create(tmp_string, ret->plugin_reg); free(tmp_string); bg_media_tree_set_play_callback(ret->tree, tree_play_callback, ret); bg_media_tree_set_userpass_callback(ret->tree, bg_gtk_get_userpass, NULL); /* Apply tree config */ bg_cfg_section_apply(ret->tree_section, bg_media_tree_get_parameters(ret->tree), bg_media_tree_set_parameter, (void*)(ret->tree)); bg_media_tree_init(ret->tree); /* Start creating the GUI */ ret->accel_group = gtk_accel_group_new(); ret->tree_window = bg_gtk_tree_window_create(ret->tree, treewindow_close_callback, ret, ret->accel_group); /* Create player window */ player_window_create(ret); // gmerlin_skin_load(&ret->skin, "Default"); // gmerlin_skin_set(ret); /* Create subwindows */ ret->info_window = bg_gtk_info_window_create(ret->player, infowindow_close_callback, ret); ret->lcdproc = bg_lcdproc_create(ret->player); remote_port = PLAYER_REMOTE_PORT; remote_env = getenv(PLAYER_REMOTE_ENV); if(remote_env) remote_port = atoi(remote_env); ret->remote = bg_remote_server_create(remote_port, PLAYER_REMOTE_ID); gmerlin_create_dialog(ret); /* Set playlist times for the display */ album = bg_media_tree_get_current_album(ret->tree); if(album) { bg_album_get_times(album, &duration_before, &duration_current, &duration_after); display_set_playlist_times(ret->player_window->display, duration_before, duration_current, duration_after); } return ret; fail: gmerlin_destroy(ret); return NULL; } void gmerlin_destroy(gmerlin_t * g) { player_window_destroy(g->player_window); /* Must destroy the dialogs early, because the destructors might reference parameter infos, which belong to other modules */ bg_dialog_destroy(g->cfg_dialog); bg_dialog_destroy(g->audio_dialog); bg_dialog_destroy(g->audio_filter_dialog); bg_dialog_destroy(g->video_dialog); bg_dialog_destroy(g->video_filter_dialog); bg_dialog_destroy(g->subtitle_dialog); bg_dialog_destroy(g->visualization_dialog); bg_lcdproc_destroy(g->lcdproc); bg_remote_server_destroy(g->remote); bg_player_destroy(g->player); bg_gtk_tree_window_destroy(g->tree_window); bg_parameter_info_destroy_array(g->input_plugin_parameters); bg_parameter_info_destroy_array(g->image_reader_parameters); /* Fetch parameters */ bg_cfg_section_get(g->infowindow_section, bg_gtk_info_window_get_parameters(g->info_window), bg_gtk_info_window_get_parameter, (void*)(g->info_window)); bg_gtk_info_window_destroy(g->info_window); bg_cfg_section_get(g->logwindow_section, bg_gtk_log_window_get_parameters(g->log_window), bg_gtk_log_window_get_parameter, (void*)(g->log_window)); bg_gtk_log_window_destroy(g->log_window); bg_cfg_section_get(g->tree_section, bg_media_tree_get_parameters(g->tree), bg_media_tree_get_parameter, (void*)(g->tree)); bg_media_tree_destroy(g->tree); bg_plugin_registry_destroy(g->plugin_reg); gmerlin_skin_destroy(&g->skin); free(g->skin_dir); if(g->remote_data.name) free(g->remote_data.name); gavl_metadata_free(&g->remote_data.metadata); free(g); } void gmerlin_run(gmerlin_t * g, char ** locations) { gmerlin_apply_config(g); if(g->show_tree_window) { bg_gtk_tree_window_show(g->tree_window); main_menu_set_tree_window_item(g->player_window->main_menu, 1); } else main_menu_set_tree_window_item(g->player_window->main_menu, 0); if(g->show_info_window) { bg_gtk_info_window_show(g->info_window); main_menu_set_info_window_item(g->player_window->main_menu, 1); } else { main_menu_set_info_window_item(g->player_window->main_menu, 0); } if(g->show_log_window) { bg_gtk_log_window_show(g->log_window); main_menu_set_log_window_item(g->player_window->main_menu, 1); } else { main_menu_set_log_window_item(g->player_window->main_menu, 0); } bg_player_run(g->player); player_window_show(g->player_window); if(locations) gmerlin_play_locations(g, locations); gtk_main(); /* The following saves the coords */ if(g->show_tree_window) bg_gtk_tree_window_hide(g->tree_window); bg_player_quit(g->player); gmerlin_get_config(g); } void gmerlin_skin_destroy(gmerlin_skin_t * s) { if(s->directory) free(s->directory); player_window_skin_destroy(&s->playerwindow); } int gmerlin_play(gmerlin_t * g, int flags) { int track_index; bg_plugin_handle_t * handle; bg_album_t * album; gavl_time_t duration_before; gavl_time_t duration_current; gavl_time_t duration_after; /* Tell the player that we want to change */ bg_player_change(g->player, flags); handle = bg_media_tree_get_current_track(g->tree, &track_index); if(!handle) { bg_player_error(g->player); return 0; } album = bg_media_tree_get_current_album(g->tree); bg_album_get_times(album, &duration_before, &duration_current, &duration_after); display_set_playlist_times(g->player_window->display, duration_before, duration_current, duration_after); bg_player_play(g->player, handle, track_index, flags, bg_media_tree_get_current_track_name(g->tree)); /* Unref the handle, we don't need it any longer here */ bg_plugin_unref(handle); return 1; } void gmerlin_pause(gmerlin_t * g) { if(g->player_state == BG_PLAYER_STATE_STOPPED) gmerlin_play(g, BG_PLAY_FLAG_INIT_THEN_PAUSE); else bg_player_pause(g->player); } void gmerlin_next_track(gmerlin_t * g) { int result, keep_going, removable, num_tries = 0, num_entries; bg_album_t * album; if(g->playback_flags & PLAYBACK_NOADVANCE) { bg_player_stop(g->player); return; } album = bg_media_tree_get_current_album(g->tree); if(!album) return; num_entries = bg_album_get_num_entries(album); removable = (bg_album_get_type(album) == BG_ALBUM_TYPE_REMOVABLE) ? 1 : 0; result = 1; keep_going = 1; while(keep_going) { switch(g->repeat_mode) { case REPEAT_MODE_NONE: if(bg_media_tree_next(g->tree, 0, g->shuffle_mode)) { result = gmerlin_play(g, BG_PLAY_FLAG_IGNORE_IF_PLAYING); if(result) keep_going = 0; } else { bg_player_stop(g->player); keep_going = 0; } break; case REPEAT_MODE_1: result = gmerlin_play(g, BG_PLAY_FLAG_IGNORE_IF_PLAYING); if(!result) bg_player_stop(g->player); keep_going = 0; break; case REPEAT_MODE_ALL: if(!bg_media_tree_next(g->tree, 1, g->shuffle_mode)) { bg_player_stop(g->player); keep_going = 0; } else { result = gmerlin_play(g, BG_PLAY_FLAG_IGNORE_IF_PLAYING); if(result) keep_going = 0; } num_tries++; if(num_tries >= num_entries) { bg_player_stop(g->player); keep_going = 0; } break; case NUM_REPEAT_MODES: break; } if(!result && (!(g->playback_flags & PLAYBACK_SKIP_ERROR) || removable)) break; } } void gmerlin_check_next_track(gmerlin_t * g, int track) { gavl_time_t duration_before, duration_current, duration_after; int result; bg_album_t * old_album, *new_album; bg_album_entry_t * current_entry; if(g->playback_flags & PLAYBACK_NOADVANCE) { bg_player_stop(g->player); return; } switch(g->repeat_mode) { case REPEAT_MODE_ALL: case REPEAT_MODE_NONE: old_album = bg_media_tree_get_current_album(g->tree); if(!bg_media_tree_next(g->tree, (g->repeat_mode == REPEAT_MODE_ALL) ? 1 : 0, g->shuffle_mode)) { bg_player_stop(g->player); } new_album = bg_media_tree_get_current_album(g->tree); if(old_album != new_album) gmerlin_play(g, 0); else { current_entry = bg_album_get_current_entry(new_album); if(current_entry->index != track) gmerlin_play(g, 0); else { bg_album_get_times(new_album, &duration_before, &duration_current, &duration_after); display_set_playlist_times(g->player_window->display, duration_before, duration_current, duration_after); } } break; case REPEAT_MODE_1: result = gmerlin_play(g, 0); if(!result) bg_player_stop(g->player); break; case NUM_REPEAT_MODES: break; } } static const bg_parameter_info_t parameters[] = { #if 0 { .name = "general_options", .long_name = TRS("General Options"), .type = BG_PARAMETER_SECTION, }, #endif { .name = "skip_error_tracks", .long_name = TRS("Skip error tracks"), .type = BG_PARAMETER_CHECKBUTTON, .val_default = { .val_i = 1 }, .help_string = TRS("If a track cannot be opened, switch to the next one") }, { .name = "dont_advance", .long_name = TRS("Don't advance"), .type = BG_PARAMETER_CHECKBUTTON, .val_default = { .val_i = 0 }, }, { .name = "shuffle_mode", .long_name = TRS("Shuffle mode"), .type = BG_PARAMETER_STRINGLIST, .multi_names = (char const *[]){"off", "current", "all", NULL }, .multi_labels = (char const *[]){TRS("Off"), TRS("Current album"), TRS("All open albums"), NULL }, .val_default = { .val_str = "Off" } }, { .name = "show_tooltips", .long_name = TRS("Show tooltips"), .type = BG_PARAMETER_CHECKBUTTON, .val_default = { .val_i = 1 }, }, { .name = "mainwin_x", .long_name = "mainwin_x", .type = BG_PARAMETER_INT, .flags = BG_PARAMETER_HIDE_DIALOG, .val_default = { .val_i = 10 } }, { .name = "mainwin_y", .long_name = "mainwin_y", .type = BG_PARAMETER_INT, .flags = BG_PARAMETER_HIDE_DIALOG, .val_default = { .val_i = 10 } }, { .name = "show_tree_window", .long_name = "show_tree_window", .type = BG_PARAMETER_CHECKBUTTON, .flags = BG_PARAMETER_HIDE_DIALOG, .val_default = { .val_i = 1 } }, { .name = "show_info_window", .long_name = "show_info_window", .type = BG_PARAMETER_CHECKBUTTON, .flags = BG_PARAMETER_HIDE_DIALOG, .val_default = { .val_i = 0 } }, { .name = "show_log_window", .long_name = "show_log_window", .type = BG_PARAMETER_CHECKBUTTON, .flags = BG_PARAMETER_HIDE_DIALOG, .val_default = { .val_i = 0 } }, { .name = "volume", .long_name = "Volume", .type = BG_PARAMETER_FLOAT, .flags = BG_PARAMETER_HIDE_DIALOG, .val_min = { .val_f = BG_PLAYER_VOLUME_MIN }, .val_max = { .val_f = 0.0 }, .val_default = { .val_f = 0.0 }, }, { .name = "skin_dir", .long_name = "Skin Directory", .type = BG_PARAMETER_DIRECTORY, .flags = BG_PARAMETER_HIDE_DIALOG, .val_default = { .val_str = DATA_DIR"/skins/Default" }, }, { /* End of Parameters */ } }; const bg_parameter_info_t * gmerlin_get_parameters(gmerlin_t * g) { return parameters; } void gmerlin_set_parameter(void * data, const char * name, const bg_parameter_value_t * val) { gmerlin_t * g = (gmerlin_t*)data; if(!name) return; if(!strcmp(name, "skip_error_tracks")) { if(val->val_i) g->playback_flags |= PLAYBACK_SKIP_ERROR; else g->playback_flags &= ~PLAYBACK_SKIP_ERROR; } else if(!strcmp(name, "dont_advance")) { if(val->val_i) g->playback_flags |= PLAYBACK_NOADVANCE; else g->playback_flags &= ~PLAYBACK_NOADVANCE; } else if(!strcmp(name, "show_tree_window")) { g->show_tree_window = val->val_i; } else if(!strcmp(name, "show_info_window")) { g->show_info_window = val->val_i; } else if(!strcmp(name, "show_log_window")) { g->show_log_window = val->val_i; } else if(!strcmp(name, "mainwin_x")) { g->player_window->window_x = val->val_i; } else if(!strcmp(name, "mainwin_y")) { g->player_window->window_y = val->val_i; } else if(!strcmp(name, "shuffle_mode")) { if(!strcmp(val->val_str, "off")) { g->shuffle_mode = BG_SHUFFLE_MODE_OFF; } else if(!strcmp(val->val_str, "current")) { g->shuffle_mode = BG_SHUFFLE_MODE_CURRENT; } else if(!strcmp(val->val_str, "all")) { g->shuffle_mode = BG_SHUFFLE_MODE_ALL; } } else if(!strcmp(name, "volume")) { bg_player_set_volume(g->player, val->val_f); g->player_window->volume = val->val_f; bg_gtk_slider_set_pos(g->player_window->volume_slider, (g->player_window->volume - BG_PLAYER_VOLUME_MIN)/ (-BG_PLAYER_VOLUME_MIN)); } else if(!strcmp(name, "show_tooltips")) { bg_gtk_set_tooltips(val->val_i); } else if(!strcmp(name, "skin_dir")) { g->skin_dir = bg_strdup(g->skin_dir, val->val_str); g->skin_dir = gmerlin_skin_load(&g->skin, g->skin_dir); gmerlin_skin_set(g); } } int gmerlin_get_parameter(void * data, const char * name, bg_parameter_value_t * val) { gmerlin_t * g = (gmerlin_t*)data; if(!name) return 0; if(!strcmp(name, "show_tree_window")) { val->val_i = g->show_tree_window; return 1; } else if(!strcmp(name, "show_info_window")) { val->val_i = g->show_info_window; return 1; } else if(!strcmp(name, "show_log_window")) { val->val_i = g->show_log_window; return 1; } else if(!strcmp(name, "mainwin_x")) { val->val_i = g->player_window->window_x; } else if(!strcmp(name, "mainwin_y")) { val->val_i = g->player_window->window_y; } else if(!strcmp(name, "volume")) { val->val_f = g->player_window->volume; } else if(!strcmp(name, "skin_dir")) { val->val_str = bg_strdup(val->val_str, g->skin_dir); } return 0; } void gmerlin_add_locations(gmerlin_t * g, char ** locations) { int was_open; int i; bg_album_t * incoming; i = 0; while(locations[i]) { i++; } incoming = bg_media_tree_get_incoming(g->tree); if(bg_album_is_open(incoming)) { was_open = 1; } else { was_open = 0; bg_album_open(incoming); } bg_album_insert_urls_before(incoming, locations, NULL, 0, NULL); if(!was_open) bg_album_close(incoming); } void gmerlin_play_locations(gmerlin_t * g, char ** locations) { int old_num_tracks, new_num_tracks; int i; bg_album_t * incoming; bg_album_entry_t * entry; i = 0; while(locations[i]) { i++; } bg_gtk_tree_window_open_incoming(g->tree_window); incoming = bg_media_tree_get_incoming(g->tree); old_num_tracks = bg_album_get_num_entries(incoming); gmerlin_add_locations(g, locations); new_num_tracks = bg_album_get_num_entries(incoming); if(new_num_tracks > old_num_tracks) { entry = bg_album_get_entry(incoming, old_num_tracks); bg_album_set_current(incoming, entry); bg_album_play(incoming); } } static bg_album_t * open_device(gmerlin_t * g, char * device) { bg_album_t * album; album = bg_media_tree_get_device_album(g->tree, device); if(!album) return album; if(!bg_album_is_open(album)) { bg_album_open(album); bg_gtk_tree_window_update(g->tree_window, 1); } return album; } void gmerlin_open_device(gmerlin_t * g, char * device) { open_device(g, device); } void gmerlin_play_device(gmerlin_t * g, char * device) { bg_album_t * album; bg_album_entry_t * entry; album = open_device(g, device); if(!album) return; entry = bg_album_get_entry(album, 0); if(!entry) return; bg_album_set_current(album, entry); bg_album_play(album); } gmerlin-1.2.0~dfsg/apps/player/cfgdialog.c0000644000175000017500000001573711764363403020437 0ustar alessioalessio/***************************************************************** * gmerlin - a general purpose multimedia framework and applications * * Copyright (c) 2001 - 2011 Members of the Gmerlin project * gmerlin-general@lists.sourceforge.net * http://gmerlin.sourceforge.net * * 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 of the License, 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 this program. If not, see . * *****************************************************************/ #include #include #include "gmerlin.h" void gmerlin_create_dialog(gmerlin_t * g) { const bg_parameter_info_t * parameters; /* Create the dialogs */ /* Audio options */ parameters = bg_player_get_audio_parameters(g->player); g->audio_dialog = bg_dialog_create(g->audio_section, bg_player_set_audio_parameter, NULL, (void*)(g->player), parameters, TR("Audio options")); /* Audio filters */ parameters = bg_player_get_audio_filter_parameters(g->player); g->audio_filter_dialog = bg_dialog_create(g->audio_filter_section, bg_player_set_audio_filter_parameter, NULL, (void*)(g->player), parameters, TR("Audio filters")); /* Video options */ parameters = bg_player_get_video_parameters(g->player); g->video_dialog = bg_dialog_create(g->video_section, bg_player_set_video_parameter, NULL, (void*)(g->player), parameters, TR("Video options")); /* Video filters */ parameters = bg_player_get_video_filter_parameters(g->player); g->video_filter_dialog = bg_dialog_create(g->video_filter_section, bg_player_set_video_filter_parameter, NULL, (void*)(g->player), parameters, TR("Video filters")); /* Subtitles */ parameters = bg_player_get_subtitle_parameters(g->player); g->subtitle_dialog = bg_dialog_create(g->subtitle_section, bg_player_set_subtitle_parameter, NULL, (void*)(g->player), parameters, TR("Subtitle options")); parameters = bg_player_get_visualization_parameters(g->player); g->visualization_dialog = bg_dialog_create(g->visualization_section, bg_player_set_visualization_parameter, NULL, (void*)(g->player), parameters, TR("Visualization")); #if 0 parent = bg_dialog_add_parent(g->subtitle_dialog, NULL, TR("Text subtitles")); bg_dialog_add_child(g->cfg_dialog, parent, TR("Subtitles"), g->subtitle_section, bg_player_set_subtitle_parameter, (void*)(g->player), parameters); #endif g->cfg_dialog = bg_dialog_create_multi(TR("Gmerlin confiuration")); /* Add sections */ parameters = gmerlin_get_parameters(g); bg_dialog_add(g->cfg_dialog, TR("General"), g->general_section, gmerlin_set_parameter, NULL, (void*)(g), parameters); parameters = bg_player_get_input_parameters(g->player); bg_dialog_add(g->cfg_dialog, TR("Input"), g->input_section, bg_player_set_input_parameter, NULL, (void*)(g->player), parameters); bg_dialog_add(g->cfg_dialog, TR("Input plugins"), NULL, bg_plugin_registry_set_parameter_input, bg_plugin_registry_get_parameter_input, g->plugin_reg, g->input_plugin_parameters); bg_dialog_add(g->cfg_dialog, TR("Image readers"), NULL, bg_plugin_registry_set_parameter_input, bg_plugin_registry_get_parameter_input, g->plugin_reg, g->image_reader_parameters); parameters = bg_player_get_osd_parameters(g->player); bg_dialog_add(g->cfg_dialog, TR("OSD"), g->osd_section, bg_player_set_osd_parameter, NULL, (void*)(g->player), parameters); parameters = display_get_parameters(g->player_window->display); bg_dialog_add(g->cfg_dialog, TR("Display"), g->display_section, display_set_parameter, NULL, (void*)(g->player_window->display), parameters); parameters = bg_media_tree_get_parameters(g->tree); bg_dialog_add(g->cfg_dialog, TR("Media Tree"), g->tree_section, bg_media_tree_set_parameter, NULL, (void*)(g->tree), parameters); parameters = bg_remote_server_get_parameters(g->remote); bg_dialog_add(g->cfg_dialog, TR("Remote control"), g->remote_section, bg_remote_server_set_parameter, NULL, (void*)(g->remote), parameters); parameters = bg_gtk_log_window_get_parameters(g->log_window); bg_dialog_add(g->cfg_dialog, TR("Log window"), g->logwindow_section, bg_gtk_log_window_set_parameter, NULL, (void*)(g->log_window), parameters); parameters = bg_lcdproc_get_parameters(g->lcdproc); bg_dialog_add(g->cfg_dialog, TR("LCDproc"), g->lcdproc_section, bg_lcdproc_set_parameter, NULL, (void*)(g->lcdproc), parameters); } void gmerlin_configure(gmerlin_t * g) { bg_dialog_show(g->cfg_dialog, g->player_window->window); } gmerlin-1.2.0~dfsg/apps/player/mainmenu.c0000644000175000017500000012020111764363403020310 0ustar alessioalessio/***************************************************************** * gmerlin - a general purpose multimedia framework and applications * * Copyright (c) 2001 - 2011 Members of the Gmerlin project * gmerlin-general@lists.sourceforge.net * http://gmerlin.sourceforge.net * * 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 of the License, 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 this program. If not, see . * *****************************************************************/ #include #include #include #include "gmerlin.h" #include #include #include #include #include typedef struct { int num_plugins; GtkWidget * menu; GtkWidget ** plugin_items; GtkWidget * info; GtkWidget * options; const bg_plugin_info_t * plugin_info; bg_plugin_handle_t * plugin_handle; bg_plugin_type_t type; uint32_t flags; bg_cfg_section_t * section; int no_callback; gmerlin_t * g; // For convenience } plugin_menu_t; typedef struct stream_menu_s { GSList * group; GtkWidget ** stream_items; guint * ids; GtkWidget * off_item; guint off_id; int num_streams; int streams_alloc; GtkWidget * menu; GtkWidget * options; GtkWidget * plugins; GtkWidget * filters; plugin_menu_t plugin_menu; } stream_menu_t; typedef struct chapter_menu_s { int timescale; int num_chapters; int chapters_alloc; guint * ids; GSList * group; GtkWidget ** chapter_items; GtkWidget * menu; } chapter_menu_t; typedef struct visualization_menu_s { GtkWidget * menu; GtkWidget * enable; GtkWidget * options; GtkWidget * plugins; plugin_menu_t plugin_menu; } visualization_menu_t; struct windows_menu_s { GtkWidget * mediatree; guint mediatree_id; GtkWidget * infowindow; guint infowindow_id; GtkWidget * logwindow; guint logwindow_id; GtkWidget * menu; }; struct help_menu_s { GtkWidget * about; GtkWidget * help; GtkWidget * menu; }; struct options_menu_s { GtkWidget * preferences; GtkWidget * skins; GtkWidget * kbd; GtkWidget * menu; }; struct command_menu_s { GtkWidget * inc_volume; GtkWidget * dec_volume; GtkWidget * mute; GtkWidget * seek_forward; GtkWidget * seek_backward; GtkWidget * next; GtkWidget * previous; GtkWidget * next_chapter; GtkWidget * previous_chapter; GtkWidget * current_to_favourites; GtkWidget * goto_current; GtkWidget * seek_start; GtkWidget * pause; GtkWidget * quit; GtkWidget * menu; }; struct accessories_menu_s { GtkWidget * transcoder; GtkWidget * visualizer; GtkWidget * mixer; GtkWidget * menu; }; struct main_menu_s { struct windows_menu_s windows_menu; struct help_menu_s help_menu; struct options_menu_s options_menu; struct command_menu_s command_menu; struct accessories_menu_s accessories_menu; struct stream_menu_s audio_stream_menu; struct stream_menu_s video_stream_menu; struct stream_menu_s subtitle_stream_menu; struct chapter_menu_s chapter_menu; struct visualization_menu_s visualization_menu; GtkWidget * windows_item; GtkWidget * help_item; GtkWidget * options_item; GtkWidget * accessories_item; GtkWidget * audio_stream_item; GtkWidget * video_stream_item; GtkWidget * subtitle_stream_item; GtkWidget * chapter_item; GtkWidget * visualization_item; GtkWidget * menu; gmerlin_t * g; }; static GtkWidget * create_menu() { GtkWidget * ret; GtkWidget * tearoff_item; ret = gtk_menu_new(); tearoff_item = gtk_tearoff_menu_item_new(); gtk_widget_show(tearoff_item); gtk_menu_shell_append(GTK_MENU_SHELL(ret), tearoff_item); return ret; } static int stream_menu_has_widget(stream_menu_t * s, GtkWidget * w, int * index) { int i; if((w == s->off_item) && gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(s->off_item))) { *index = -1; return 1; } for(i = 0; i < s->num_streams; i++) { if((w == s->stream_items[i]) && gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(s->stream_items[i]))) { *index = i; return 1; } } return 0; } static int chapter_menu_has_widget(chapter_menu_t * s, GtkWidget * w, int * index) { int i; for(i = 0; i < s->num_chapters; i++) { if((w == s->chapter_items[i]) && gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(s->chapter_items[i]))) { *index = i; return 1; } } return 0; } static int plugin_menu_has_widget(plugin_menu_t * s, GtkWidget * w, int * index) { int i; for(i = 0; i < s->num_plugins; i++) { if((w == s->plugin_items[i]) && gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(s->plugin_items[i]))) { *index = i; return 1; } } return 0; } static void plugin_menu_set_plugin(plugin_menu_t * s, int index) { if(s->no_callback) return; s->plugin_info = bg_plugin_find_by_index(s->g->plugin_reg, index, s->type, BG_PLUGIN_ALL); /* Save for future use */ bg_plugin_registry_set_default(s->g->plugin_reg, s->type, s->flags, s->plugin_info->name); if(s->plugin_handle) { bg_plugin_unref(s->plugin_handle); s->plugin_handle = NULL; } if(s->plugin_info->parameters) gtk_widget_set_sensitive(s->options, 1); else gtk_widget_set_sensitive(s->options, 0); if(s->type == BG_PLUGIN_OUTPUT_AUDIO) { s->plugin_handle = bg_plugin_load(s->g->plugin_reg, s->plugin_info); bg_player_set_oa_plugin(s->g->player, s->plugin_handle); } else if(s->type == BG_PLUGIN_OUTPUT_VIDEO) { bg_ov_plugin_t * plugin; s->plugin_handle = bg_plugin_load(s->g->plugin_reg, s->plugin_info); plugin = (bg_ov_plugin_t *)s->plugin_handle->plugin; if(plugin->set_window_options) { gavl_video_frame_t * icon = NULL; gavl_video_format_t icon_format; char * icon_path; memset(&icon_format, 0, sizeof(icon_format)); /* Load icon */ icon_path = bg_search_file_read("icons", WINDOW_ICON); if(icon_path) { icon = bg_plugin_registry_load_image(s->g->plugin_reg, icon_path, &icon_format, NULL); } plugin->set_window_options(s->plugin_handle->priv, WINDOW_NAME, WINDOW_CLASS, icon, &icon_format); if(icon) gavl_video_frame_destroy(icon); if(icon_path) free(icon_path); } bg_player_set_ov_plugin(s->g->player, s->plugin_handle); } else if(s->type == BG_PLUGIN_VISUALIZATION) { bg_player_set_visualization_plugin(s->g->player, s->plugin_info); } s->section = bg_plugin_registry_get_section(s->g->plugin_reg, s->plugin_info->name); } static void set_parameter(void * data, const char * name, const bg_parameter_value_t * v) { plugin_menu_t * m; m = (plugin_menu_t*)data; if(m->plugin_handle && m->plugin_handle->plugin->set_parameter) { bg_plugin_lock(m->plugin_handle); m->plugin_handle->plugin->set_parameter(m->plugin_handle->priv, name, v); bg_plugin_unlock(m->plugin_handle); } else if(m->type == BG_PLUGIN_VISUALIZATION) { bg_player_set_visualization_plugin_parameter(m->g->player, name, v); } } static void plugin_menu_configure(plugin_menu_t * m) { const bg_parameter_info_t * parameters; bg_dialog_t * dialog; if(m->plugin_handle) parameters = m->plugin_handle->plugin->get_parameters(m->plugin_handle->priv); else parameters = m->plugin_info->parameters; dialog = bg_dialog_create(m->section, set_parameter, NULL, (void*)m, parameters, TRD(m->plugin_info->long_name, m->plugin_info->gettext_domain)); bg_dialog_show(dialog, m->g->player_window->window); bg_dialog_destroy(dialog); } static void plugin_menu_free(plugin_menu_t * s) { if(s->plugin_handle) bg_plugin_unref(s->plugin_handle); if(s->plugin_items) free(s->plugin_items); } static void about_window_close_callback(bg_gtk_about_window_t* win, void* data) { gmerlin_t * g; main_menu_t * the_menu; g = (gmerlin_t*)data; the_menu = g->player_window->main_menu; gtk_widget_set_sensitive(the_menu->help_menu.about, 1); } static void menu_callback(GtkWidget * w, gpointer data) { int i; gmerlin_t * g; main_menu_t * the_menu; g = (gmerlin_t*)data; the_menu = g->player_window->main_menu; if(w == the_menu->options_menu.preferences) gmerlin_configure(g); else if(w == the_menu->audio_stream_menu.options) bg_dialog_show(g->audio_dialog, g->player_window->window); else if(w == the_menu->audio_stream_menu.filters) bg_dialog_show(g->audio_filter_dialog, g->player_window->window); else if(w == the_menu->video_stream_menu.options) bg_dialog_show(g->video_dialog, g->player_window->window); else if(w == the_menu->video_stream_menu.filters) bg_dialog_show(g->video_filter_dialog, g->player_window->window); else if(w == the_menu->subtitle_stream_menu.options) bg_dialog_show(g->subtitle_dialog, g->player_window->window); else if(w == the_menu->visualization_menu.options) bg_dialog_show(g->visualization_dialog, g->player_window->window); else if(w == the_menu->visualization_menu.enable) { i = gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(the_menu->visualization_menu.enable)); bg_player_set_visualization(g->player, i); bg_plugin_registry_set_visualize(g->plugin_reg, i); } else if(w == the_menu->options_menu.skins) { if(!g->skin_browser) g->skin_browser = gmerlin_skin_browser_create(g); gmerlin_skin_browser_show(g->skin_browser); } else if(w == the_menu->options_menu.kbd) { bg_system("gmerlin_kbd_config &"); } else if(w == the_menu->windows_menu.infowindow) { if(gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(the_menu->windows_menu.infowindow))) { bg_gtk_info_window_show(g->info_window); g->show_info_window = 1; } else { bg_gtk_info_window_hide(g->info_window); g->show_info_window = 0; } } else if(w == the_menu->windows_menu.logwindow) { if(gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(the_menu->windows_menu.logwindow))) { bg_gtk_log_window_show(g->log_window); g->show_log_window = 1; } else { bg_gtk_log_window_hide(g->log_window); g->show_log_window = 0; } } else if(w == the_menu->help_menu.about) { gtk_widget_set_sensitive(the_menu->help_menu.about, 0); bg_gtk_about_window_create("Gmerlin player", VERSION, "player_icon.png", about_window_close_callback, g); } else if(w == the_menu->help_menu.help) { bg_display_html_help("userguide/GUI-Player.html"); } else if(w == the_menu->windows_menu.mediatree) { if(gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(the_menu->windows_menu.mediatree))) { bg_gtk_tree_window_show(g->tree_window); g->show_tree_window = 1; } else { bg_gtk_tree_window_hide(g->tree_window); g->show_tree_window = 0; } } else if(w == the_menu->accessories_menu.visualizer) { bg_system("gmerlin_visualizer &"); } else if(w == the_menu->accessories_menu.mixer) { bg_system("gmerlin_alsamixer &"); } else if(w == the_menu->accessories_menu.transcoder) { bg_system("gmerlin_transcoder_remote -launch"); } /* Commands (== accelerators) */ else if(w == the_menu->command_menu.inc_volume) player_window_push_accel(g->player_window, ACCEL_VOLUME_UP); else if(w == the_menu->command_menu.dec_volume) player_window_push_accel(g->player_window, ACCEL_VOLUME_DOWN); else if(w == the_menu->command_menu.seek_backward) player_window_push_accel(g->player_window, ACCEL_SEEK_BACKWARD); else if(w == the_menu->command_menu.seek_forward) player_window_push_accel(g->player_window, ACCEL_SEEK_FORWARD); else if(w == the_menu->command_menu.seek_start) player_window_push_accel(g->player_window, ACCEL_SEEK_START); else if(w == the_menu->command_menu.pause) player_window_push_accel(g->player_window, ACCEL_PAUSE); else if(w == the_menu->command_menu.mute) player_window_push_accel(g->player_window, ACCEL_MUTE); else if(w == the_menu->command_menu.next_chapter) player_window_push_accel(g->player_window, ACCEL_NEXT_CHAPTER); else if(w == the_menu->command_menu.previous_chapter) player_window_push_accel(g->player_window, ACCEL_PREV_CHAPTER); else if(w == the_menu->command_menu.next) player_window_push_accel(g->player_window, ACCEL_NEXT); else if(w == the_menu->command_menu.previous) player_window_push_accel(g->player_window, ACCEL_PREV); else if(w == the_menu->command_menu.current_to_favourites) player_window_push_accel(g->player_window, ACCEL_CURRENT_TO_FAVOURITES); else if(w == the_menu->command_menu.quit) player_window_push_accel(g->player_window, ACCEL_QUIT); /* Stream selection */ else if(stream_menu_has_widget(&the_menu->audio_stream_menu, w, &i)) bg_player_set_audio_stream(g->player, i); else if(stream_menu_has_widget(&the_menu->video_stream_menu, w, &i)) bg_player_set_video_stream(g->player, i); else if(stream_menu_has_widget(&the_menu->subtitle_stream_menu, w, &i)) bg_player_set_subtitle_stream(g->player, i); /* Chapters */ else if(chapter_menu_has_widget(&the_menu->chapter_menu, w, &i)) bg_player_set_chapter(g->player, i); /* Audio plugin */ else if(plugin_menu_has_widget(&the_menu->audio_stream_menu.plugin_menu, w, &i)) plugin_menu_set_plugin(&the_menu->audio_stream_menu.plugin_menu, i); else if(w == the_menu->audio_stream_menu.plugin_menu.info) bg_gtk_plugin_info_show(the_menu->audio_stream_menu.plugin_menu.plugin_info, g->player_window->window); else if(w == the_menu->audio_stream_menu.plugin_menu.options) plugin_menu_configure(&the_menu->audio_stream_menu.plugin_menu); /* Video plugin */ else if(plugin_menu_has_widget(&the_menu->video_stream_menu.plugin_menu, w, &i)) plugin_menu_set_plugin(&the_menu->video_stream_menu.plugin_menu, i); else if(w == the_menu->video_stream_menu.plugin_menu.info) bg_gtk_plugin_info_show(the_menu->video_stream_menu.plugin_menu.plugin_info, g->player_window->window); else if(w == the_menu->video_stream_menu.plugin_menu.options) plugin_menu_configure(&the_menu->video_stream_menu.plugin_menu); /* Visualization plugin */ else if(plugin_menu_has_widget(&the_menu->visualization_menu.plugin_menu, w, &i)) plugin_menu_set_plugin(&the_menu->visualization_menu.plugin_menu, i); else if(w == the_menu->visualization_menu.plugin_menu.info) bg_gtk_plugin_info_show(the_menu->visualization_menu.plugin_menu.plugin_info, g->player_window->window); else if(w == the_menu->visualization_menu.plugin_menu.options) plugin_menu_configure(&the_menu->visualization_menu.plugin_menu); } static GtkWidget * create_pixmap_item(const char * label, const char * pixmap, gmerlin_t * gmerlin, GtkWidget * menu) { GtkWidget * ret, *image; char * path; if(pixmap) { path = bg_search_file_read("icons", pixmap); if(path) { image = gtk_image_new_from_file(path); free(path); } else image = gtk_image_new(); gtk_widget_show(image); ret = gtk_image_menu_item_new_with_label(label); gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(ret), image); } else { ret = gtk_menu_item_new_with_label(label); } g_signal_connect(G_OBJECT(ret), "activate", G_CALLBACK(menu_callback), (gpointer)gmerlin); gtk_widget_show(ret); gtk_menu_shell_append(GTK_MENU_SHELL(menu), ret); return ret; } static GtkWidget * create_item(const char * label, gmerlin_t * gmerlin, GtkWidget * menu) { GtkWidget * ret; ret = gtk_menu_item_new_with_label(label); g_signal_connect(G_OBJECT(ret), "activate", G_CALLBACK(menu_callback), gmerlin); gtk_widget_show(ret); gtk_menu_shell_append(GTK_MENU_SHELL(menu), ret); return ret; } static GtkWidget * create_toggle_item(const char * label, gmerlin_t * gmerlin, GtkWidget * menu, guint * id) { guint32 handler_id; GtkWidget * ret; ret = gtk_check_menu_item_new_with_label(label); handler_id = g_signal_connect(G_OBJECT(ret), "toggled", G_CALLBACK(menu_callback), gmerlin); if(id) *id = handler_id; gtk_widget_show(ret); gtk_menu_shell_append(GTK_MENU_SHELL(menu), ret); return ret; } static GtkWidget * create_stream_item(gmerlin_t * gmerlin, stream_menu_t * m, guint * id) { GtkWidget * ret; ret = gtk_radio_menu_item_new_with_label(m->group, ""); m->group = gtk_radio_menu_item_get_group(GTK_RADIO_MENU_ITEM(ret)); *id = g_signal_connect(G_OBJECT(ret), "activate", G_CALLBACK(menu_callback), gmerlin); gtk_menu_shell_insert(GTK_MENU_SHELL(m->menu), ret, (int)(id - m->ids) + 2); return ret; } static GtkWidget * create_chapter_item(gmerlin_t * gmerlin, chapter_menu_t * m, guint * id) { GtkWidget * ret; ret = gtk_radio_menu_item_new_with_label(m->group, ""); m->group = gtk_radio_menu_item_get_group(GTK_RADIO_MENU_ITEM(ret)); *id = g_signal_connect(G_OBJECT(ret), "activate", G_CALLBACK(menu_callback), gmerlin); gtk_menu_shell_append(GTK_MENU_SHELL(m->menu), ret); return ret; } static GtkWidget * create_submenu_item(const char * label, GtkWidget * child_menu, GtkWidget * parent_menu) { GtkWidget * ret; ret = gtk_menu_item_new_with_label(label); gtk_menu_item_set_submenu(GTK_MENU_ITEM(ret), child_menu); gtk_widget_show(ret); gtk_menu_shell_append(GTK_MENU_SHELL(parent_menu), ret); return ret; } #if 0 typedef struct stream_menu_s { GSList * group; GtkWidget ** stream_items; guint * ids; GtkWidget * off_item; guint off_id; int num_streams; int streams_alloc; GtkWidget * menu; } stream_menu_t; #endif static void plugin_menu_init(plugin_menu_t * m, gmerlin_t * gmerlin, bg_plugin_type_t plugin_type, uint32_t flags) { int i; const bg_plugin_info_t * info; GtkWidget * w; GSList * group = NULL; m->type = plugin_type; m->flags = flags; m->menu = create_menu(); m->g = gmerlin; m->num_plugins = bg_plugin_registry_get_num_plugins(gmerlin->plugin_reg, plugin_type, BG_PLUGIN_ALL); m->plugin_items = calloc(m->num_plugins, sizeof(*m->plugin_items)); for(i = 0; i < m->num_plugins; i++) { info = bg_plugin_find_by_index(gmerlin->plugin_reg, i, plugin_type, BG_PLUGIN_ALL); m->plugin_items[i] = gtk_radio_menu_item_new_with_label(group, TRD(info->long_name, info->gettext_domain)); g_signal_connect(G_OBJECT(m->plugin_items[i]), "activate", G_CALLBACK(menu_callback), gmerlin); gtk_widget_show(m->plugin_items[i]); group = gtk_radio_menu_item_get_group(GTK_RADIO_MENU_ITEM(m->plugin_items[i])); gtk_menu_shell_append(GTK_MENU_SHELL(m->menu), m->plugin_items[i]); } w = gtk_separator_menu_item_new(); gtk_widget_show(w); gtk_menu_shell_append(GTK_MENU_SHELL(m->menu), w); m->options = create_pixmap_item("Options...", "config_16.png", gmerlin, m->menu); m->info = create_pixmap_item("Info...", "info_16.png", gmerlin, m->menu); } static void plugin_menu_finalize(plugin_menu_t * m) { const bg_plugin_info_t * default_info; const bg_plugin_info_t * info; int default_index = 0, i; default_info = bg_plugin_registry_get_default(m->g->plugin_reg, m->type, m->flags); m->no_callback = 1; for(i = 0; i < m->num_plugins; i++) { info = bg_plugin_find_by_index(m->g->plugin_reg, i, m->type, BG_PLUGIN_ALL); if(info == default_info) { gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(m->plugin_items[i]), 1); default_index = i; } } m->no_callback = 0; /* Set default plugin and send it to the player */ plugin_menu_set_plugin(m, default_index); } static void stream_menu_init(stream_menu_t * s, gmerlin_t * gmerlin, int has_plugins, int has_filters, bg_plugin_type_t plugin_type) { GtkWidget * separator; s->menu = create_menu(); s->off_item = gtk_radio_menu_item_new_with_label(NULL, TR("Off")); s->off_id = g_signal_connect(G_OBJECT(s->off_item), "activate", G_CALLBACK(menu_callback), gmerlin); s->group = gtk_radio_menu_item_get_group(GTK_RADIO_MENU_ITEM(s->off_item)); gtk_widget_show(s->off_item); gtk_menu_shell_append(GTK_MENU_SHELL(s->menu), s->off_item); separator = gtk_separator_menu_item_new(); gtk_widget_show(separator); gtk_menu_shell_append(GTK_MENU_SHELL(s->menu), separator); s->options = create_pixmap_item(TR("Options..."), "config_16.png", gmerlin, s->menu); if(has_filters) s->filters = create_pixmap_item(TR("Filters..."), "filter_16.png", gmerlin, s->menu); if(has_plugins) { s->plugins = create_pixmap_item(TR("Output plugin..."), "plugin_16.png", gmerlin, s->menu); plugin_menu_init(&s->plugin_menu, gmerlin, plugin_type, BG_PLUGIN_PLAYBACK); gtk_menu_item_set_submenu(GTK_MENU_ITEM(s->plugins), s->plugin_menu.menu); } } static void stream_menu_free(stream_menu_t * s) { if(s->stream_items) free(s->stream_items); if(s->ids) free(s->ids); } static void stream_menu_finalize(stream_menu_t * s) { if(s->plugin_menu.menu) plugin_menu_finalize(&s->plugin_menu); } static void visualization_menu_init(visualization_menu_t * s, gmerlin_t * gmerlin) { s->menu = create_menu(); s->enable = create_toggle_item(TR("Enable visualizations"), gmerlin, s->menu, NULL); gtk_widget_show(s->enable); s->options = create_pixmap_item(TR("Options..."), "config_16.png", gmerlin, s->menu); s->plugins = create_pixmap_item(TR("Plugin..."), "plugin_16.png", gmerlin, s->menu); plugin_menu_init(&s->plugin_menu, gmerlin, BG_PLUGIN_VISUALIZATION, BG_PLUGIN_VISUALIZE_FRAME | BG_PLUGIN_VISUALIZE_GL); gtk_menu_item_set_submenu(GTK_MENU_ITEM(s->plugins), s->plugin_menu.menu); } static void visualization_menu_finalize(visualization_menu_t * s, gmerlin_t * gmerlin) { plugin_menu_finalize(&s->plugin_menu); if(bg_plugin_registry_get_visualize(gmerlin->plugin_reg)) gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(s->enable), 1); } static void stream_menu_set_num(gmerlin_t * g, stream_menu_t * s, int num) { int i; if(num > s->streams_alloc) { s->stream_items = realloc(s->stream_items, num * sizeof(*s->stream_items)); s->ids = realloc(s->ids, num * sizeof(*s->ids)); for(i = s->streams_alloc; i < num; i++) s->stream_items[i] = create_stream_item(g, s, &s->ids[i]); s->streams_alloc = num; } for(i = 0; i < num; i++) gtk_widget_show(s->stream_items[i]); for(i = num; i < s->streams_alloc; i++) gtk_widget_hide(s->stream_items[i]); s->num_streams = num; } static void stream_menu_set_index(stream_menu_t * s, int index) { int i; /* Block event handlers */ g_signal_handler_block(G_OBJECT(s->off_item), s->off_id); for(i = 0; i < s->streams_alloc; i++) g_signal_handler_block(G_OBJECT(s->stream_items[i]), s->ids[i]); /* Select item */ if(index == -1) gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(s->off_item), 1); else gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(s->stream_items[index]), 1); /* Unblock event handlers */ g_signal_handler_unblock(G_OBJECT(s->off_item), s->off_id); for(i = 0; i < s->streams_alloc; i++) g_signal_handler_unblock(G_OBJECT(s->stream_items[i]), s->ids[i]); } static void chapter_menu_set_num(gmerlin_t * g, chapter_menu_t * s, int num, int timescale) { int i; if(num > s->chapters_alloc) { s->chapter_items = realloc(s->chapter_items, num * sizeof(*s->chapter_items)); s->ids = realloc(s->ids, num * sizeof(*s->ids)); for(i = s->chapters_alloc; i < num; i++) s->chapter_items[i] = create_chapter_item(g, s, &s->ids[i]); s->chapters_alloc = num; } s->timescale = timescale; for(i = 0; i < num; i++) gtk_widget_show(s->chapter_items[i]); for(i = num; i < s->chapters_alloc; i++) gtk_widget_hide(s->chapter_items[i]); s->num_chapters = num; } void main_menu_set_audio_index(main_menu_t * m, int index) { stream_menu_set_index(&m->audio_stream_menu, index); } void main_menu_set_video_index(main_menu_t * m, int index) { stream_menu_set_index(&m->video_stream_menu, index); } void main_menu_set_subtitle_index(main_menu_t * m, int index) { stream_menu_set_index(&m->subtitle_stream_menu, index); } void main_menu_set_num_streams(main_menu_t * m, int audio_streams, int video_streams, int subtitle_streams) { stream_menu_set_num(m->g, &m->audio_stream_menu, audio_streams); stream_menu_set_num(m->g, &m->video_stream_menu, video_streams); stream_menu_set_num(m->g, &m->subtitle_stream_menu, subtitle_streams); } void main_menu_set_num_chapters(main_menu_t * m, int num, int timescale) { if(!num) gtk_widget_set_sensitive(m->chapter_item, 0); else gtk_widget_set_sensitive(m->chapter_item, 1); chapter_menu_set_num(m->g, &m->chapter_menu, num, timescale); } void main_menu_set_chapter_info(main_menu_t * m, int chapter, const char * name, gavl_time_t time) { char * label; char time_string[GAVL_TIME_STRING_LEN]; GtkWidget * w; gavl_time_prettyprint(gavl_time_unscale(m->chapter_menu.timescale, time), time_string); if(name) label = bg_sprintf("%s [%s]", name, time_string); else label = bg_sprintf(TR("Chapter %d [%s]"), chapter+1, time_string); w = m->chapter_menu.chapter_items[chapter]; gtk_label_set_text(GTK_LABEL(gtk_bin_get_child(GTK_BIN(w))), label); free(label); } void main_menu_chapter_changed(main_menu_t * m, int chapter) { GtkWidget * w; if(chapter >= m->chapter_menu.num_chapters) return; w = m->chapter_menu.chapter_items[chapter]; g_signal_handler_block(G_OBJECT(w), m->chapter_menu.ids[chapter]); gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(w), 1); g_signal_handler_unblock(G_OBJECT(w), m->chapter_menu.ids[chapter]); } void main_menu_set_audio_info(main_menu_t * m, int stream, const gavl_metadata_t * metadata) { char * label; GtkWidget * w; label = bg_get_stream_label(stream, metadata); w = m->audio_stream_menu.stream_items[stream]; gtk_label_set_text(GTK_LABEL(gtk_bin_get_child(GTK_BIN(w))), label); free(label); } void main_menu_set_video_info(main_menu_t * m, int stream, const gavl_metadata_t * metadata) { char * label; GtkWidget * w; label = bg_get_stream_label(stream, metadata); w = m->video_stream_menu.stream_items[stream]; gtk_label_set_text(GTK_LABEL(gtk_bin_get_child(GTK_BIN(w))), label); free(label); } void main_menu_set_subtitle_info(main_menu_t * m, int stream, const gavl_metadata_t * metadata) { char * label; GtkWidget * w; label = bg_get_stream_label(stream, metadata); w = m->subtitle_stream_menu.stream_items[stream]; gtk_label_set_text(GTK_LABEL(gtk_bin_get_child(GTK_BIN(w))), label); free(label); } main_menu_t * main_menu_create(gmerlin_t * gmerlin) { main_menu_t * ret; ret = calloc(1, sizeof(*ret)); ret->g = gmerlin; /* Windows */ ret->windows_menu.menu = create_menu(); ret->windows_menu.mediatree = create_toggle_item(TR("Media Tree"), gmerlin, ret->windows_menu.menu, &ret->windows_menu.mediatree_id); ret->windows_menu.infowindow = create_toggle_item(TR("Info window"), gmerlin, ret->windows_menu.menu, &ret->windows_menu.infowindow_id); ret->windows_menu.logwindow = create_toggle_item(TR("Log window"), gmerlin, ret->windows_menu.menu, &ret->windows_menu.logwindow_id); gtk_widget_show(ret->windows_menu.menu); /* Help */ ret->help_menu.menu = create_menu(); ret->help_menu.about = create_pixmap_item(TR("About..."), "about_16.png", gmerlin, ret->help_menu.menu); ret->help_menu.help = create_pixmap_item(TR("Userguide"), "help_16.png", gmerlin, ret->help_menu.menu); gtk_widget_show(ret->help_menu.menu); /* Streams */ stream_menu_init(&ret->audio_stream_menu, gmerlin, 1, 1, BG_PLUGIN_OUTPUT_AUDIO); stream_menu_init(&ret->video_stream_menu, gmerlin, 1, 1, BG_PLUGIN_OUTPUT_VIDEO); stream_menu_init(&ret->subtitle_stream_menu, gmerlin, 0, 0, BG_PLUGIN_NONE); /* Chapters */ ret->chapter_menu.menu = create_menu(); /* Visualization */ visualization_menu_init(&ret->visualization_menu, gmerlin); /* Options */ ret->options_menu.menu = create_menu(); ret->options_menu.preferences = create_pixmap_item(TR("Preferences..."), "config_16.png", gmerlin, ret->options_menu.menu); gtk_widget_add_accelerator(ret->options_menu.preferences, "activate", ret->g->accel_group, GDK_o, GDK_CONTROL_MASK, GTK_ACCEL_VISIBLE); ret->options_menu.skins = create_item(TR("Skins..."), gmerlin, ret->options_menu.menu); if(bg_search_file_exec("gmerlin_kbd_config", NULL)) ret->options_menu.kbd = create_item(TR("Multimedia keys..."), gmerlin, ret->options_menu.menu); /* Commands */ ret->command_menu.menu = create_menu(); ret->command_menu.seek_forward = create_item(TR("Seek forward"), gmerlin, ret->command_menu.menu); gtk_widget_add_accelerator(ret->command_menu.seek_forward, "activate", ret->g->accel_group, GDK_Right, GDK_CONTROL_MASK, GTK_ACCEL_VISIBLE); ret->command_menu.seek_backward = create_item(TR("Seek backward"), gmerlin, ret->command_menu.menu); gtk_widget_add_accelerator(ret->command_menu.seek_backward, "activate", ret->g->accel_group, GDK_Left, GDK_CONTROL_MASK, GTK_ACCEL_VISIBLE); ret->command_menu.inc_volume = create_item(TR("Increase volume"), gmerlin, ret->command_menu.menu); gtk_widget_add_accelerator(ret->command_menu.inc_volume, "activate", ret->g->accel_group, GDK_Right, GDK_SHIFT_MASK, GTK_ACCEL_VISIBLE); ret->command_menu.dec_volume = create_item(TR("Decrease volume"), gmerlin, ret->command_menu.menu); gtk_widget_add_accelerator(ret->command_menu.dec_volume, "activate", ret->g->accel_group, GDK_Left, GDK_SHIFT_MASK, GTK_ACCEL_VISIBLE); ret->command_menu.mute = create_item(TR("Toggle mute"), gmerlin, ret->command_menu.menu); gtk_widget_add_accelerator(ret->command_menu.mute, "activate", ret->g->accel_group, GDK_m, GDK_CONTROL_MASK, GTK_ACCEL_VISIBLE); ret->command_menu.next = create_item(TR("Next track"), gmerlin, ret->command_menu.menu); gtk_widget_add_accelerator(ret->command_menu.next, "activate", ret->g->accel_group, GDK_Page_Down, GDK_CONTROL_MASK, GTK_ACCEL_VISIBLE); ret->command_menu.previous = create_item(TR("Previous track"), gmerlin, ret->command_menu.menu); gtk_widget_add_accelerator(ret->command_menu.previous, "activate", ret->g->accel_group, GDK_Page_Up, GDK_CONTROL_MASK, GTK_ACCEL_VISIBLE); ret->command_menu.next_chapter = create_item(TR("Next chapter"), gmerlin, ret->command_menu.menu); gtk_widget_add_accelerator(ret->command_menu.next_chapter, "activate", ret->g->accel_group, GDK_Page_Down, GDK_SHIFT_MASK | GDK_CONTROL_MASK, GTK_ACCEL_VISIBLE); ret->command_menu.previous_chapter = create_item(TR("Previous chapter"), gmerlin, ret->command_menu.menu); gtk_widget_add_accelerator(ret->command_menu.previous_chapter, "activate", ret->g->accel_group, GDK_Page_Up, GDK_SHIFT_MASK | GDK_CONTROL_MASK, GTK_ACCEL_VISIBLE); ret->command_menu.goto_current = create_item(TR("Goto current track"), gmerlin, ret->command_menu.menu); gtk_widget_add_accelerator(ret->command_menu.goto_current, "activate", ret->g->accel_group, GDK_g, GDK_CONTROL_MASK, GTK_ACCEL_VISIBLE); ret->command_menu.current_to_favourites = create_item(TR("Copy current track to favourites"), gmerlin, ret->command_menu.menu); gtk_widget_add_accelerator(ret->command_menu.current_to_favourites, "activate", ret->g->accel_group, GDK_F9, 0, GTK_ACCEL_VISIBLE); ret->command_menu.seek_start = create_item(TR("Seek to start"), gmerlin, ret->command_menu.menu); gtk_widget_add_accelerator(ret->command_menu.seek_start, "activate", ret->g->player_window->accel_group, GDK_0, 0, GTK_ACCEL_VISIBLE); ret->command_menu.pause = create_item(TR("Pause"), gmerlin, ret->command_menu.menu); gtk_widget_add_accelerator(ret->command_menu.pause, "activate", ret->g->player_window->accel_group, GDK_space, 0, GTK_ACCEL_VISIBLE); ret->command_menu.quit = create_item(TR("Quit gmerlin"), gmerlin, ret->command_menu.menu); gtk_widget_add_accelerator(ret->command_menu.quit, "activate", ret->g->accel_group, GDK_q, GDK_CONTROL_MASK, GTK_ACCEL_VISIBLE); /* Accessories */ ret->accessories_menu.menu = create_menu(); if(bg_search_file_exec("gmerlin_transcoder", NULL)) ret->accessories_menu.transcoder = create_item(TR("Transcoder"), gmerlin, ret->accessories_menu.menu); if(bg_search_file_exec("gmerlin_visualizer", NULL)) ret->accessories_menu.visualizer = create_item(TR("Visualizer"), gmerlin, ret->accessories_menu.menu); if(bg_search_file_exec("gmerlin_alsamixer", NULL)) ret->accessories_menu.mixer = create_item(TR("Mixer"), gmerlin, ret->accessories_menu.menu); /* Main menu */ ret->menu = create_menu(); ret->audio_stream_item = create_submenu_item(TR("Audio..."), ret->audio_stream_menu.menu, ret->menu); ret->video_stream_item = create_submenu_item(TR("Video..."), ret->video_stream_menu.menu, ret->menu); ret->subtitle_stream_item = create_submenu_item(TR("Subtitles..."), ret->subtitle_stream_menu.menu, ret->menu); ret->chapter_item = create_submenu_item(TR("Chapters..."), ret->chapter_menu.menu, ret->menu); ret->visualization_item = create_submenu_item(TR("Visualization..."), ret->visualization_menu.menu, ret->menu); ret->windows_item = create_submenu_item(TR("Windows..."), ret->windows_menu.menu, ret->menu); ret->options_item = create_submenu_item(TR("Options..."), ret->options_menu.menu, ret->menu); ret->options_item = create_submenu_item(TR("Commands..."), ret->command_menu.menu, ret->menu); ret->accessories_item = create_submenu_item(TR("Accessories..."), ret->accessories_menu.menu, ret->menu); ret->help_item = create_submenu_item(TR("Help..."), ret->help_menu.menu, ret->menu); gtk_widget_show(ret->menu); return ret; } void main_menu_finalize(main_menu_t * ret, gmerlin_t * gmerlin) { /* Streams */ stream_menu_finalize(&ret->audio_stream_menu); stream_menu_finalize(&ret->video_stream_menu); stream_menu_finalize(&ret->subtitle_stream_menu); /* Visualization */ visualization_menu_finalize(&ret->visualization_menu, gmerlin); } void main_menu_destroy(main_menu_t * m) { plugin_menu_free(&m->audio_stream_menu.plugin_menu); plugin_menu_free(&m->video_stream_menu.plugin_menu); plugin_menu_free(&m->visualization_menu.plugin_menu); stream_menu_free(&m->audio_stream_menu); stream_menu_free(&m->video_stream_menu); stream_menu_free(&m->subtitle_stream_menu); free(m); } GtkWidget * main_menu_get_widget(main_menu_t * m) { return m->menu; } void main_menu_set_tree_window_item(main_menu_t * m, int state) { g_signal_handler_block(G_OBJECT(m->windows_menu.mediatree), m->windows_menu.mediatree_id); gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(m->windows_menu.mediatree), state); g_signal_handler_unblock(G_OBJECT(m->windows_menu.mediatree), m->windows_menu.mediatree_id); } void main_menu_set_info_window_item(main_menu_t * m, int state) { g_signal_handler_block(G_OBJECT(m->windows_menu.infowindow), m->windows_menu.infowindow_id); gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(m->windows_menu.infowindow), state); g_signal_handler_unblock(G_OBJECT(m->windows_menu.infowindow), m->windows_menu.infowindow_id); } void main_menu_set_log_window_item(main_menu_t * m, int state) { g_signal_handler_block(G_OBJECT(m->windows_menu.logwindow), m->windows_menu.logwindow_id); gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(m->windows_menu.logwindow), state); g_signal_handler_unblock(G_OBJECT(m->windows_menu.logwindow), m->windows_menu.logwindow_id); } gmerlin-1.2.0~dfsg/apps/player/display.c0000644000175000017500000006133511764363403020160 0ustar alessioalessio/***************************************************************** * gmerlin - a general purpose multimedia framework and applications * * Copyright (c) 2001 - 2011 Members of the Gmerlin project * gmerlin-general@lists.sourceforge.net * http://gmerlin.sourceforge.net * * 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 of the License, 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 this program. If not, see . * *****************************************************************/ #include #include #include #include "gmerlin.h" #include #include #include #include #include #include #include #define STATE_STOPPED 0 #define STATE_PLAYING 1 #define STATE_PAUSED 2 #define STATE_CHANGING 3 #define STATE_SEEKING 4 #define STATE_BUFFERING_1 5 #define STATE_BUFFERING_2 6 #define STATE_BUFFERING_3 7 #define STATE_BUFFERING_4 8 #define STATE_BUFFERING_5 9 #define STATE_ERROR 10 #define STATE_MUTE 11 #define NUM_STATES 12 #define DIGIT_HEIGHT 32 #define DIGIT_WIDTH 20 typedef enum { DISPLAY_MODE_NONE, DISPLAY_MODE_ALL, DISPLAY_MODE_REM, DISPLAY_MODE_ALL_REM, NUM_DISPLAY_MODES } display_mode_t; /* Mode for the time display */ static const bg_parameter_info_t parameters[] = { { .name = "get_colors_from_skin", .long_name = TRS("Get colors from skin"), .type = BG_PARAMETER_CHECKBUTTON, .val_default = { .val_i = 1 }, .help_string = TRS("Take the display colors from the skin definition") }, { .name = "background", .long_name = TRS("Background"), .type = BG_PARAMETER_COLOR_RGB, .val_default = { .val_color = { 0.0, 0.0, 0.0, 1.0 } }, }, { .name = "foreground_normal", .long_name = TRS("Normal foreground"), .type = BG_PARAMETER_COLOR_RGB, .val_default = { .val_color = { 1.0, 0.5, 0.0, 1.0 } }, }, { .name = "foreground_error", .long_name = TRS("Error foreground"), .type = BG_PARAMETER_COLOR_RGB, .val_default = { .val_color = { 1.0, 0.0, 0.0, 1.0 } }, }, { .name = "display_mode", .long_name = TRS("Display mode"), .type = BG_PARAMETER_INT, .flags = BG_PARAMETER_HIDE_DIALOG, .val_min = { .val_i = DISPLAY_MODE_NONE }, .val_max = { .val_i = NUM_DISPLAY_MODES - 1 }, .val_default = { .val_i = DISPLAY_MODE_NONE }, }, { .name = "repeat_mode", .long_name = TRS("Repeat mode"), .type = BG_PARAMETER_INT, .flags = BG_PARAMETER_HIDE_DIALOG, .val_min = { .val_i = REPEAT_MODE_NONE }, .val_max = { .val_i = NUM_REPEAT_MODES - 1 }, .val_default = { .val_i = REPEAT_MODE_NONE }, }, { .name = "font", .long_name = TRS("Font"), .type = BG_PARAMETER_FONT, .val_default = { .val_str = "Sans-10:slant=0:weight=200:width=100" }, }, { /* End of parameters */ } }; const bg_parameter_info_t * display_get_parameters(display_t * display) { return parameters; } int pixbufs_loaded = 0; GdkPixbuf * state_pixbufs[NUM_STATES]; GdkPixbuf * repeat_pixbufs[NUM_REPEAT_MODES]; GdkPixbuf * display_pixbufs[NUM_DISPLAY_MODES]; static GdkPixbuf * load_pixbuf(const char * filename) { char * tmp_string; GdkPixbuf * ret; tmp_string = bg_search_file_read("icons", filename); ret = gdk_pixbuf_new_from_file(tmp_string, NULL); free(tmp_string); return ret; } static void load_pixbufs() { if(pixbufs_loaded) return; state_pixbufs[STATE_STOPPED] = load_pixbuf("state_stopped.png"); state_pixbufs[STATE_PLAYING] = load_pixbuf("state_playing.png"); state_pixbufs[STATE_PAUSED] = load_pixbuf("state_paused.png"); state_pixbufs[STATE_CHANGING] = load_pixbuf("state_changing.png"); state_pixbufs[STATE_SEEKING] = load_pixbuf("state_seeking.png"); state_pixbufs[STATE_BUFFERING_1] = load_pixbuf("state_buffering_1.png"); state_pixbufs[STATE_BUFFERING_2] = load_pixbuf("state_buffering_2.png"); state_pixbufs[STATE_BUFFERING_3] = load_pixbuf("state_buffering_3.png"); state_pixbufs[STATE_BUFFERING_4] = load_pixbuf("state_buffering_4.png"); state_pixbufs[STATE_BUFFERING_5] = load_pixbuf("state_buffering_5.png"); state_pixbufs[STATE_ERROR] = load_pixbuf("state_error.png"); state_pixbufs[STATE_MUTE] = load_pixbuf("state_mute.png"); repeat_pixbufs[REPEAT_MODE_NONE] = load_pixbuf("repeat_mode_none.png"); repeat_pixbufs[REPEAT_MODE_ALL] = load_pixbuf("repeat_mode_all.png"); repeat_pixbufs[REPEAT_MODE_1] = load_pixbuf("repeat_mode_1.png"); display_pixbufs[DISPLAY_MODE_NONE] = load_pixbuf("display_mode_none.png"); display_pixbufs[DISPLAY_MODE_REM] = load_pixbuf("display_mode_rem.png"); display_pixbufs[DISPLAY_MODE_ALL] = load_pixbuf("display_mode_all.png"); display_pixbufs[DISPLAY_MODE_ALL_REM] = load_pixbuf("display_mode_all_rem.png"); pixbufs_loaded = 1; } struct display_s { bg_gtk_time_display_t * time_display; bg_gtk_scrolltext_t * scrolltext; GtkWidget * widget; GtkWidget * state_area; GtkWidget * repeat_area; GtkWidget * display_area; GdkGC * gc; GdkPixbuf * state_pixbufs[NUM_STATES]; GdkPixbuf * repeat_pixbufs[NUM_REPEAT_MODES]; GdkPixbuf * display_pixbufs[NUM_DISPLAY_MODES]; float foreground_error[3]; float foreground_normal[3]; float background[3]; /* From the config file */ float foreground_error_cfg[3]; float foreground_normal_cfg[3]; float background_cfg[3]; int get_colors_from_skin; gmerlin_t * gmerlin; repeat_mode_t repeat_mode; display_mode_t display_mode; int state_index; int state; float buffer_percentage; display_skin_t * skin; int error_active; char * track_name; gavl_time_t duration_before; gavl_time_t duration_after; gavl_time_t duration_current; gavl_time_t last_time; guint32 last_click_time; int mute; char * error_msg; }; static void update_background(display_t * d) { GdkColor col; col.red = (guint16)(d->background[0] * 65535.0); col.green = (guint16)(d->background[1] * 65535.0); col.blue = (guint16)(d->background[2] * 65535.0); col.pixel = ((col.red >> 8) << 16) | ((col.green >> 8) << 8) | ((col.blue >> 8)); gdk_color_alloc(gdk_window_get_colormap(d->widget->window), &col); gdk_gc_set_foreground(d->gc, &col); gdk_window_clear_area_e(GTK_LAYOUT(d->widget)->bin_window, 0, 0, DISPLAY_WIDTH, DISPLAY_HEIGHT); } static void update_colors(display_t * d) { int i; for(i = 0; i < NUM_STATES; i++) { if(d->state_pixbufs[i]) g_object_unref(G_OBJECT(d->state_pixbufs[i])); d->state_pixbufs[i] = bg_gtk_pixbuf_scale_alpha(state_pixbufs[i], 20, 32, d->foreground_normal, d->background); } for(i = 0; i < NUM_REPEAT_MODES; i++) { if(d->repeat_pixbufs[i]) g_object_unref(G_OBJECT(d->repeat_pixbufs[i])); d->repeat_pixbufs[i] = bg_gtk_pixbuf_scale_alpha(repeat_pixbufs[i], 40, 16, d->foreground_normal, d->background); } for(i = 0; i < NUM_DISPLAY_MODES; i++) { if(d->display_pixbufs[i]) g_object_unref(G_OBJECT(d->display_pixbufs[i])); d->display_pixbufs[i] = bg_gtk_pixbuf_scale_alpha(display_pixbufs[i], 40, 16, d->foreground_normal, d->background); } if(d->state_area->window) gdk_window_clear_area_e(d->state_area->window, 0, 0, 20, 32); if(d->repeat_area->window) gdk_window_clear_area_e(d->repeat_area->window, 0, 0, 40, 16); if(d->display_area->window) gdk_window_clear_area_e(d->display_area->window, 0, 0, 40, 16); if(d->error_active) bg_gtk_scrolltext_set_colors(d->scrolltext, d->foreground_error, d->background); else bg_gtk_scrolltext_set_colors(d->scrolltext, d->foreground_normal, d->background); bg_gtk_time_display_set_colors(d->time_display, d->foreground_normal, d->background); if(d->gc) update_background(d); } static gboolean expose_callback(GtkWidget * w, GdkEventExpose * evt, gpointer data) { display_t * d = (display_t*)data; if(!d->gc) return TRUE; if(w == d->widget) { gdk_draw_rectangle(GTK_LAYOUT(d->widget)->bin_window, d->gc, TRUE, 0, 0, DISPLAY_WIDTH, DISPLAY_HEIGHT); } if(w == d->state_area) { gdk_draw_pixbuf(d->state_area->window, NULL, d->state_pixbufs[d->state_index], 0, // gint src_x, 0, // gint src_y, 0, // gint dest_x, 0, // gint dest_y, -1, // gint width, -1, // gint height, GDK_RGB_DITHER_NONE, // GdkRgbDither dither, 0, // gint x_dither, 0 // gint y_dither ); } if(w == d->repeat_area) { gdk_draw_pixbuf(d->repeat_area->window, NULL, d->repeat_pixbufs[d->repeat_mode], 0, // gint src_x, 0, // gint src_y, 0, // gint dest_x, 0, // gint dest_y, -1, // gint width, -1, // gint height, GDK_RGB_DITHER_NONE, // GdkRgbDither dither, 0, // gint x_dither, 0 // gint y_dither ); } if(w == d->display_area) { gdk_draw_pixbuf(d->display_area->window, NULL, d->display_pixbufs[d->display_mode], 0, // gint src_x, 0, // gint src_y, 0, // gint dest_x, 0, // gint dest_y, -1, // gint width, -1, // gint height, GDK_RGB_DITHER_NONE, // GdkRgbDither dither, 0, // gint x_dither, 0 // gint y_dither ); } return TRUE; } static void set_display_mode(display_t * d) { if(d->display_mode == NUM_DISPLAY_MODES) d->display_mode = 0; expose_callback(d->display_area, NULL, d); display_set_time(d, d->last_time); } static void set_repeat_mode(display_t * d) { if(d->repeat_mode == NUM_REPEAT_MODES) d->repeat_mode = 0; expose_callback(d->repeat_area, NULL, d); d->gmerlin->repeat_mode = d->repeat_mode; } void display_set_parameter(void * data, const char * name, const bg_parameter_value_t * v) { display_t * d = (display_t*)data; if(!name) { if(d->get_colors_from_skin && d->skin) { memcpy(d->foreground_normal, d->skin->foreground_normal, 3 * sizeof(float)); memcpy(d->foreground_error, d->skin->foreground_error, 3 * sizeof(float)); memcpy(d->background, d->skin->background, 3 * sizeof(float)); update_colors(d); } else { memcpy(d->foreground_normal, d->foreground_normal_cfg, 3 * sizeof(float)); memcpy(d->foreground_error, d->foreground_error_cfg, 3 * sizeof(float)); memcpy(d->background, d->background_cfg, 3 * sizeof(float)); update_colors(d); } } else if(!strcmp(name, "get_colors_from_skin")) d->get_colors_from_skin = v->val_i; else if(!strcmp(name, "foreground_error")) memcpy(d->foreground_error_cfg, v->val_color, 3 * sizeof(float)); else if(!strcmp(name, "foreground_normal")) memcpy(d->foreground_normal_cfg, v->val_color, 3 * sizeof(float)); else if(!strcmp(name, "background")) memcpy(d->background_cfg, v->val_color, 3 * sizeof(float)); else if(!strcmp(name, "display_mode")) { d->display_mode = v->val_i; set_display_mode(d); } else if(!strcmp(name, "repeat_mode")) { d->repeat_mode = v->val_i; set_repeat_mode(d); } else if(!strcmp(name, "font")) { bg_gtk_scrolltext_set_font(d->scrolltext, v->val_str); } } int display_get_parameter(void * data, const char * name, bg_parameter_value_t * v) { display_t * d = (display_t*)data; if(!strcmp(name, "display_mode")) { v->val_i = d->display_mode; return 1; } else if(!strcmp(name, "repeat_mode")) { v->val_i = d->repeat_mode; return 1; } return 0; } static void realize_callback(GtkWidget * w, gpointer data) { display_t * d = (display_t*)data; d->gc = gdk_gc_new(d->widget->window); update_background(d); } static gboolean button_press_callback(GtkWidget * w, GdkEventButton * evt, gpointer data) { display_t * d = (display_t*)data; if(evt->time == d->last_click_time) return FALSE; if(w == d->repeat_area) { d->repeat_mode++; set_repeat_mode(d); d->last_click_time = evt->time; return TRUE; } else if(w == d->display_area) { d->display_mode++; set_display_mode(d); d->last_click_time = evt->time; return TRUE; } return FALSE; } display_t * display_create(gmerlin_t * gmerlin) { display_t * ret; bg_cfg_section_t * cfg_section; load_pixbufs(); ret = calloc(1, sizeof(*ret)); /* Create objects */ ret->gmerlin = gmerlin; ret->widget = gtk_layout_new(NULL, NULL); g_signal_connect(G_OBJECT(ret->widget), "expose_event", G_CALLBACK(expose_callback), (gpointer)ret); g_signal_connect(G_OBJECT(ret->widget), "realize", G_CALLBACK(realize_callback), (gpointer)ret); ret->state_index = STATE_STOPPED; ret->scrolltext = bg_gtk_scrolltext_create(226, 18); /* State area */ ret->state_area = gtk_drawing_area_new(); gtk_widget_set_size_request(ret->state_area, 20, 32); g_signal_connect(G_OBJECT(ret->state_area), "expose_event", G_CALLBACK(expose_callback), (gpointer)ret); gtk_widget_show(ret->state_area); /* Repeat area */ ret->repeat_area = gtk_drawing_area_new(); gtk_widget_set_size_request(ret->repeat_area, 40, 16); gtk_widget_set_events(ret->repeat_area, GDK_BUTTON_PRESS_MASK | GDK_ENTER_NOTIFY_MASK | GDK_LEAVE_NOTIFY_MASK); bg_gtk_tooltips_set_tip(ret->repeat_area, "Repeat mode\nClick to change", PACKAGE); g_signal_connect(G_OBJECT(ret->repeat_area), "button_press_event", G_CALLBACK (button_press_callback), ret); g_signal_connect(G_OBJECT(ret->repeat_area), "expose_event", G_CALLBACK(expose_callback), (gpointer)ret); gtk_widget_show(ret->repeat_area); /* Display mode area */ ret->display_area = gtk_drawing_area_new(); gtk_widget_set_size_request(ret->display_area, 40, 16); gtk_widget_set_events(ret->display_area, GDK_BUTTON_PRESS_MASK | GDK_ENTER_NOTIFY_MASK | GDK_LEAVE_NOTIFY_MASK); bg_gtk_tooltips_set_tip(ret->display_area, "Time display mode\nClick to change", PACKAGE); g_signal_connect(G_OBJECT(ret->display_area), "button_press_event", G_CALLBACK (button_press_callback), ret); g_signal_connect(G_OBJECT(ret->display_area), "expose_event", G_CALLBACK(expose_callback), (gpointer)ret); gtk_widget_show(ret->display_area); /* Scrolltext */ bg_gtk_scrolltext_set_font(ret->scrolltext, "Sans Bold 10"); ret->time_display = bg_gtk_time_display_create(BG_GTK_DISPLAY_SIZE_NORMAL, 0, BG_GTK_DISPLAY_MODE_HMS); /* Set attributes */ gtk_widget_set_size_request(ret->widget, DISPLAY_WIDTH, DISPLAY_HEIGHT); /* Set Callbacks */ /* Pack */ gtk_layout_put(GTK_LAYOUT(ret->widget), bg_gtk_scrolltext_get_widget(ret->scrolltext), 3, 38); gtk_layout_put(GTK_LAYOUT(ret->widget), ret->state_area, 3, 3); gtk_layout_put(GTK_LAYOUT(ret->widget), ret->display_area, 189, 3); gtk_layout_put(GTK_LAYOUT(ret->widget), ret->repeat_area, 189, 19); gtk_layout_put(GTK_LAYOUT(ret->widget), bg_gtk_time_display_get_widget(ret->time_display), 26, 3); gtk_widget_show(ret->widget); cfg_section = bg_cfg_registry_find_section(gmerlin->cfg_reg, "Display"); return ret; } GtkWidget * display_get_widget(display_t * d) { return d->widget; } void display_destroy(display_t * d) { if(d->error_msg) free(d->error_msg); bg_gtk_time_display_destroy(d->time_display); bg_gtk_scrolltext_destroy(d->scrolltext); free(d); } void display_set_playlist_times(display_t * d, gavl_time_t duration_before, gavl_time_t duration_current, gavl_time_t duration_after) { d->duration_before = duration_before; d->duration_current = duration_current; d->duration_after = duration_after; } void display_set_time(display_t * d, gavl_time_t time) { gavl_time_t display_time; d->last_time = time; if(d->state_index == STATE_STOPPED) display_time = d->duration_current + d->duration_before + d->duration_after; else { switch(d->display_mode) { case DISPLAY_MODE_NONE: display_time = time; break; case DISPLAY_MODE_ALL: if(d->duration_before == GAVL_TIME_UNDEFINED) display_time = GAVL_TIME_UNDEFINED; else display_time = time + d->duration_before; break; case DISPLAY_MODE_REM: if(d->duration_current == GAVL_TIME_UNDEFINED) display_time = GAVL_TIME_UNDEFINED; else display_time = d->duration_current - time; break; case DISPLAY_MODE_ALL_REM: if((d->duration_current == GAVL_TIME_UNDEFINED) || (d->duration_after == GAVL_TIME_UNDEFINED)) display_time = GAVL_TIME_UNDEFINED; else display_time = d->duration_after + d->duration_current - time; break; default: display_time = time; break; } } bg_gtk_time_display_update(d->time_display, display_time, BG_GTK_DISPLAY_MODE_HMS); } static void update_state(display_t * d) { switch(d->state) { case BG_PLAYER_STATE_STOPPED: d->state_index = STATE_STOPPED; display_set_track_name(d, "Gmerlin player (version "VERSION")"); bg_gtk_time_display_update(d->time_display, d->duration_before+d->duration_current+ d->duration_after, BG_GTK_DISPLAY_MODE_HMS); break; case BG_PLAYER_STATE_SEEKING: d->state_index = STATE_SEEKING; break; case BG_PLAYER_STATE_CHANGING: case BG_PLAYER_STATE_STARTING: d->state_index = STATE_CHANGING; break; case BG_PLAYER_STATE_BUFFERING: if((d->state_index != STATE_BUFFERING_5) && (d->state_index != STATE_BUFFERING_4) && (d->state_index != STATE_BUFFERING_3) && (d->state_index != STATE_BUFFERING_2) && (d->state_index != STATE_BUFFERING_1)) { bg_gtk_scrolltext_set_text(d->scrolltext, "Buffering...", d->foreground_normal, d->background); } if(d->buffer_percentage > 0.8) d->state_index = STATE_BUFFERING_5; else if(d->buffer_percentage > 0.6) d->state_index = STATE_BUFFERING_4; else if(d->buffer_percentage > 0.4) d->state_index = STATE_BUFFERING_3; else if(d->buffer_percentage > 0.2) d->state_index = STATE_BUFFERING_2; else d->state_index = STATE_BUFFERING_1; break; case BG_PLAYER_STATE_PAUSED: d->state_index = STATE_PAUSED; break; case BG_PLAYER_STATE_ERROR: d->state_index = STATE_ERROR; bg_gtk_scrolltext_set_text(d->scrolltext, d->error_msg, d->foreground_error, d->background); break; default: /* BG_PLAYER_STATE_PLAYING */ if(d->state_index != STATE_PLAYING) bg_gtk_scrolltext_set_text(d->scrolltext, d->track_name, d->foreground_normal, d->background); if(d->mute) d->state_index = STATE_MUTE; else d->state_index = STATE_PLAYING; break; } expose_callback(d->state_area, NULL, d); } void display_set_state(display_t * d, int state, const void * arg) { switch(state) { case BG_PLAYER_STATE_BUFFERING: d->buffer_percentage = *((float*)arg); break; case BG_PLAYER_STATE_ERROR: d->error_msg = bg_strdup(d->error_msg, (char*)arg); break; default: /* BG_PLAYER_STATE_PLAYING */ break; } d->state = state; update_state(d); } void display_set_mute(display_t * d, int mute) { d->mute = mute; update_state(d); } void display_skin_load(display_skin_t * s, xmlDocPtr doc, xmlNodePtr node) { char * tmp_string; char * rest; char * pos; char * old_locale; node = node->children; old_locale = setlocale(LC_NUMERIC, "C"); while(node) { if(!node->name) { node = node->next; continue; } tmp_string = (char*)xmlNodeListGetString(doc, node->children, 1); if(!BG_XML_STRCMP(node->name, "X")) s->x = atoi(tmp_string); else if(!BG_XML_STRCMP(node->name, "Y")) s->y = atoi(tmp_string); else if(!BG_XML_STRCMP(node->name, "BACKGROUND")) { pos = tmp_string; s->background[0] = strtod(pos, &rest); pos = rest; s->background[1] = strtod(pos, &rest); pos = rest; s->background[2] = strtod(pos, &rest); } else if(!BG_XML_STRCMP(node->name, "FOREGROUND_NORMAL")) { pos = tmp_string; s->foreground_normal[0] = strtod(pos, &rest); pos = rest; s->foreground_normal[1] = strtod(pos, &rest); pos = rest; s->foreground_normal[2] = strtod(pos, &rest); } else if(!BG_XML_STRCMP(node->name, "FOREGROUND_ERROR")) { pos = tmp_string; s->foreground_error[0] = strtod(pos, &rest); pos = rest; s->foreground_error[1] = strtod(pos, &rest); pos = rest; s->foreground_error[2] = strtod(pos, &rest); } node = node->next; xmlFree(tmp_string); } setlocale(LC_NUMERIC, old_locale); } void display_set_skin(display_t * d, display_skin_t * s) { d->skin = s; if(d->get_colors_from_skin) { memcpy(d->foreground_normal, d->skin->foreground_normal, 3 * sizeof(float)); memcpy(d->foreground_error, d->skin->foreground_error, 3 * sizeof(float)); memcpy(d->background, d->skin->background, 3 * sizeof(float)); update_colors(d); } } void display_get_coords(display_t * d, int * x, int * y) { *x = d->skin->x; *y = d->skin->y; } void display_set_track_name(display_t * d, char * name) { d->track_name = bg_strdup(d->track_name, name); d->error_active = 0; bg_gtk_scrolltext_set_text(d->scrolltext, d->track_name, d->foreground_normal, d->background); } void display_set_error_msg(display_t * d, char * msg) { d->error_active = 1; bg_gtk_scrolltext_set_text(d->scrolltext, msg, d->foreground_error, d->background); } gmerlin-1.2.0~dfsg/apps/player/playerwindow.c0000644000175000017500000007337011764363403021241 0ustar alessioalessio/***************************************************************** * gmerlin - a general purpose multimedia framework and applications * * Copyright (c) 2001 - 2011 Members of the Gmerlin project * gmerlin-general@lists.sourceforge.net * http://gmerlin.sourceforge.net * * 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 of the License, 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 this program. If not, see . * *****************************************************************/ #include #include #include #include #include "gmerlin.h" #include #include #include #include #define DELAY_TIME 10 #define BACKGROUND_WINDOW GTK_LAYOUT(win->layout)->bin_window // #define MASK_WINDOW win->window->window #define BACKGROUND_WIDGET win->layout #define MASK_WIDGET win->window static void set_background(player_window_t * win) { GdkBitmap * mask; GdkPixmap * pixmap; int width, height; GdkPixbuf * pixbuf; if(win->mouse_inside) pixbuf = win->background_pixbuf_highlight; else pixbuf = win->background_pixbuf; if(!pixbuf) return; width = gdk_pixbuf_get_width(pixbuf); height = gdk_pixbuf_get_height(pixbuf); gtk_widget_set_size_request(win->window, width, height); // gtk_window_resize(GTK_WINDOW(win->window), width, height); bg_gdk_pixbuf_render_pixmap_and_mask(pixbuf, &pixmap, &mask); if(pixmap) bg_gtk_set_widget_bg_pixmap(win->layout, pixmap); gtk_widget_shape_combine_mask(win->window, mask, 0, 0); if(mask) { g_object_unref(G_OBJECT(mask)); } if(BACKGROUND_WINDOW) gdk_window_clear_area_e(BACKGROUND_WINDOW, 0, 0, width, height); gdk_display_sync(gdk_display_get_default()); while(gdk_events_pending() || gtk_events_pending()) gtk_main_iteration(); } void player_window_set_skin(player_window_t * win, player_window_skin_t * s, const char * directory) { int x, y; char * tmp_path; if(win->background_pixbuf) g_object_unref(G_OBJECT(win->background_pixbuf)); tmp_path = bg_sprintf("%s/%s", directory, s->background); win->background_pixbuf = gdk_pixbuf_new_from_file(tmp_path, NULL); free(tmp_path); if(s->background_highlight) { tmp_path = bg_sprintf("%s/%s", directory, s->background_highlight); win->background_pixbuf_highlight = gdk_pixbuf_new_from_file(tmp_path, NULL); free(tmp_path); } set_background(win); /* Apply the button skins */ bg_gtk_button_set_skin(win->play_button, &s->play_button, directory); bg_gtk_button_get_coords(win->play_button, &x, &y); gtk_layout_move(GTK_LAYOUT(win->layout), bg_gtk_button_get_widget(win->play_button), x, y); bg_gtk_button_set_skin(win->stop_button, &s->stop_button, directory); bg_gtk_button_get_coords(win->stop_button, &x, &y); gtk_layout_move(GTK_LAYOUT(win->layout), bg_gtk_button_get_widget(win->stop_button), x, y); bg_gtk_button_set_skin(win->pause_button, &s->pause_button, directory); bg_gtk_button_get_coords(win->pause_button, &x, &y); gtk_layout_move(GTK_LAYOUT(win->layout), bg_gtk_button_get_widget(win->pause_button), x, y); bg_gtk_button_set_skin(win->next_button, &s->next_button, directory); bg_gtk_button_get_coords(win->next_button, &x, &y); gtk_layout_move(GTK_LAYOUT(win->layout), bg_gtk_button_get_widget(win->next_button), x, y); bg_gtk_button_set_skin(win->prev_button, &s->prev_button, directory); bg_gtk_button_get_coords(win->prev_button, &x, &y); gtk_layout_move(GTK_LAYOUT(win->layout), bg_gtk_button_get_widget(win->prev_button), x, y); bg_gtk_button_set_skin(win->close_button, &s->close_button, directory); bg_gtk_button_get_coords(win->close_button, &x, &y); gtk_layout_move(GTK_LAYOUT(win->layout), bg_gtk_button_get_widget(win->close_button), x, y); bg_gtk_button_set_skin(win->menu_button, &s->menu_button, directory); bg_gtk_button_get_coords(win->menu_button, &x, &y); gtk_layout_move(GTK_LAYOUT(win->layout), bg_gtk_button_get_widget(win->menu_button), x, y); /* Apply slider skins */ bg_gtk_slider_set_skin(win->seek_slider, &s->seek_slider, directory); bg_gtk_slider_get_coords(win->seek_slider, &x, &y); gtk_layout_move(GTK_LAYOUT(win->layout), bg_gtk_slider_get_widget(win->seek_slider), x, y); bg_gtk_slider_set_skin(win->volume_slider, &s->volume_slider, directory); bg_gtk_slider_get_coords(win->volume_slider, &x, &y); gtk_layout_move(GTK_LAYOUT(win->layout), bg_gtk_slider_get_widget(win->volume_slider), x, y); /* Apply display skin */ display_set_skin(win->display, &s->display); display_get_coords(win->display, &x, &y); gtk_layout_move(GTK_LAYOUT(win->layout), display_get_widget(win->display), x, y); /* Update slider positions */ bg_gtk_slider_set_pos(win->volume_slider, (win->volume - BG_PLAYER_VOLUME_MIN)/ (-BG_PLAYER_VOLUME_MIN)); } /* Gtk Callbacks */ static void realize_callback(GtkWidget * w, gpointer data) { player_window_t * win; win = (player_window_t*)data; set_background(win); } static gboolean button_press_callback(GtkWidget * w, GdkEventButton * evt, gpointer data) { player_window_t * win; win = (player_window_t*)data; win->mouse_x = (int)(evt->x); win->mouse_y = (int)(evt->y); return TRUE; } static gboolean motion_callback(GtkWidget * w, GdkEventMotion * evt, gpointer data) { player_window_t * win; /* Buggy (newer) gtk versions send motion events even if no button is pressed */ if(!(evt->state & (GDK_BUTTON1_MASK|GDK_BUTTON2_MASK|GDK_BUTTON3_MASK))) return TRUE; win = (player_window_t*)data; gtk_window_move(GTK_WINDOW(win->window), (int)(evt->x_root) - win->mouse_x, (int)(evt->y_root) - win->mouse_y); win->window_x = (int)(evt->x_root - evt->x); win->window_y = (int)(evt->y_root - evt->y); return TRUE; } /* Gmerlin callbacks */ static void seek_change_callback(bg_gtk_slider_t * slider, float perc, void * data) { gavl_time_t time; player_window_t * win = (player_window_t *)data; time = (gavl_time_t)(perc * (double)win->duration); if(!win->seek_active) { if(win->gmerlin->player_state == BG_PLAYER_STATE_PAUSED) win->seek_active = 2; else { win->seek_active = 1; bg_player_pause(win->gmerlin->player); } } // player_window_t * win = (player_window_t *)data; bg_player_seek(win->gmerlin->player, time, GAVL_TIME_SCALE); display_set_time(win->display, time); } static void seek_release_callback(bg_gtk_slider_t * slider, float perc, void * data) { gavl_time_t time; player_window_t * win = (player_window_t *)data; time = (gavl_time_t)(perc * (double)win->duration); // player_window_t * win = (player_window_t *)data; bg_player_seek(win->gmerlin->player, time, GAVL_TIME_SCALE); if(win->seek_active == 1) bg_player_pause(win->gmerlin->player); } static void slider_scroll_callback(bg_gtk_slider_t * slider, int up, void * data) { player_window_t * win = (player_window_t *)data; if(slider == win->volume_slider) { if(up) bg_player_set_volume_rel(win->gmerlin->player, 1.0); else bg_player_set_volume_rel(win->gmerlin->player, -1.0); } else if(slider == win->seek_slider) { if(up) bg_player_seek_rel(win->gmerlin->player, 2 * GAVL_TIME_SCALE); else bg_player_seek_rel(win->gmerlin->player, -2 * GAVL_TIME_SCALE); } } static void volume_change_callback(bg_gtk_slider_t * slider, float perc, void * data) { float volume; player_window_t * win = (player_window_t *)data; volume = BG_PLAYER_VOLUME_MIN - BG_PLAYER_VOLUME_MIN * perc; if(volume > 0.0) volume = 0.0; bg_player_set_volume(win->gmerlin->player, volume); win->volume = volume; } static void gmerlin_button_callback_2(bg_gtk_button_t * b, void * data) { player_window_t * win = (player_window_t *)data; if(b == win->next_button) { bg_player_next_chapter(win->gmerlin->player); } else if(b == win->prev_button) { bg_player_prev_chapter(win->gmerlin->player); } } static void gmerlin_button_callback(bg_gtk_button_t * b, void * data) { player_window_t * win = (player_window_t *)data; if(b == win->play_button) { gmerlin_play(win->gmerlin, BG_PLAY_FLAG_IGNORE_IF_PLAYING | BG_PLAY_FLAG_RESUME); } else if(b == win->pause_button) { gmerlin_pause(win->gmerlin); } else if(b == win->stop_button) { bg_player_stop(win->gmerlin->player); } else if(b == win->next_button) { bg_media_tree_next(win->gmerlin->tree, 1, win->gmerlin->shuffle_mode); gmerlin_play(win->gmerlin, BG_PLAY_FLAG_IGNORE_IF_STOPPED); } else if(b == win->prev_button) { bg_media_tree_previous(win->gmerlin->tree, 1, win->gmerlin->shuffle_mode); gmerlin_play(win->gmerlin, BG_PLAY_FLAG_IGNORE_IF_STOPPED); } else if(b == win->close_button) { gtk_main_quit(); } } static gboolean do_configure(gpointer data) { gmerlin_t * gmerlin; gmerlin = (gmerlin_t*)data; gmerlin_configure(gmerlin); return FALSE; } static void handle_message(player_window_t * win, bg_msg_t * msg) { int id; int arg_i_1; int arg_i_2; int arg_i_3; float arg_f_1; char * arg_str_1; gavl_time_t time; id = bg_msg_get_id(msg); switch(id) { case BG_PLAYER_MSG_TIME_CHANGED: if(!win->seek_active) { time = bg_msg_get_arg_time(msg, 0); display_set_time(win->display, time); if(win->duration != GAVL_TIME_UNDEFINED) bg_gtk_slider_set_pos(win->seek_slider, (float)(time) / (float)(win->duration)); win->gmerlin->remote_data.time = time; } break; case BG_PLAYER_MSG_VOLUME_CHANGED: arg_f_1 = bg_msg_get_arg_float(msg, 0); bg_gtk_slider_set_pos(win->volume_slider, (arg_f_1 - BG_PLAYER_VOLUME_MIN) / (- BG_PLAYER_VOLUME_MIN)); break; case BG_PLAYER_MSG_TRACK_CHANGED: arg_i_1 = bg_msg_get_arg_int(msg, 0); gmerlin_check_next_track(win->gmerlin, arg_i_1); break; case BG_PLAYER_MSG_MUTE: arg_i_1 = bg_msg_get_arg_int(msg, 0); display_set_mute(win->display, arg_i_1); break; case BG_PLAYER_MSG_STATE_CHANGED: win->gmerlin->player_state = bg_msg_get_arg_int(msg, 0); switch(win->gmerlin->player_state) { case BG_PLAYER_STATE_PAUSED: display_set_state(win->display, win->gmerlin->player_state, NULL); break; case BG_PLAYER_STATE_SEEKING: display_set_state(win->display, win->gmerlin->player_state, NULL); break; case BG_PLAYER_STATE_ERROR: bg_gtk_log_window_flush(win->gmerlin->log_window); display_set_state(win->display, win->gmerlin->player_state, bg_gtk_log_window_last_error(win->gmerlin->log_window)); break; case BG_PLAYER_STATE_BUFFERING: arg_f_1 = bg_msg_get_arg_float(msg, 1); display_set_state(win->display, win->gmerlin->player_state, &arg_f_1); break; case BG_PLAYER_STATE_PLAYING: display_set_state(win->display, win->gmerlin->player_state, NULL); bg_media_tree_mark_error(win->gmerlin->tree, 0); win->seek_active = 0; break; case BG_PLAYER_STATE_STOPPED: bg_gtk_slider_set_state(win->seek_slider, BG_GTK_SLIDER_INACTIVE); display_set_state(win->display, win->gmerlin->player_state, NULL); break; case BG_PLAYER_STATE_CHANGING: arg_i_2 = bg_msg_get_arg_int(msg, 1); display_set_state(win->display, win->gmerlin->player_state, NULL); if(arg_i_2) gmerlin_next_track(win->gmerlin); break; case BG_PLAYER_STATE_EOF: display_set_state(win->display, win->gmerlin->player_state, NULL); gmerlin_next_track(win->gmerlin); break; } break; case BG_PLAYER_MSG_TRACK_NAME: arg_str_1 = bg_msg_get_arg_string(msg, 0); display_set_track_name(win->display, arg_str_1); win->gmerlin->remote_data.name = bg_strdup(win->gmerlin->remote_data.name, arg_str_1); free(arg_str_1); break; case BG_PLAYER_MSG_TRACK_NUM_STREAMS: arg_i_1 = bg_msg_get_arg_int(msg, 0); arg_i_2 = bg_msg_get_arg_int(msg, 1); arg_i_3 = bg_msg_get_arg_int(msg, 2); main_menu_set_num_streams(win->main_menu, arg_i_1, arg_i_2, arg_i_3); break; case BG_PLAYER_MSG_NUM_CHAPTERS: arg_i_1 = bg_msg_get_arg_int(msg, 0); arg_i_2 = bg_msg_get_arg_int(msg, 1); main_menu_set_num_chapters(win->main_menu, arg_i_1, arg_i_2); break; case BG_PLAYER_MSG_CHAPTER_INFO: arg_i_1 = bg_msg_get_arg_int(msg, 0); arg_str_1 = bg_msg_get_arg_string(msg, 1); time = bg_msg_get_arg_time(msg, 2); main_menu_set_chapter_info(win->main_menu, arg_i_1, arg_str_1, time); break; case BG_PLAYER_MSG_CHAPTER_CHANGED: arg_i_1 = bg_msg_get_arg_int(msg, 0); main_menu_chapter_changed(win->main_menu, arg_i_1); break; case BG_PLAYER_MSG_ACCEL: arg_i_1 = bg_msg_get_arg_int(msg, 0); switch(arg_i_1) { case ACCEL_VOLUME_DOWN: bg_player_set_volume_rel(win->gmerlin->player, -1.0); break; case ACCEL_VOLUME_UP: bg_player_set_volume_rel(win->gmerlin->player, 1.0); break; case ACCEL_SEEK_BACKWARD: bg_player_seek_rel(win->gmerlin->player, -2 * GAVL_TIME_SCALE ); break; case ACCEL_SEEK_FORWARD: bg_player_seek_rel(win->gmerlin->player, 2 * GAVL_TIME_SCALE ); break; case ACCEL_SEEK_START: bg_player_seek(win->gmerlin->player,0, GAVL_TIME_SCALE ); break; case ACCEL_PAUSE: bg_player_pause(win->gmerlin->player); break; case ACCEL_MUTE: bg_player_toggle_mute(win->gmerlin->player); break; case ACCEL_NEXT_CHAPTER: bg_player_next_chapter(win->gmerlin->player); break; case ACCEL_PREV_CHAPTER: bg_player_prev_chapter(win->gmerlin->player); break; case ACCEL_PREV: bg_media_tree_previous(win->gmerlin->tree, 1, win->gmerlin->shuffle_mode); gmerlin_play(win->gmerlin, BG_PLAY_FLAG_IGNORE_IF_STOPPED); break; case ACCEL_NEXT: bg_media_tree_next(win->gmerlin->tree, 1, win->gmerlin->shuffle_mode); gmerlin_play(win->gmerlin, BG_PLAY_FLAG_IGNORE_IF_STOPPED); break; case ACCEL_QUIT: gtk_main_quit(); return; break; case ACCEL_CURRENT_TO_FAVOURITES: bg_media_tree_copy_current_to_favourites(win->gmerlin->tree); return; break; case ACCEL_OPTIONS: g_idle_add(do_configure, win->gmerlin); break; case ACCEL_GOTO_CURRENT: bg_gtk_tree_window_goto_current(win->gmerlin->tree_window); break; } break; case BG_PLAYER_MSG_TRACK_DURATION: win->duration = bg_msg_get_arg_time(msg, 0); win->gmerlin->remote_data.duration = win->duration; arg_i_2 = bg_msg_get_arg_int(msg, 1); if(arg_i_2) bg_gtk_slider_set_state(win->seek_slider, BG_GTK_SLIDER_ACTIVE); else if(win->duration != GAVL_TIME_UNDEFINED) bg_gtk_slider_set_state(win->seek_slider, BG_GTK_SLIDER_INACTIVE); else bg_gtk_slider_set_state(win->seek_slider, BG_GTK_SLIDER_HIDDEN); break; case BG_PLAYER_MSG_METADATA: gavl_metadata_free(&win->gmerlin->remote_data.metadata); bg_msg_get_arg_metadata(msg, 0, &win->gmerlin->remote_data.metadata); break; case BG_PLAYER_MSG_AUDIO_STREAM: arg_i_1 = bg_msg_get_arg_int(msg, 0); main_menu_set_audio_index(win->main_menu, arg_i_1); break; case BG_PLAYER_MSG_VIDEO_STREAM: arg_i_1 = bg_msg_get_arg_int(msg, 0); main_menu_set_video_index(win->main_menu, arg_i_1); break; case BG_PLAYER_MSG_SUBTITLE_STREAM: arg_i_1 = bg_msg_get_arg_int(msg, 0); main_menu_set_subtitle_index(win->main_menu, arg_i_1); break; case BG_PLAYER_MSG_AUDIO_STREAM_INFO: { gavl_metadata_t m; gavl_metadata_init(&m); arg_i_1 = bg_msg_get_arg_int(msg, 0); bg_msg_get_arg_metadata(msg, 1, &m); main_menu_set_audio_info(win->main_menu, arg_i_1, &m); gavl_metadata_free(&m); } break; case BG_PLAYER_MSG_VIDEO_STREAM_INFO: { gavl_metadata_t m; gavl_metadata_init(&m); arg_i_1 = bg_msg_get_arg_int(msg, 0); bg_msg_get_arg_metadata(msg, 1, &m); main_menu_set_video_info(win->main_menu, arg_i_1, &m); gavl_metadata_free(&m); } break; case BG_PLAYER_MSG_SUBTITLE_STREAM_INFO: { gavl_metadata_t m; gavl_metadata_init(&m); arg_i_1 = bg_msg_get_arg_int(msg, 0); bg_msg_get_arg_metadata(msg, 1, &m); main_menu_set_subtitle_info(win->main_menu, arg_i_1, &m); gavl_metadata_free(&m); } break; } } void player_window_push_accel(player_window_t * w, int accel) { bg_msg_t * msg; msg = bg_msg_queue_lock_write(w->msg_queue); bg_msg_set_id(msg, BG_PLAYER_MSG_ACCEL); bg_msg_set_arg_int(msg, 0, accel); bg_msg_queue_unlock_write(w->msg_queue); } static gboolean idle_callback(gpointer data) { bg_msg_t * msg; player_window_t * w = (player_window_t *)data; if(!w->msg_queue_locked) { while((msg = bg_msg_queue_try_lock_read(w->msg_queue))) { w->msg_queue_locked = 1; handle_message(w, msg); if(w->msg_queue_locked) { bg_msg_queue_unlock_read(w->msg_queue); w->msg_queue_locked = 0; } } } /* Handle remote control */ while((msg = bg_remote_server_get_msg(w->gmerlin->remote))) { gmerlin_handle_remote(w->gmerlin, msg); } return TRUE; } static gboolean crossing_callback(GtkWidget *widget, GdkEventCrossing *event, gpointer data) { player_window_t * w = (player_window_t *)data; if(event->detail == GDK_NOTIFY_INFERIOR) return FALSE; // fprintf(stderr, "crossing callback %d %d %d\n", // event->detail, event->type, w->mouse_inside); w->mouse_inside = (event->type == GDK_ENTER_NOTIFY) ? 1 : 0; // fprintf(stderr, "Set background..."); g_signal_handler_block(w->window, w->enter_notify_id); g_signal_handler_block(w->window, w->leave_notify_id); set_background(w); g_signal_handler_unblock(w->window, w->enter_notify_id); g_signal_handler_unblock(w->window, w->leave_notify_id); // fprintf(stderr, "Done\n"); return FALSE; } void player_window_create(gmerlin_t * g) { player_window_t * ret; ret = calloc(1, sizeof(*ret)); ret->gmerlin = g; g->player_window = ret; ret->msg_queue = bg_msg_queue_create(); bg_player_add_message_queue(g->player, ret->msg_queue); g_timeout_add(DELAY_TIME, idle_callback, (gpointer)ret); /* Create objects */ ret->window = bg_gtk_window_new(GTK_WINDOW_TOPLEVEL); gtk_window_set_decorated(GTK_WINDOW(ret->window), FALSE); ret->accel_group = gtk_accel_group_new(); gtk_window_add_accel_group (GTK_WINDOW(ret->window), ret->gmerlin->accel_group); gtk_window_add_accel_group (GTK_WINDOW(ret->window), ret->accel_group); ret->layout = gtk_layout_new(NULL, NULL); /* Set attributes */ gtk_widget_set_events(ret->window, GDK_ENTER_NOTIFY_MASK | GDK_LEAVE_NOTIFY_MASK); gtk_widget_set_events(ret->layout, GDK_BUTTON1_MOTION_MASK| GDK_BUTTON2_MOTION_MASK| GDK_BUTTON3_MOTION_MASK| GDK_BUTTON_PRESS_MASK); /* Set Callbacks */ g_signal_connect(G_OBJECT(ret->window), "realize", G_CALLBACK(realize_callback), (gpointer*)ret); ret->enter_notify_id = g_signal_connect(G_OBJECT(ret->window), "enter-notify-event", G_CALLBACK(crossing_callback), (gpointer*)ret); ret->leave_notify_id = g_signal_connect(G_OBJECT(ret->window), "leave-notify-event", G_CALLBACK(crossing_callback), (gpointer*)ret); g_signal_connect(G_OBJECT(ret->layout), "realize", G_CALLBACK(realize_callback), (gpointer*)ret); g_signal_connect(G_OBJECT(ret->layout), "motion-notify-event", G_CALLBACK(motion_callback), (gpointer*)ret); g_signal_connect(G_OBJECT(ret->layout), "button-press-event", G_CALLBACK(button_press_callback), (gpointer*)ret); /* Create child objects */ ret->play_button = bg_gtk_button_create(); ret->stop_button = bg_gtk_button_create(); ret->next_button = bg_gtk_button_create(); ret->prev_button = bg_gtk_button_create(); ret->pause_button = bg_gtk_button_create(); ret->menu_button = bg_gtk_button_create(); ret->close_button = bg_gtk_button_create(); ret->seek_slider = bg_gtk_slider_create(); ret->volume_slider = bg_gtk_slider_create(); ret->main_menu = main_menu_create(g); main_menu_finalize(ret->main_menu, g); ret->display = display_create(g); /* Set callbacks */ bg_gtk_slider_set_change_callback(ret->seek_slider, seek_change_callback, ret); bg_gtk_slider_set_release_callback(ret->seek_slider, seek_release_callback, ret); bg_gtk_slider_set_change_callback(ret->volume_slider, volume_change_callback, ret); bg_gtk_slider_set_scroll_callback(ret->volume_slider, slider_scroll_callback, ret); bg_gtk_slider_set_scroll_callback(ret->seek_slider, slider_scroll_callback, ret); bg_gtk_button_set_callback(ret->play_button, gmerlin_button_callback, ret); bg_gtk_button_set_callback(ret->stop_button, gmerlin_button_callback, ret); bg_gtk_button_set_callback(ret->pause_button, gmerlin_button_callback, ret); bg_gtk_button_set_callback(ret->next_button, gmerlin_button_callback, ret); bg_gtk_button_set_callback(ret->prev_button, gmerlin_button_callback, ret); bg_gtk_button_set_callback(ret->close_button, gmerlin_button_callback, ret); bg_gtk_button_set_callback_2(ret->next_button, gmerlin_button_callback_2, ret); bg_gtk_button_set_callback_2(ret->prev_button, gmerlin_button_callback_2, ret); bg_gtk_button_set_menu(ret->menu_button, main_menu_get_widget(ret->main_menu)); /* Set tooltips */ bg_gtk_tooltips_set_tip(bg_gtk_button_get_widget(ret->play_button), "Play", PACKAGE); bg_gtk_tooltips_set_tip(bg_gtk_button_get_widget(ret->stop_button), "Stop", PACKAGE); bg_gtk_tooltips_set_tip(bg_gtk_button_get_widget(ret->pause_button), "Pause", PACKAGE); bg_gtk_tooltips_set_tip(bg_gtk_button_get_widget(ret->next_button), "Left button: Next track\nRight button: Next chapter", PACKAGE); bg_gtk_tooltips_set_tip(bg_gtk_button_get_widget(ret->prev_button), "Left button: Previous track\nRight button: Previous chapter", PACKAGE); bg_gtk_tooltips_set_tip(bg_gtk_button_get_widget(ret->menu_button), "Main menu", PACKAGE); bg_gtk_tooltips_set_tip(bg_gtk_button_get_widget(ret->close_button), "Quit program", PACKAGE); bg_gtk_tooltips_set_tip(bg_gtk_slider_get_slider_widget(ret->volume_slider), "Volume", PACKAGE); bg_gtk_tooltips_set_tip(bg_gtk_slider_get_slider_widget(ret->seek_slider), "Seek", PACKAGE); /* Pack Objects */ gtk_layout_put(GTK_LAYOUT(ret->layout), bg_gtk_button_get_widget(ret->play_button), 0, 0); gtk_layout_put(GTK_LAYOUT(ret->layout), bg_gtk_button_get_widget(ret->stop_button), 0, 0); gtk_layout_put(GTK_LAYOUT(ret->layout), bg_gtk_button_get_widget(ret->pause_button), 0, 0); gtk_layout_put(GTK_LAYOUT(ret->layout), bg_gtk_button_get_widget(ret->next_button), 0, 0); gtk_layout_put(GTK_LAYOUT(ret->layout), bg_gtk_button_get_widget(ret->prev_button), 0, 0); gtk_layout_put(GTK_LAYOUT(ret->layout), bg_gtk_button_get_widget(ret->close_button), 0, 0); gtk_layout_put(GTK_LAYOUT(ret->layout), bg_gtk_button_get_widget(ret->menu_button), 0, 0); gtk_layout_put(GTK_LAYOUT(ret->layout), bg_gtk_slider_get_widget(ret->seek_slider), 0, 0); gtk_layout_put(GTK_LAYOUT(ret->layout), bg_gtk_slider_get_widget(ret->volume_slider), 0, 0); gtk_layout_put(GTK_LAYOUT(ret->layout), display_get_widget(ret->display), 0, 0); gtk_widget_show(ret->layout); gtk_container_add(GTK_CONTAINER(ret->window), ret->layout); } void player_window_show(player_window_t * win) { gtk_window_move(GTK_WINDOW(win->window), win->window_x, win->window_y); gtk_widget_show(win->window); } void player_window_destroy(player_window_t * win) { /* Fetch parameters */ bg_cfg_section_get(win->gmerlin->display_section, display_get_parameters(win->display), display_get_parameter, (void*)(win->display)); bg_msg_queue_destroy(win->msg_queue); bg_gtk_slider_destroy(win->seek_slider); bg_gtk_slider_destroy(win->volume_slider); main_menu_destroy(win->main_menu); if(win->background_pixbuf) g_object_unref(win->background_pixbuf); if(win->background_pixbuf_highlight) g_object_unref(win->background_pixbuf_highlight); free(win); } void player_window_skin_load(player_window_skin_t * s, xmlDocPtr doc, xmlNodePtr node) { xmlNodePtr child; char * tmp_string; child = node->children; while(child) { if(!child->name) { child = child->next; continue; } else if(!BG_XML_STRCMP(child->name, "BACKGROUND")) { tmp_string = (char*)xmlNodeListGetString(doc, child->children, 1); s->background = bg_strdup(s->background, tmp_string); xmlFree(tmp_string); } else if(!BG_XML_STRCMP(child->name, "BACKGROUND_HIGHLIGHT")) { tmp_string = (char*)xmlNodeListGetString(doc, child->children, 1); s->background_highlight = bg_strdup(s->background_highlight, tmp_string); xmlFree(tmp_string); } else if(!BG_XML_STRCMP(child->name, "DISPLAY")) display_skin_load(&s->display, doc, child); else if(!BG_XML_STRCMP(child->name, "PLAYBUTTON")) bg_gtk_button_skin_load(&s->play_button, doc, child); else if(!BG_XML_STRCMP(child->name, "PAUSEBUTTON")) bg_gtk_button_skin_load(&s->pause_button, doc, child); else if(!BG_XML_STRCMP(child->name, "NEXTBUTTON")) bg_gtk_button_skin_load(&s->next_button, doc, child); else if(!BG_XML_STRCMP(child->name, "PREVBUTTON")) bg_gtk_button_skin_load(&s->prev_button, doc, child); else if(!BG_XML_STRCMP(child->name, "STOPBUTTON")) bg_gtk_button_skin_load(&s->stop_button, doc, child); else if(!BG_XML_STRCMP(child->name, "MENUBUTTON")) bg_gtk_button_skin_load(&s->menu_button, doc, child); else if(!BG_XML_STRCMP(child->name, "CLOSEBUTTON")) bg_gtk_button_skin_load(&s->close_button, doc, child); else if(!BG_XML_STRCMP(child->name, "SEEKSLIDER")) bg_gtk_slider_skin_load(&s->seek_slider, doc, child); else if(!BG_XML_STRCMP(child->name, "VOLUMESLIDER")) bg_gtk_slider_skin_load(&s->volume_slider, doc, child); else if(!BG_XML_STRCMP(child->name, "DISPLAY")) display_skin_load(&s->display, doc, child); child = child->next; } } void player_window_skin_destroy(player_window_skin_t * s) { if(s->background) free(s->background); if(s->background_highlight) free(s->background_highlight); bg_gtk_button_skin_free(&s->play_button); bg_gtk_button_skin_free(&s->stop_button); bg_gtk_button_skin_free(&s->pause_button); bg_gtk_button_skin_free(&s->next_button); bg_gtk_button_skin_free(&s->prev_button); bg_gtk_button_skin_free(&s->close_button); bg_gtk_button_skin_free(&s->menu_button); bg_gtk_slider_skin_free(&s->seek_slider); bg_gtk_slider_skin_free(&s->volume_slider); } gmerlin-1.2.0~dfsg/apps/player/skinbrowser.c0000644000175000017500000002742611764363403021066 0ustar alessioalessio/***************************************************************** * gmerlin - a general purpose multimedia framework and applications * * Copyright (c) 2001 - 2011 Members of the Gmerlin project * gmerlin-general@lists.sourceforge.net * http://gmerlin.sourceforge.net * * 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 of the License, 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 this program. If not, see . * *****************************************************************/ #include #include #include #include #include #include #include #include #include #include "gmerlin.h" #include #include #include enum { COLUMN_NAME, NUM_COLUMNS }; typedef struct skin_info_s { char * name; char * directory; struct skin_info_s * next; } skin_info_t; static skin_info_t * scan_directory(const char * directory) { skin_info_t * ret = NULL; skin_info_t * ret_end = NULL; skin_info_t * new_info; const char * start; DIR * dir; struct dirent * entry; char dir_filename[FILENAME_MAX]; char skin_filename[FILENAME_MAX]; struct stat st; dir = opendir(directory); if(!dir) return NULL; while((entry = readdir(dir))) { if(entry->d_name[0] == '.') /* Skip ".", ".." and hidden files */ continue; sprintf(dir_filename, "%s/%s", directory, entry->d_name); /* Check if we can do a stat */ if(stat(dir_filename, &st)) continue; /* Check if this is a directory */ if(!S_ISDIR(st.st_mode)) continue; /* Check if a file skin.xml is inside, this also checks if the directory is readable for us */ sprintf(skin_filename, "%s/skin.xml", dir_filename); if(stat(skin_filename, &st)) continue; /* Now, create the skin info */ new_info = calloc(1, sizeof(*new_info)); new_info->directory = bg_strdup(new_info->directory, dir_filename); start = strrchr(new_info->directory, '/'); if(!start) continue; start++; new_info->name = bg_strdup(new_info->name, start); if(!ret) { ret = new_info; ret_end = ret; } else { ret_end->next = new_info; ret_end = ret_end->next; } } closedir(dir); return ret; } static skin_info_t * skin_info_create() { char * home_dir; char * directory; skin_info_t * system_skins; skin_info_t * home_skins = NULL; skin_info_t * ret_end; directory = bg_sprintf("%s/%s", DATA_DIR, "skins"); system_skins = scan_directory(directory); free(directory); home_dir = getenv("HOME"); if(home_dir) { directory = bg_sprintf("%s/%s", home_dir, ".gmerlin/skins"); home_skins = scan_directory(directory); free(directory); } if(system_skins && home_skins) { ret_end = system_skins; while(ret_end->next) ret_end = ret_end->next; ret_end->next = home_skins; return system_skins; } else if(system_skins) return system_skins; else if(home_skins) return system_skins; else return NULL; } static void skin_info_destroy(skin_info_t * info) { skin_info_t * tmp_info; while(info) { tmp_info = info->next; free(info->name); free(info->directory); free(info); info = tmp_info; } } struct gmerlin_skin_browser_s { GtkWidget * window; GtkWidget * treeview; GtkWidget * new_button; GtkWidget * close_button; gmerlin_t * g; guint select_handler_id; skin_info_t * skins; }; static void update_list(gmerlin_skin_browser_t * b) { skin_info_t * skin; GtkTreeSelection * selection; GtkTreeModel * model; GtkTreeIter iter; model = gtk_tree_view_get_model(GTK_TREE_VIEW(b->treeview)); selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(b->treeview)); g_signal_handler_block(G_OBJECT(selection), b->select_handler_id); gtk_list_store_clear(GTK_LIST_STORE(model)); skin = b->skins; while(skin) { gtk_list_store_append(GTK_LIST_STORE(model), &iter); gtk_list_store_set(GTK_LIST_STORE(model), &iter, COLUMN_NAME, skin->name, -1); if(!strcmp(skin->directory, b->g->skin_dir)) { gtk_tree_selection_select_iter(selection, &iter); } skin = skin->next; } while(gtk_events_pending()) gtk_main_iteration(); g_signal_handler_unblock(G_OBJECT(selection), b->select_handler_id); } static void select_row_callback(GtkTreeSelection * sel, gpointer data) { gmerlin_skin_browser_t * b; skin_info_t * skin; GtkTreeIter iter; GtkTreeSelection * selection; GtkTreeModel * model; b = (gmerlin_skin_browser_t*)data; selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(b->treeview)); model = gtk_tree_view_get_model(GTK_TREE_VIEW(b->treeview)); if(!gtk_tree_model_get_iter_first(model, &iter)) return; skin = b->skins; /* Find the selected skin */ while(skin) { if(gtk_tree_selection_iter_is_selected(selection, &iter)) break; skin = skin->next; if(skin) gtk_tree_model_iter_next(model, &iter); } if(!skin) return; /* Found the skin */ if(!strcmp(skin->directory, b->g->skin_dir)) return; b->g->skin_dir = bg_strdup(b->g->skin_dir, skin->directory); gmerlin_skin_load(&b->g->skin, b->g->skin_dir); gmerlin_skin_set(b->g); } static void filesel_close_callback(bg_gtk_filesel_t * f , void * data) { gmerlin_skin_browser_t * b; b = (gmerlin_skin_browser_t*)data; gtk_widget_set_sensitive(b->new_button, 1); } static int install_skin(const char * filename, GtkWidget * parent) { int ret = 0; char * command; char * home_dir; char * error_msg; struct stat st; char * test_dir; home_dir = getenv("HOME"); /* Create skin directory if it doesn't exist */ test_dir = bg_sprintf("%s/.gmerlin", home_dir); if(stat(test_dir, &st)) { if(mkdir(test_dir, S_IRUSR|S_IWUSR|S_IXUSR) == -1) { free(test_dir); return 0; } } free(test_dir); test_dir = bg_sprintf("%s/.gmerlin/skins", home_dir); if(stat(test_dir, &st)) { if(mkdir(test_dir, S_IRUSR|S_IWUSR|S_IXUSR) == -1) { free(test_dir); return 0; } } free(test_dir); command = bg_sprintf("tar -C %s/.gmerlin/skins -xvzf %s", home_dir, filename); if(system(command)) { error_msg = bg_sprintf(TR("Installing skin from\n%s\nfailed"), filename); bg_gtk_message(error_msg, BG_GTK_MESSAGE_ERROR, parent); free(error_msg); } else ret = 1; free(command); return ret; } static void add_file_callback(char ** files, const char * plugin, int prefer_edl, void * data) { int rescan = 0; int i; gmerlin_skin_browser_t * b; b = (gmerlin_skin_browser_t*)data; i = 0; while(files[i]) { if(install_skin(files[i], b->window)) rescan = 1; i++; } if(rescan) { skin_info_destroy(b->skins); b->skins = skin_info_create(); update_list(b); } } static void button_callback(GtkWidget * w, gpointer data) { bg_gtk_filesel_t * filesel; gmerlin_skin_browser_t * b; b = (gmerlin_skin_browser_t*)data; if((w == b->window) || (w == b->close_button)) { gtk_widget_hide(b->window); } else if(w == b->new_button) { filesel = bg_gtk_filesel_create("Install skin", add_file_callback, filesel_close_callback, b, b->window /* parent */, NULL, 0, 0); gtk_widget_set_sensitive(b->new_button, 0); bg_gtk_filesel_run(filesel, 0); } } static int delete_callback(GtkWidget * w, GdkEvent * event, gpointer data) { button_callback(w, data); return TRUE; } gmerlin_skin_browser_t * gmerlin_skin_browser_create(gmerlin_t * g) { GtkWidget * mainbox; GtkWidget * buttonbox; GtkWidget * scrolledwin; GtkTreeViewColumn * col; GtkListStore *store; GtkCellRenderer *renderer; GtkTreeSelection * selection; gmerlin_skin_browser_t * ret; ret = calloc(1, sizeof(*ret)); ret->g = g; ret->skins = skin_info_create(); /* Create window */ ret->window = bg_gtk_window_new(GTK_WINDOW_TOPLEVEL); g_signal_connect(G_OBJECT(ret->window), "delete_event", G_CALLBACK(delete_callback), (gpointer)ret); gtk_window_set_title(GTK_WINDOW(ret->window), TR("Skin browser")); gtk_window_set_position(GTK_WINDOW(ret->window), GTK_WIN_POS_CENTER); /* Create skin list */ store = gtk_list_store_new(NUM_COLUMNS, G_TYPE_STRING); ret->treeview = gtk_tree_view_new_with_model(GTK_TREE_MODEL(store)); gtk_widget_set_size_request(ret->treeview, 200, 200); selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(ret->treeview)); ret->select_handler_id = g_signal_connect(G_OBJECT(selection), "changed", G_CALLBACK(select_row_callback), (gpointer)ret); renderer = gtk_cell_renderer_text_new(); col = gtk_tree_view_column_new (); gtk_tree_view_column_set_title(col, "Installed skins"); gtk_tree_view_column_pack_start(col, renderer, FALSE); gtk_tree_view_column_add_attribute(col, renderer, "text", COLUMN_NAME); gtk_tree_view_append_column (GTK_TREE_VIEW(ret->treeview), col); gtk_widget_show(ret->treeview); scrolledwin = gtk_scrolled_window_new(gtk_tree_view_get_hadjustment(GTK_TREE_VIEW(ret->treeview)), gtk_tree_view_get_vadjustment(GTK_TREE_VIEW(ret->treeview))); gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolledwin), GTK_POLICY_NEVER, GTK_POLICY_ALWAYS); gtk_container_add(GTK_CONTAINER(scrolledwin), ret->treeview); gtk_widget_show(scrolledwin); /* Create buttons */ ret->close_button = gtk_button_new_from_stock(GTK_STOCK_CLOSE); ret->new_button = gtk_button_new_from_stock(GTK_STOCK_NEW); g_signal_connect(G_OBJECT(ret->close_button), "clicked", G_CALLBACK(button_callback), (gpointer)ret); g_signal_connect(G_OBJECT(ret->new_button), "clicked", G_CALLBACK(button_callback), (gpointer)ret); gtk_widget_show(ret->close_button); gtk_widget_show(ret->new_button); /* Pack the objects */ mainbox = gtk_vbox_new(0, 5); gtk_container_set_border_width(GTK_CONTAINER(mainbox), 5); bg_gtk_box_pack_start_defaults(GTK_BOX(mainbox), scrolledwin); buttonbox = gtk_hbutton_box_new(); gtk_box_set_spacing(GTK_BOX(buttonbox), 5); gtk_container_add(GTK_CONTAINER(buttonbox), ret->close_button); gtk_container_add(GTK_CONTAINER(buttonbox), ret->new_button); gtk_widget_show(buttonbox); gtk_box_pack_start(GTK_BOX(mainbox), buttonbox, FALSE, FALSE, 0); gtk_widget_show(mainbox); gtk_container_add(GTK_CONTAINER(ret->window), mainbox); update_list(ret); return ret; } void gmerlin_skin_browser_destroy(gmerlin_skin_browser_t * b) { g_object_unref(b->window); free(b); } void gmerlin_skin_browser_show(gmerlin_skin_browser_t * b) { gtk_widget_show(b->window); } gmerlin-1.2.0~dfsg/apps/player/Makefile.in0000644000175000017500000006511111764363423020412 0ustar alessioalessio# Makefile.in generated by automake 1.11.1 from Makefile.am. # @configure_input@ # Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, # 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation, # Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ VPATH = @srcdir@ pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ bin_PROGRAMS = gmerlin$(EXEEXT) gmerlin_remote$(EXEEXT) subdir = apps/player DIST_COMMON = $(dist_man_MANS) $(noinst_HEADERS) $(srcdir)/Makefile.am \ $(srcdir)/Makefile.in ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/m4/check_funcs.m4 \ $(top_srcdir)/m4/gavl_simd.m4 $(top_srcdir)/m4/gettext.m4 \ $(top_srcdir)/m4/iconv.m4 $(top_srcdir)/m4/lib-ld.m4 \ $(top_srcdir)/m4/lib-link.m4 $(top_srcdir)/m4/lib-prefix.m4 \ $(top_srcdir)/m4/lqt_opt_cflags.m4 $(top_srcdir)/m4/nls.m4 \ $(top_srcdir)/m4/po.m4 $(top_srcdir)/m4/progtest.m4 \ $(top_srcdir)/acinclude.m4 $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/include/config.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = am__installdirs = "$(DESTDIR)$(bindir)" "$(DESTDIR)$(bindir)" \ "$(DESTDIR)$(man1dir)" "$(DESTDIR)$(Desktopdir)" PROGRAMS = $(bin_PROGRAMS) am_gmerlin_OBJECTS = cfgdialog.$(OBJEXT) display.$(OBJEXT) \ gmerlin.$(OBJEXT) main.$(OBJEXT) mainmenu.$(OBJEXT) \ playerwindow.$(OBJEXT) remote.$(OBJEXT) skin.$(OBJEXT) \ skinbrowser.$(OBJEXT) gmerlin_OBJECTS = $(am_gmerlin_OBJECTS) gmerlin_DEPENDENCIES = $(top_builddir)/lib/libgmerlin.la \ $(top_builddir)/lib/gtk/libgmerlin_gtk.la am_gmerlin_remote_OBJECTS = gmerlin_remote.$(OBJEXT) gmerlin_remote_OBJECTS = $(am_gmerlin_remote_OBJECTS) gmerlin_remote_DEPENDENCIES = $(top_builddir)/lib/libgmerlin.la am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; am__vpath_adj = case $$p in \ $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ *) f=$$p;; \ esac; am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; am__install_max = 40 am__nobase_strip_setup = \ srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` am__nobase_strip = \ for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" am__nobase_list = $(am__nobase_strip_setup); \ for p in $$list; do echo "$$p $$p"; done | \ sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ if (++n[$$2] == $(am__install_max)) \ { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ END { for (dir in files) print dir, files[dir] }' am__base_list = \ sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' SCRIPTS = $(bin_SCRIPTS) DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)/include depcomp = $(SHELL) $(top_srcdir)/depcomp am__depfiles_maybe = depfiles am__mv = mv -f COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) LTCOMPILE = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \ --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) CCLD = $(CC) LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \ --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \ $(LDFLAGS) -o $@ SOURCES = $(gmerlin_SOURCES) $(gmerlin_remote_SOURCES) DIST_SOURCES = $(gmerlin_SOURCES) $(gmerlin_remote_SOURCES) man1dir = $(mandir)/man1 NROFF = nroff MANS = $(dist_man_MANS) DATA = $(Desktop_DATA) HEADERS = $(noinst_HEADERS) ETAGS = etags CTAGS = ctags DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ ALSA_CFLAGS = @ALSA_CFLAGS@ ALSA_LIBS = @ALSA_LIBS@ ALSA_REQUIRED = @ALSA_REQUIRED@ AMTAR = @AMTAR@ AR = @AR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ BG_VERSION = @BG_VERSION@ BG_VERSION_MAJOR = @BG_VERSION_MAJOR@ BG_VERSION_MICRO = @BG_VERSION_MICRO@ BG_VERSION_MINOR = @BG_VERSION_MINOR@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CDDB_CFLAGS = @CDDB_CFLAGS@ CDDB_LIBS = @CDDB_LIBS@ CDIO_CDDA_CFLAGS = @CDIO_CDDA_CFLAGS@ CDIO_CDDA_LIBS = @CDIO_CDDA_LIBS@ CDIO_CFLAGS = @CDIO_CFLAGS@ CDIO_LIBS = @CDIO_LIBS@ CDIO_PARANOIA_CFLAGS = @CDIO_PARANOIA_CFLAGS@ CDIO_PARANOIA_LIBS = @CDIO_PARANOIA_LIBS@ CDIO_REQUIRED = @CDIO_REQUIRED@ CFLAGS = @CFLAGS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CYGPATH_W = @CYGPATH_W@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DOXYGEN = @DOXYGEN@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ ESD_CFLAGS = @ESD_CFLAGS@ ESD_CONFIG = @ESD_CONFIG@ ESD_LIBS = @ESD_LIBS@ ESD_REQUIRED = @ESD_REQUIRED@ EXEEXT = @EXEEXT@ FGREP = @FGREP@ FONTCONFIG_CFLAGS = @FONTCONFIG_CFLAGS@ FONTCONFIG_LIBS = @FONTCONFIG_LIBS@ FREETYPE_CFLAGS = @FREETYPE_CFLAGS@ FREETYPE_LIBS = @FREETYPE_LIBS@ GAVL_CFLAGS = @GAVL_CFLAGS@ GAVL_LIBS = @GAVL_LIBS@ GAVL_REQUIRED = @GAVL_REQUIRED@ GLX_CFLAGS = @GLX_CFLAGS@ GLX_LIBS = @GLX_LIBS@ GL_CFLAGS = @GL_CFLAGS@ GL_LIBS = @GL_LIBS@ GMERLIN_DEP_LIBS = @GMERLIN_DEP_LIBS@ GMERLIN_PLUGIN_LDFLAGS = @GMERLIN_PLUGIN_LDFLAGS@ GMSGFMT = @GMSGFMT@ GMSGFMT_015 = @GMSGFMT_015@ GREP = @GREP@ GTK_CFLAGS = @GTK_CFLAGS@ GTK_LIBS = @GTK_LIBS@ GTK_REQUIRED = @GTK_REQUIRED@ ICONV_LIBS = @ICONV_LIBS@ INCLUDES = -I$(top_srcdir)/include INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ INTLLIBS = @INTLLIBS@ INTL_MACOSX_LIBS = @INTL_MACOSX_LIBS@ JACK_CFLAGS = @JACK_CFLAGS@ JACK_LIBS = @JACK_LIBS@ JACK_REQUIRED = @JACK_REQUIRED@ JPEG_CFLAGS = @JPEG_CFLAGS@ JPEG_LIBS = @JPEG_LIBS@ JPEG_REQUIRED = @JPEG_REQUIRED@ LD = @LD@ LDFLAGS = @LDFLAGS@ LIBCDDB_REQUIRED = @LIBCDDB_REQUIRED@ LIBEXIF_CFLAGS = @LIBEXIF_CFLAGS@ LIBEXIF_LIBS = @LIBEXIF_LIBS@ LIBICONV = @LIBICONV@ LIBINTL = @LIBINTL@ LIBM = @LIBM@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIPO = @LIPO@ LN_S = @LN_S@ LQT_CFLAGS = @LQT_CFLAGS@ LQT_LIBS = @LQT_LIBS@ LQT_REQUIRED = @LQT_REQUIRED@ LTLIBICONV = @LTLIBICONV@ LTLIBINTL = @LTLIBINTL@ LTLIBOBJS = @LTLIBOBJS@ LTVERSION_AGE = @LTVERSION_AGE@ LTVERSION_CURRENT = @LTVERSION_CURRENT@ LTVERSION_REVISION = @LTVERSION_REVISION@ LV_CFLAGS = @LV_CFLAGS@ LV_LIBS = @LV_LIBS@ LV_REQUIRED = @LV_REQUIRED@ MAKEINFO = @MAKEINFO@ MKDIR_P = @MKDIR_P@ MODULE_LIBADD = @MODULE_LIBADD@ MSGFMT = @MSGFMT@ MSGFMT_015 = @MSGFMT_015@ MSGMERGE = @MSGMERGE@ MUSICBRAINZ_CFLAGS = @MUSICBRAINZ_CFLAGS@ MUSICBRAINZ_LIBS = @MUSICBRAINZ_LIBS@ MUSICBRAINZ_REQUIRED = @MUSICBRAINZ_REQUIRED@ NM = @NM@ NMEDIT = @NMEDIT@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OTOOL = @OTOOL@ OTOOL64 = @OTOOL64@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PKG_CONFIG = @PKG_CONFIG@ PNG_CFLAGS = @PNG_CFLAGS@ PNG_LIBS = @PNG_LIBS@ PNG_REQUIRED = @PNG_REQUIRED@ POSUB = @POSUB@ PULSEAUDIO_CFLAGS = @PULSEAUDIO_CFLAGS@ PULSEAUDIO_LIBS = @PULSEAUDIO_LIBS@ PULSEAUDIO_REQUIRED = @PULSEAUDIO_REQUIRED@ RANLIB = @RANLIB@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ SQLITE3_LIBS = @SQLITE3_LIBS@ STRIP = @STRIP@ TEXINFO = @TEXINFO@ TIFF_CFLAGS = @TIFF_CFLAGS@ TIFF_LIBS = @TIFF_LIBS@ TIFF_REQUIRED = @TIFF_REQUIRED@ TOP_SRCDIR = @TOP_SRCDIR@ USE_NLS = @USE_NLS@ V4LCONVERT_CFLAGS = @V4LCONVERT_CFLAGS@ V4LCONVERT_LIBS = @V4LCONVERT_LIBS@ V4LCONVERT_REQUIRED = @V4LCONVERT_REQUIRED@ VERSION = @VERSION@ XDPMS_LIBS = @XDPMS_LIBS@ XFIXES_LIBS = @XFIXES_LIBS@ XGETTEXT = @XGETTEXT@ XGETTEXT_015 = @XGETTEXT_015@ XINERAMA_LIBS = @XINERAMA_LIBS@ XMKMF = @XMKMF@ XML2_CFLAGS = @XML2_CFLAGS@ XML2_LIBS = @XML2_LIBS@ XML2_REQUIRED = @XML2_REQUIRED@ XTEST_LIBS = @XTEST_LIBS@ XV_LIBS = @XV_LIBS@ X_CFLAGS = @X_CFLAGS@ X_LIBS = @X_LIBS@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_CC = @ac_ct_CC@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_vendor = @build_vendor@ builddir = @builddir@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ lt_ECHO = @lt_ECHO@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ plugindir = $(pkglibdir)/plugins AM_CFLAGS = \ @XML2_CFLAGS@ \ @GTK_CFLAGS@ \ -DLOCALE_DIR=\"$(localedir)\" \ -DPLUGIN_DIR=\"$(plugindir)\" \ -DDOC_DIR=\"$(docdir)\" \ -DDATA_DIR=\"$(pkgdatadir)\" Desktopdir = $(datadir)/applications Desktop_DATA = gmerlin-player.desktop dist_man_MANS = gmerlin.1 gmerlin_remote.1 bin_SCRIPTS = gmerlin_launcher gmerlin_SOURCES = \ cfgdialog.c \ display.c \ gmerlin.c \ main.c \ mainmenu.c \ playerwindow.c \ remote.c \ skin.c \ skinbrowser.c gmerlin_remote_SOURCES = \ gmerlin_remote.c noinst_HEADERS = \ display.h \ gmerlin.h \ player_remote.h \ playerwindow.h gmerlin_LDADD = $(top_builddir)/lib/libgmerlin.la $(top_builddir)/lib/gtk/libgmerlin_gtk.la @XML2_LIBS@ gmerlin_remote_LDADD = $(top_builddir)/lib/libgmerlin.la EXTRA_DIST = gmerlin_launcher gmerlin-player.desktop all: all-am .SUFFIXES: .SUFFIXES: .c .lo .o .obj $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ && { if test -f $@; then exit 0; else break; fi; }; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu apps/player/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --gnu apps/player/Makefile .PRECIOUS: Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): install-binPROGRAMS: $(bin_PROGRAMS) @$(NORMAL_INSTALL) test -z "$(bindir)" || $(MKDIR_P) "$(DESTDIR)$(bindir)" @list='$(bin_PROGRAMS)'; test -n "$(bindir)" || list=; \ for p in $$list; do echo "$$p $$p"; done | \ sed 's/$(EXEEXT)$$//' | \ while read p p1; do if test -f $$p || test -f $$p1; \ then echo "$$p"; echo "$$p"; else :; fi; \ done | \ sed -e 'p;s,.*/,,;n;h' -e 's|.*|.|' \ -e 'p;x;s,.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/' | \ sed 'N;N;N;s,\n, ,g' | \ $(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1 } \ { d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \ if ($$2 == $$4) files[d] = files[d] " " $$1; \ else { print "f", $$3 "/" $$4, $$1; } } \ END { for (d in files) print "f", d, files[d] }' | \ while read type dir files; do \ if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \ test -z "$$files" || { \ echo " $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files '$(DESTDIR)$(bindir)$$dir'"; \ $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files "$(DESTDIR)$(bindir)$$dir" || exit $$?; \ } \ ; done uninstall-binPROGRAMS: @$(NORMAL_UNINSTALL) @list='$(bin_PROGRAMS)'; test -n "$(bindir)" || list=; \ files=`for p in $$list; do echo "$$p"; done | \ sed -e 'h;s,^.*/,,;s/$(EXEEXT)$$//;$(transform)' \ -e 's/$$/$(EXEEXT)/' `; \ test -n "$$list" || exit 0; \ echo " ( cd '$(DESTDIR)$(bindir)' && rm -f" $$files ")"; \ cd "$(DESTDIR)$(bindir)" && rm -f $$files clean-binPROGRAMS: @list='$(bin_PROGRAMS)'; test -n "$$list" || exit 0; \ echo " rm -f" $$list; \ rm -f $$list || exit $$?; \ test -n "$(EXEEXT)" || exit 0; \ list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ echo " rm -f" $$list; \ rm -f $$list gmerlin$(EXEEXT): $(gmerlin_OBJECTS) $(gmerlin_DEPENDENCIES) @rm -f gmerlin$(EXEEXT) $(LINK) $(gmerlin_OBJECTS) $(gmerlin_LDADD) $(LIBS) gmerlin_remote$(EXEEXT): $(gmerlin_remote_OBJECTS) $(gmerlin_remote_DEPENDENCIES) @rm -f gmerlin_remote$(EXEEXT) $(LINK) $(gmerlin_remote_OBJECTS) $(gmerlin_remote_LDADD) $(LIBS) install-binSCRIPTS: $(bin_SCRIPTS) @$(NORMAL_INSTALL) test -z "$(bindir)" || $(MKDIR_P) "$(DESTDIR)$(bindir)" @list='$(bin_SCRIPTS)'; test -n "$(bindir)" || list=; \ for p in $$list; do \ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ if test -f "$$d$$p"; then echo "$$d$$p"; echo "$$p"; else :; fi; \ done | \ sed -e 'p;s,.*/,,;n' \ -e 'h;s|.*|.|' \ -e 'p;x;s,.*/,,;$(transform)' | sed 'N;N;N;s,\n, ,g' | \ $(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1; } \ { d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \ if ($$2 == $$4) { files[d] = files[d] " " $$1; \ if (++n[d] == $(am__install_max)) { \ print "f", d, files[d]; n[d] = 0; files[d] = "" } } \ else { print "f", d "/" $$4, $$1 } } \ END { for (d in files) print "f", d, files[d] }' | \ while read type dir files; do \ if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \ test -z "$$files" || { \ echo " $(INSTALL_SCRIPT) $$files '$(DESTDIR)$(bindir)$$dir'"; \ $(INSTALL_SCRIPT) $$files "$(DESTDIR)$(bindir)$$dir" || exit $$?; \ } \ ; done uninstall-binSCRIPTS: @$(NORMAL_UNINSTALL) @list='$(bin_SCRIPTS)'; test -n "$(bindir)" || exit 0; \ files=`for p in $$list; do echo "$$p"; done | \ sed -e 's,.*/,,;$(transform)'`; \ test -n "$$list" || exit 0; \ echo " ( cd '$(DESTDIR)$(bindir)' && rm -f" $$files ")"; \ cd "$(DESTDIR)$(bindir)" && rm -f $$files mostlyclean-compile: -rm -f *.$(OBJEXT) distclean-compile: -rm -f *.tab.c @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cfgdialog.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/display.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gmerlin.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gmerlin_remote.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/main.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mainmenu.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/playerwindow.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/remote.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/skin.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/skinbrowser.Po@am__quote@ .c.o: @am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(COMPILE) -c $< .c.obj: @am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(COMPILE) -c `$(CYGPATH_W) '$<'` .c.lo: @am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(LTCOMPILE) -c -o $@ $< mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs install-man1: $(dist_man_MANS) @$(NORMAL_INSTALL) test -z "$(man1dir)" || $(MKDIR_P) "$(DESTDIR)$(man1dir)" @list=''; test -n "$(man1dir)" || exit 0; \ { for i in $$list; do echo "$$i"; done; \ l2='$(dist_man_MANS)'; for i in $$l2; do echo "$$i"; done | \ sed -n '/\.1[a-z]*$$/p'; \ } | while read p; do \ if test -f $$p; then d=; else d="$(srcdir)/"; fi; \ echo "$$d$$p"; echo "$$p"; \ done | \ sed -e 'n;s,.*/,,;p;h;s,.*\.,,;s,^[^1][0-9a-z]*$$,1,;x' \ -e 's,\.[0-9a-z]*$$,,;$(transform);G;s,\n,.,' | \ sed 'N;N;s,\n, ,g' | { \ list=; while read file base inst; do \ if test "$$base" = "$$inst"; then list="$$list $$file"; else \ echo " $(INSTALL_DATA) '$$file' '$(DESTDIR)$(man1dir)/$$inst'"; \ $(INSTALL_DATA) "$$file" "$(DESTDIR)$(man1dir)/$$inst" || exit $$?; \ fi; \ done; \ for i in $$list; do echo "$$i"; done | $(am__base_list) | \ while read files; do \ test -z "$$files" || { \ echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(man1dir)'"; \ $(INSTALL_DATA) $$files "$(DESTDIR)$(man1dir)" || exit $$?; }; \ done; } uninstall-man1: @$(NORMAL_UNINSTALL) @list=''; test -n "$(man1dir)" || exit 0; \ files=`{ for i in $$list; do echo "$$i"; done; \ l2='$(dist_man_MANS)'; for i in $$l2; do echo "$$i"; done | \ sed -n '/\.1[a-z]*$$/p'; \ } | sed -e 's,.*/,,;h;s,.*\.,,;s,^[^1][0-9a-z]*$$,1,;x' \ -e 's,\.[0-9a-z]*$$,,;$(transform);G;s,\n,.,'`; \ test -z "$$files" || { \ echo " ( cd '$(DESTDIR)$(man1dir)' && rm -f" $$files ")"; \ cd "$(DESTDIR)$(man1dir)" && rm -f $$files; } install-DesktopDATA: $(Desktop_DATA) @$(NORMAL_INSTALL) test -z "$(Desktopdir)" || $(MKDIR_P) "$(DESTDIR)$(Desktopdir)" @list='$(Desktop_DATA)'; test -n "$(Desktopdir)" || list=; \ for p in $$list; do \ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ echo "$$d$$p"; \ done | $(am__base_list) | \ while read files; do \ echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(Desktopdir)'"; \ $(INSTALL_DATA) $$files "$(DESTDIR)$(Desktopdir)" || exit $$?; \ done uninstall-DesktopDATA: @$(NORMAL_UNINSTALL) @list='$(Desktop_DATA)'; test -n "$(Desktopdir)" || list=; \ files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ test -n "$$files" || exit 0; \ echo " ( cd '$(DESTDIR)$(Desktopdir)' && rm -f" $$files ")"; \ cd "$(DESTDIR)$(Desktopdir)" && rm -f $$files ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | \ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in files) print i; }; }'`; \ mkid -fID $$unique tags: TAGS TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ $(TAGS_FILES) $(LISP) set x; \ here=`pwd`; \ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | \ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in files) print i; }; }'`; \ shift; \ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ test -n "$$unique" || unique=$$empty_fix; \ if test $$# -gt 0; then \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ "$$@" $$unique; \ else \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ $$unique; \ fi; \ fi ctags: CTAGS CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ $(TAGS_FILES) $(LISP) list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | \ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in files) print i; }; }'`; \ test -z "$(CTAGS_ARGS)$$unique" \ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ $$unique GTAGS: here=`$(am__cd) $(top_builddir) && pwd` \ && $(am__cd) $(top_srcdir) \ && gtags -i $(GTAGS_ARGS) "$$here" distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags distdir: $(DISTFILES) @list='$(MANS)'; if test -n "$$list"; then \ list=`for p in $$list; do \ if test -f $$p; then d=; else d="$(srcdir)/"; fi; \ if test -f "$$d$$p"; then echo "$$d$$p"; else :; fi; done`; \ if test -n "$$list" && \ grep 'ab help2man is required to generate this page' $$list >/dev/null; then \ echo "error: found man pages containing the \`missing help2man' replacement text:" >&2; \ grep -l 'ab help2man is required to generate this page' $$list | sed 's/^/ /' >&2; \ echo " to fix them, install help2man, remove and regenerate the man pages;" >&2; \ echo " typically \`make maintainer-clean' will remove them" >&2; \ exit 1; \ else :; fi; \ else :; fi @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done check-am: all-am check: check-am all-am: Makefile $(PROGRAMS) $(SCRIPTS) $(MANS) $(DATA) $(HEADERS) installdirs: for dir in "$(DESTDIR)$(bindir)" "$(DESTDIR)$(bindir)" "$(DESTDIR)$(man1dir)" "$(DESTDIR)$(Desktopdir)"; do \ test -z "$$dir" || $(MKDIR_P) "$$dir"; \ done install: install-am install-exec: install-exec-am install-data: install-data-am uninstall: uninstall-am install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-am install-strip: $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ `test -z '$(STRIP)' || \ echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install mostlyclean-generic: clean-generic: distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." clean: clean-am clean-am: clean-binPROGRAMS clean-generic clean-libtool mostlyclean-am distclean: distclean-am -rm -rf ./$(DEPDIR) -rm -f Makefile distclean-am: clean-am distclean-compile distclean-generic \ distclean-tags dvi: dvi-am dvi-am: html: html-am html-am: info: info-am info-am: install-data-am: install-DesktopDATA install-man install-dvi: install-dvi-am install-dvi-am: install-exec-am: install-binPROGRAMS install-binSCRIPTS install-html: install-html-am install-html-am: install-info: install-info-am install-info-am: install-man: install-man1 install-pdf: install-pdf-am install-pdf-am: install-ps: install-ps-am install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-am -rm -rf ./$(DEPDIR) -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-compile mostlyclean-generic \ mostlyclean-libtool pdf: pdf-am pdf-am: ps: ps-am ps-am: uninstall-am: uninstall-DesktopDATA uninstall-binPROGRAMS \ uninstall-binSCRIPTS uninstall-man uninstall-man: uninstall-man1 .MAKE: install-am install-strip .PHONY: CTAGS GTAGS all all-am check check-am clean clean-binPROGRAMS \ clean-generic clean-libtool ctags distclean distclean-compile \ distclean-generic distclean-libtool distclean-tags distdir dvi \ dvi-am html html-am info info-am install install-DesktopDATA \ install-am install-binPROGRAMS install-binSCRIPTS install-data \ install-data-am install-dvi install-dvi-am install-exec \ install-exec-am install-html install-html-am install-info \ install-info-am install-man install-man1 install-pdf \ install-pdf-am install-ps install-ps-am install-strip \ installcheck installcheck-am installdirs maintainer-clean \ maintainer-clean-generic mostlyclean mostlyclean-compile \ mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ tags uninstall uninstall-DesktopDATA uninstall-am \ uninstall-binPROGRAMS uninstall-binSCRIPTS uninstall-man \ uninstall-man1 # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: gmerlin-1.2.0~dfsg/apps/player/gmerlin-player.desktop0000644000175000017500000000032011764363403022654 0ustar alessioalessio[Desktop Entry] Name=Gmerlin player Name[de]=Gmerlin player Comment=Multiformat mediaplayer Comment[de]=Multiformat mediaplayer Exec=gmerlin Icon=gmerlin-player Type=Application Categories=AudioVideo;Player; gmerlin-1.2.0~dfsg/apps/player/player_remote.h0000644000175000017500000000450311764363403021361 0ustar alessioalessio/***************************************************************** * gmerlin - a general purpose multimedia framework and applications * * Copyright (c) 2001 - 2011 Members of the Gmerlin project * gmerlin-general@lists.sourceforge.net * http://gmerlin.sourceforge.net * * 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 of the License, 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 this program. If not, see . * *****************************************************************/ #define PLAYER_REMOTE_PORT (BG_REMOTE_PORT_BASE+1) #define PLAYER_REMOTE_ID "gmerlin_player" #define PLAYER_REMOTE_ENV "GMERLIN_PLAYER_REMOTE_PORT" /* Player commands */ /* These resemble the player buttons */ #define PLAYER_COMMAND_PLAY 1 #define PLAYER_COMMAND_STOP 2 #define PLAYER_COMMAND_NEXT 3 #define PLAYER_COMMAND_PREV 4 #define PLAYER_COMMAND_PAUSE 5 /* Add or play a location (arg1: Location) */ #define PLAYER_COMMAND_ADD_LOCATION 6 #define PLAYER_COMMAND_PLAY_LOCATION 7 /* Volume control (arg: Volume in dB) */ #define PLAYER_COMMAND_SET_VOLUME 8 #define PLAYER_COMMAND_SET_VOLUME_REL 9 /* Seek */ #define PLAYER_COMMAND_SEEK 10 #define PLAYER_COMMAND_SEEK_REL 11 /* Open devices */ #define PLAYER_COMMAND_OPEN_DEVICE 12 #define PLAYER_COMMAND_PLAY_DEVICE 13 /* Mute */ #define PLAYER_COMMAND_TOGGLE_MUTE 14 /* Chapters */ #define PLAYER_COMMAND_SET_CHAPTER 15 #define PLAYER_COMMAND_NEXT_CHAPTER 16 #define PLAYER_COMMAND_PREV_CHAPTER 17 /* Query values */ #define PLAYER_COMMAND_GET_NAME (1<<8) #define PLAYER_COMMAND_GET_METADATA (2<<8) #define PLAYER_COMMAND_GET_TIME (3<<8) /* Query responses */ #define PLAYER_RESPONSE_GET_NAME (1<<16) #define PLAYER_RESPONSE_GET_METADATA (2<<16) #define PLAYER_RESPONSE_GET_TIME (3<<16) gmerlin-1.2.0~dfsg/apps/cmdlinerecorder/0000755000175000017500000000000011764363443020210 5ustar alessioalessiogmerlin-1.2.0~dfsg/apps/cmdlinerecorder/Makefile.am0000644000175000017500000000056111764363402022241 0ustar alessioalessioplugindir=$(pkglibdir)/plugins AM_CFLAGS = \ -DLOCALE_DIR=\"$(localedir)\" \ -DPLUGIN_DIR=\"$(plugindir)\" \ -DDOC_DIR=\"$(docdir)\" \ -DDATA_DIR=\"$(pkgdatadir)\" INCLUDES = -I$(top_srcdir)/include bin_PROGRAMS = gmerlin-record dist_man_MANS = gmerlin-record.1 gmerlin_record_LDADD = $(top_builddir)/lib/libgmerlin.la -ldl gmerlin_record_SOURCES=gmerlin-record.c gmerlin-1.2.0~dfsg/apps/cmdlinerecorder/gmerlin-record.c0000644000175000017500000003166611764363402023274 0ustar alessioalessio/***************************************************************** * gmerlin - a general purpose multimedia framework and applications * * Copyright (c) 2001 - 2011 Members of the Gmerlin project * gmerlin-general@lists.sourceforge.net * http://gmerlin.sourceforge.net * * 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 of the License, 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 this program. If not, see . * *****************************************************************/ #include #include #include #include #include #include #include #include #include static bg_recorder_t * recorder; static bg_cfg_section_t * audio_section; static bg_cfg_section_t * video_section; static bg_cfg_section_t * metadata_section; static bg_cfg_section_t * encoder_section; static bg_cfg_section_t * af_section; static bg_cfg_section_t * vf_section; static bg_cfg_section_t * vm_section; static bg_cfg_section_t * output_section; const bg_parameter_info_t * audio_parameters; const bg_parameter_info_t * video_parameters; const bg_parameter_info_t * af_parameters; const bg_parameter_info_t * vf_parameters; const bg_parameter_info_t * vm_parameters; const bg_parameter_info_t * output_parameters; const bg_parameter_info_t * metadata_parameters; const bg_parameter_info_t * encoder_parameters; static bg_plugin_registry_t * plugin_reg; static bg_cfg_registry_t * cfg_reg; static int do_record = 0; static int do_syslog = 0; #define DELAY_TIME 50 #define PING_INTERVAL 20 int got_sigint = 0; static void sigint_handler(int sig) { fprintf(stderr, "\nCTRL+C caught\n"); got_sigint = 1; } static void set_sigint_handler() { struct sigaction sa; sa.sa_flags = 0; sigemptyset(&sa.sa_mask); sa.sa_handler = sigint_handler; if (sigaction(SIGINT, &sa, NULL) == -1) { fprintf(stderr, "sigaction failed\n"); } } static void opt_aud(void * data, int * argc, char *** _argv, int arg) { if(arg >= *argc) { fprintf(stderr, "Option -aud requires an argument\n"); exit(-1); } if(!bg_cmdline_apply_options(audio_section, bg_recorder_set_audio_parameter, recorder, audio_parameters, (*_argv)[arg])) exit(-1); bg_cmdline_remove_arg(argc, _argv, arg); } static void opt_af(void * data, int * argc, char *** _argv, int arg) { if(arg >= *argc) { fprintf(stderr, "Option -af requires an argument\n"); exit(-1); } if(!bg_cmdline_apply_options(audio_section, bg_recorder_set_audio_filter_parameter, recorder, af_parameters, (*_argv)[arg])) exit(-1); bg_cmdline_remove_arg(argc, _argv, arg); } static void opt_vid(void * data, int * argc, char *** _argv, int arg) { if(arg >= *argc) { fprintf(stderr, "Option -vid requires an argument\n"); exit(-1); } if(!bg_cmdline_apply_options(video_section, bg_recorder_set_video_parameter, recorder, video_parameters, (*_argv)[arg])) exit(-1); bg_cmdline_remove_arg(argc, _argv, arg); } static void opt_vf(void * data, int * argc, char *** _argv, int arg) { if(arg >= *argc) { fprintf(stderr, "Option -vf requires an argument\n"); exit(-1); } if(!bg_cmdline_apply_options(video_section, bg_recorder_set_video_filter_parameter, recorder, vf_parameters, (*_argv)[arg])) exit(-1); bg_cmdline_remove_arg(argc, _argv, arg); } static void opt_vm(void * data, int * argc, char *** _argv, int arg) { if(arg >= *argc) { fprintf(stderr, "Option -vm requires an argument\n"); exit(-1); } if(!bg_cmdline_apply_options(video_section, bg_recorder_set_video_monitor_parameter, recorder, vm_parameters, (*_argv)[arg])) exit(-1); bg_cmdline_remove_arg(argc, _argv, arg); } static void opt_m(void * data, int * argc, char *** _argv, int arg) { if(arg >= *argc) { fprintf(stderr, "Option -m requires an argument\n"); exit(-1); } if(!bg_cmdline_apply_options(metadata_section, bg_recorder_set_metadata_parameter, recorder, metadata_parameters, (*_argv)[arg])) exit(-1); bg_cmdline_remove_arg(argc, _argv, arg); } static void opt_r(void * data, int * argc, char *** _argv, int arg) { do_record = 1; } static void opt_enc(void * data, int * argc, char *** _argv, int arg) { if(arg >= *argc) { fprintf(stderr, "Option -enc requires an argument\n"); exit(-1); } if(!bg_cmdline_apply_options(encoder_section, /* bg_recorder_set_metadata_parameter */ NULL, /* recorder */ NULL, encoder_parameters, (*_argv)[arg])) exit(-1); bg_cmdline_remove_arg(argc, _argv, arg); } static void opt_o(void * data, int * argc, char *** _argv, int arg) { if(arg >= *argc) { fprintf(stderr, "Option -o requires an argument\n"); exit(-1); } if(!bg_cmdline_apply_options(encoder_section, bg_recorder_set_output_parameter, recorder, output_parameters, (*_argv)[arg])) exit(-1); bg_cmdline_remove_arg(argc, _argv, arg); } static void opt_syslog(void * data, int * argc, char *** _argv, int arg) { if(arg >= *argc) { fprintf(stderr, "Option -syslog requires an argument\n"); exit(-1); } bg_log_syslog_init((*_argv)[arg]); do_syslog = 1; bg_cmdline_remove_arg(argc, _argv, arg); } static bg_cmdline_arg_t global_options[] = { { .arg = "-aud", .help_arg = "", .help_string = "Set audio recording options", .callback = opt_aud, }, { .arg = "-vid", .help_arg = "", .help_string = "Set video recording options", .callback = opt_vid, }, { .arg = "-af", .help_arg = " (default: 1.000,1.000,1.000,1.000)" .P , , and are in the range 0.0..1.0 .P Text color .P .BR border_color "=,, (default: 0.000,0.000,0.000)" .P , and are in the range 0.0..1.0 .P Border color .P .BR border_width "= (0.00..10.00, default: 2.00)" .P Border width .P .BR font "= (Default: Courier-20)" .P Font .P .BR justify_h "=" .P Supported strings: center left right .P Default: right .P Horizontal justify .P .BR justify_v "=" .P Supported strings: center top bottom .P Default: top .P Vertical justify .P .BR border_left "= (0..65535, default: 10)" .P Left border .P Distance from the left text border to the image border .P .BR border_right "= (0..65535, default: 10)" .P Right border .P Distance from the right text border to the image border .P .BR border_top "= (0..65535, default: 10)" .P Top border .P Distance from the top text border to the image border .P .BR border_bottom "= (0..65535, default: 10)" .P Bottom border .P Distance from the bottom text border to the image border .P .RE .B Suboptions for fv_displaywalltv .P .RS 2 .BR scale "= (1..9, default: 3)" .P Scale .P .BR speedx "= (-100..100, default: 10)" .P Horizontal scroll speed .P .BR speedy "= (-100..100, default: 10)" .P Vertical scroll speed .P .RE .B Suboptions for fv_dottv .P .RS 2 .BR mode "=" .P Supported strings: dots hearts .P Default: dots .P Mode .P .RE .B Suboptions for fv_edgeblurtv .P .RS 2 .BR color "=,, (default: 1.000,1.000,1.000)" .P , and are in the range 0.0..1.0 .P Color .P .RE .B Suboptions for fv_equalizer .P .RS 2 .BR brightness "= (-10.0..10.0, default: 0.0)" .P Brightness .P .BR contrast "= (-10.0..10.0, default: 0.0)" .P Contrast .P .BR saturation "= (-10.0..10.0, default: 0.0)" .P Saturation .P .BR hue "= (-180.0..180.0, default: 0.0)" .P Hue .P .RE .B Suboptions for fv_firetv .P .RS 2 .BR mode "=" .P Supported strings: fg light dark .P Default: all .P Mode .P .RE .B Suboptions for fv_flip .P .RS 2 .BR flip_h "=[1|0] (default: 0)" .P Flip horizontally .P .BR flip_v "=[1|0] (default: 0)" .P Flip vertically .P .RE .B Suboptions for fv_framerate .P .RS 2 .BR framerate "=" .P Supported strings: from_source user_defined 23_976 24 25 29_970 30 50 59_940 60 .P Default: from_source .P Framerate .P Output framerate. For user defined framerate, enter the timescale and frame duration below (framerate = timescale / frame duration). .P .BR timescale "= (1..100000, default: 25)" .P Timescale .P Timescale for user defined output framerate (Framerate = timescale / frame duration). .P .BR frame_duration "= (1..100000, default: 1)" .P Frame duration .P Frame duration for user defined output framerate (Framerate = timescale / frame duration). .P .RE .B Suboptions for fv_pixelformat .P .RS 2 .BR pixelformat "=" .P Supported strings: 8 bpp gray 16 bpp gray Float gray 16 bpp gray + alpha 32 bpp gray + alpha Float gray + alpha 15 bpp RGB 15 bpp BGR 16 bpp RGB 16 bpp BGR 24 bpp RGB 24 bpp BGR 32 bpp RGB 32 bpp BGR 32 bpp RGBA 48 bpp RGB 64 bpp RGBA Float RGB Float RGBA YUV 422 (YUY2) YUV 422 (UYVY) YUVA 4444 (8 bit) YUVA 4444 (16 bit) YUVA 4444 (float) YUV 444 (float) YUV 420 Planar YUV 410 Planar YUV 411 Planar YUV 422 Planar YUV 422 Planar (16 bit) YUV 444 Planar YUV 444 Planar (16 bit) YUVJ 420 Planar YUVJ 422 Planar YUVJ 444 Planar .P Default: YUV 420 Planar .P Pixelformat .P .RE .B Suboptions for fv_interlace .P .RS 2 .BR field_order "=" .P Supported strings: top bottom .P Default: top .P Output field order .P .RE .B Suboptions for fv_invert .P .RS 2 .BR r "=[1|0] (default: 1)" .P Invert red .P .BR g "=[1|0] (default: 1)" .P Invert green .P .BR b "=[1|0] (default: 1)" .P Invert blue .P .BR a "=[1|0] (default: 1)" .P Invert alpha .P .RE .B Suboptions for fv_lenstv .P .RS 2 .BR x "= (0.00..1.00, default: 0.25)" .P X .P .BR y "= (0.00..1.00, default: 0.25)" .P Y .P .BR lens_width "= (0.00..1.00, default: 0.25)" .P Diameter .P .BR lens_zoom "= (5..200, default: 30)" .P Zoom .P .RE .B Suboptions for fv_matrixtv .P .RS 2 .BR mode "=[1|0] (default: 0)" .P Blend .P .RE .B Suboptions for fv_halftv .P .RS 2 .BR mode "=" .P Supported strings: delay scratch nervous .P Default: delay .P Mode .P .BR direction "=" .P Supported strings: left right top bottom .P Default: right .P Direction .P .BR mirror "=" .P Supported strings: normal mirror copy .P Default: mirror .P Mirror .P .BR delay "= (0..31, default: 10)" .P Delay .P .RE .B Suboptions for fv_nervoustv .P .RS 2 .BR mode "=" .P Supported strings: random scratch .P Default: random .P Mode .P .RE .B Suboptions for fv_oldcolor .P .RS 2 .BR style "=" .P Supported strings: bw tech1 tech2 .P Default: tech1 .P Style .P .BR strength "= (0.000..1.000, default: 1.000)" .P Strength .P .BR r_gain "= (0.000..2.000, default: 1.000)" .P Red gain .P .BR g_gain "= (0.000..2.000, default: 1.000)" .P Green gain .P .BR b_gain "= (0.000..2.000, default: 1.000)" .P Blue gain .P .RE .B Suboptions for fv_optv .P .RS 2 .BR mode "=" .P Supported strings: maelstrom radiation perspective vertical .P Default: maelstrom .P Mode .P .BR speed "= (-64..64, default: 16)" .P Speed .P .RE .B Suboptions for fv_puptv .P .RS 2 .BR mode "=" .P Supported strings: horizontal vertical diagonal dissolution random raster .P Default: horizontal .P Mode .P .BR strength "= (0.00..1.00, default: 0.20)" .P Strength .P .RE .B Suboptions for fv_colormatrix_rgb .P .RS 2 .BR r_to_r "= (-2.000..2.000, default: 1.000)" .P Red -> Red .P .BR g_to_r "= (-2.000..2.000, default: 0.000)" .P Green -> Red .P .BR b_to_r "= (-2.000..2.000, default: 0.000)" .P Blue -> Red .P .BR a_to_r "= (-2.000..2.000, default: 0.000)" .P Alpha -> Red .P .BR off_r "= (-2.000..2.000, default: 0.000)" .P Red offset .P .BR r_to_g "= (-2.000..2.000, default: 0.000)" .P Red -> Green .P .BR g_to_g "= (-2.000..2.000, default: 1.000)" .P Green -> Green .P .BR b_to_g "= (-2.000..2.000, default: 0.000)" .P Blue -> Green .P .BR a_to_g "= (-2.000..2.000, default: 0.000)" .P Alpha -> Green .P .BR off_g "= (-2.000..2.000, default: 0.000)" .P Green offset .P .BR r_to_b "= (-2.000..2.000, default: 0.000)" .P Red -> Blue .P .BR g_to_b "= (-2.000..2.000, default: 0.000)" .P Green -> Blue .P .BR b_to_b "= (-2.000..2.000, default: 1.000)" .P Blue -> Blue .P .BR a_to_b "= (-2.000..2.000, default: 0.000)" .P Alpha -> Blue .P .BR off_b "= (-2.000..2.000, default: 0.000)" .P Blue offset .P .BR r_to_a "= (-2.000..2.000, default: 0.000)" .P Red -> Alpha .P .BR g_to_a "= (-2.000..2.000, default: 0.000)" .P Green -> Alpha .P .BR b_to_a "= (-2.000..2.000, default: 0.000)" .P Blue -> Alpha .P .BR a_to_a "= (-2.000..2.000, default: 1.000)" .P Alpha -> Alpha .P .BR off_a "= (-2.000..2.000, default: 0.000)" .P Alpha offset .P .BR force_alpha "=[1|0] (default: 0)" .P Force alpha .P Create video with alpha channel even if the input format has no alpha channel. Use this to generate the alpha channel from other channels using the colormatrix. .P .RE .B Suboptions for fv_rdstv .P .RS 2 .BR method "=" .P Supported strings: wall cross .P Default: wall .P Method .P .RE .B Suboptions for fv_revtv .P .RS 2 .BR fg_color "=,, (default: 1.000,1.000,1.000)" .P , and are in the range 0.0..1.0 .P Line color .P .BR bg_color "=,, (default: 0.000,0.000,0.000)" .P , and are in the range 0.0..1.0 .P Background .P .BR spacing "= (0.000..1.000, default: 0.100)" .P Spacing .P .BR amplitude "= (0.00..1.00, default: 0.10)" .P Amplitude .P .BR vgrabtime "= (1..10, default: 1)" .P Grab interval .P .RE .B Suboptions for fv_rippletv .P .RS 2 .BR mode "=" .P Supported strings: motion rain .P Default: motion .P Mode .P .BR loopnum "= (1..5, default: 2)" .P Speed .P .BR strength "= (1..10, default: 8)" .P Strength .P .BR decay_cfg "= (1..15, default: 8)" .P Decay .P .RE .B Suboptions for fv_rndmtv .P .RS 2 .BR rmode "=[1|0] (default: 1)" .P Color .P .RE .B Suboptions for fv_shagadelictv .P .RS 2 .BR mask_r "=[1|0] (default: 1)" .P Red mask .P .BR mask_g "=[1|0] (default: 1)" .P Green mask .P .BR mask_b "=[1|0] (default: 1)" .P Blue mask .P .RE .B Suboptions for fv_shift .P .RS 2 .BR shift "= (0..8, default: 0)" .P Bits to shift .P .RE .B Suboptions for fv_simuratv .P .RS 2 .BR color "=,, (default: 0.000,0.000,0.000)" .P , and are in the range 0.0..1.0 .P Color .P .BR mirror_mode "=" .P Supported strings: no l r d dl dr u ul ur .P Default: no .P Mirror mode .P .RE .B Suboptions for fv_sparktv .P .RS 2 .BR mode "=" .P Supported strings: fg light dark .P Default: all .P Mode .P .RE .B Suboptions for fv_spiraltv .P .RS 2 .BR mode "=" .P Supported strings: Concentric A Sawtooth Up Sawtooth Down Triangle Sinusoidal Concentric B Lens Flat .P Default: Concentric A .P Mode .P .BR g_focus_interval "= (0..60, default: 6)" .P Focus interval .P .BR center_x "= (0.000..1.000, default: 0.500)" .P Center x .P .BR center_y "= (0.000..1.000, default: 0.500)" .P Center y .P .BR g_depth_shift "= (0..5, default: 0)" .P Depth shift .P .RE .B Suboptions for fv_tlp .P .RS 2 .BR factor "= (0.00..1.00, default: 0.50)" .P Strength .P 0 means no effect, 1 means maximum (= still image) .P .BR quality "= (1..5, default: 2)" .P Quality .P .RE .B Suboptions for fv_transform .P .RS 2 .BR tm "=" .P Supported strings: rotate affine perspective lens_effect whirl .P Default: rotate .P Transformation mode .P Choose Transformation method. Each method can be configured in it's section. .P .BR im "=" .P Supported strings: auto nearest bilinear quadratic cubic_bspline .P Default: auto .P Interpolation mode .P Choose interpolation method. Auto means to choose based on the conversion quality. Nearest is fastest, Bicubic is slowest. .P .BR bg_color "=,,, (default: 0.000,0.000,0.000,1.000)" .P , , and are in the range 0.0..1.0 .P Background color .P .BR rotate_angle "= (-360.00..360.00, default: 0.00)" .P Angle .P .BR affine_xx "= (-2.000..2.000, default: 1.000)" .P X -> X .P .BR affine_xy "= (-2.000..2.000, default: 0.000)" .P X -> Y .P .BR affine_yx "= (-2.000..2.000, default: 0.000)" .P Y -> X .P .BR affine_yy "= (-2.000..2.000, default: 1.000)" .P Y -> Y .P .BR affine_ox "= (-1.000..1.000, default: 0.000)" .P X Offset .P Normalized X offset. 1 corresponds to image with. .P .BR affine_oy "= (-1.000..1.000, default: 0.000)" .P Y Offset .P Normalized Y offset. 1 corresponds to image height. .P .BR perspective_tl "=, (default: 0.000,0.000)" .P , and are in the range 0.0..1.0 .P Top left .P Top left corner in normalized image coordinates .P .BR perspective_tr "=, (default: 1.000,0.000)" .P , and are in the range 0.0..1.0 .P Top right .P Top right corner in normalized image coordinates .P .BR perspective_bl "=, (default: 0.000,1.000)" .P , and are in the range 0.0..1.0 .P Bottom left .P Bottom left corner in normalized image coordinates .P .BR perspective_br "=, (default: 1.000,1.000)" .P , and are in the range 0.0..1.0 .P Bottom right .P Bottom right corner in normalized image coordinates .P .BR lens_effect_pos "=, (default: 0.500,0.500)" .P , and are in the range 0.0..1.0 .P Position .P Center of the lens .P .BR lens_effect_diameter "= (0.00..1.00, default: 0.25)" .P Diameter .P Diamater of the lens (1 is image size) .P .BR lens_effect_zoom "= (5.00..200.00, default: 20.00)" .P Zoom .P Zoom factor .P .BR whirl_center "=, (default: 0.500,0.500)" .P , and are in the range 0.0..1.0 .P Center .P .BR whirl_radius "= (0.00..1.00, default: 0.50)" .P Radius .P .BR whirl_pinch "= (0.00..1.00, default: 0.50)" .P Pinch .P .BR whirl_angle "= (0.00..360.00, default: 30.00)" .P Angle .P .RE .B Suboptions for fv_transformtv .P .RS 2 .BR transform "= (0..5, default: 0)" .P Transformation .P .RE .B Suboptions for fv_tctweak .P .RS 2 .BR mode "=" .P Supported strings: off interpolate remove_redundant remove_all add add_first .P Default: off .P Mode .P .BR int_framerate "= (1..999, default: 25)" .P Integer framerate .P Set the integer framerate used when adding new timecodes .P .BR drop "=[1|0] (default: 0)" .P Drop frame .P Set the if drop frame is used when adding new timecodes .P .BR hours "= (0..23, default: 0)" .P Start hour .P Set the start hours used when adding new timecodes .P .BR minutes "= (0..59, default: 0)" .P Start minute .P Set the start minutes used when adding new timecodes .P .BR seconds "= (0..59, default: 0)" .P Start second .P Set the start seconds used when adding new timecodes .P .BR frames "= (0..999, default: 0)" .P Start frames .P Set the start frames used when adding new timecodes .P .RE .B Suboptions for fv_vertigotv .P .RS 2 .BR phase_increment "= (0.01..1.00, default: 0.02)" .P Phase increment .P .BR zoomrate "= (1.01..1.10, default: 1.01)" .P Zoom rate .P .RE .B Suboptions for fv_colormatrix_yuv .P .RS 2 .BR y_to_y "= (-2.000..2.000, default: 1.000)" .P Luminance -> Luminance .P .BR u_to_y "= (-2.000..2.000, default: 0.000)" .P Cb -> Luminance .P .BR v_to_y "= (-2.000..2.000, default: 0.000)" .P Cr -> Luminance .P .BR a_to_y "= (-2.000..2.000, default: 0.000)" .P Alpha -> Luminance .P .BR off_y "= (-2.000..2.000, default: 0.000)" .P Luminance offset .P .BR r_to_u "= (-2.000..2.000, default: 0.000)" .P Luminance -> Cb .P .BR u_to_u "= (-2.000..2.000, default: 1.000)" .P Cb -> Cb .P .BR b_to_u "= (-2.000..2.000, default: 0.000)" .P Cr -> Cb .P .BR a_to_u "= (-2.000..2.000, default: 0.000)" .P Alpha -> Cb .P .BR off_u "= (-2.000..2.000, default: 0.000)" .P Cb offset .P .BR y_to_v "= (-2.000..2.000, default: 0.000)" .P Luminance -> Cr .P .BR u_to_v "= (-2.000..2.000, default: 0.000)" .P Cb -> Cr .P .BR v_to_v "= (-2.000..2.000, default: 1.000)" .P Cr -> Cr .P .BR a_to_v "= (-2.000..2.000, default: 0.000)" .P Alpha -> Cr .P .BR off_v "= (-2.000..2.000, default: 0.000)" .P Cr offset .P .BR y_to_a "= (-2.000..2.000, default: 0.000)" .P Luminance -> Alpha .P .BR u_to_a "= (-2.000..2.000, default: 0.000)" .P Cb -> Alpha .P .BR v_to_a "= (-2.000..2.000, default: 0.000)" .P Cr -> Alpha .P .BR a_to_a "= (-2.000..2.000, default: 1.000)" .P Alpha -> Alpha .P .BR off_a "= (-2.000..2.000, default: 0.000)" .P Alpha offset .P .BR force_alpha "=[1|0] (default: 0)" .P Force alpha .P Create video with alpha channel even if the input format has no alpha channel. Use this to generate the alpha channel from other channels using the colormatrix. .P .RE .B Suboptions for fv_zoom .P .RS 2 .BR zoom_h "= (0.50..2.00, default: 1.00)" .P Zoom horizontally .P .BR zoom_v "= (0.50..2.00, default: 1.00)" .P Zoom vertically .P .BR sm "=" .P Supported strings: auto nearest bilinear quadratic cubic_bspline cubic_mitchell cubic_catmull sinc_lanczos .P Default: auto .P Scale mode .P Choose scaling method. Auto means to choose based on the conversion quality. Nearest is fastest, Sinc with Lanczos window is slowest. .P .BR so "= (4..1000, default: 4)" .P Scale order .P Order for sinc scaling .P .BR downscale_filter "=" .P Supported strings: auto none wide gauss .P Default: auto .P Antialiasing for downscaling .P Specifies the antialiasing filter to be used when downscaling images. .P .BR downscale_blur "= (0.00..2.00, default: 1.00)" .P Blur factor for downscaling .P Specifies how much blurring should be applied when downscaling. Smaller values can speed up scaling, but might result in strong aliasing. .P .BR quality "= (1..5, default: 2)" .P Quality .P .BR bg_color "=,,, (default: 0.000,0.000,0.000,1.000)" .P , , and are in the range 0.0..1.0 .P Background color .P .RE .B Suboptions for bg_f0r_3 point color balance .P .RS 2 .BR Black color "=,, (default: 0.000,0.000,0.000)" .P , and are in the range 0.0..1.0 .P Black color .P Black color .P .BR Gray color "=,, (default: 0.500,0.500,0.500)" .P , and are in the range 0.0..1.0 .P Gray color .P Gray color .P .BR White color "=,, (default: 1.000,1.000,1.000)" .P , and are in the range 0.0..1.0 .P White color .P White color .P .BR Split preview "=[1|0] (default: 1)" .P Split preview .P Split privew .P .BR Source image on left side "=[1|0] (default: 1)" .P Source image on left side .P Source image on left side .P .RE .B Suboptions for bg_f0r_3dflippo .P .RS 2 .BR X axis rotation "= (0.0000..1.0000, default: 0.5000)" .P X axis rotation .P Rotation on the X axis .P .BR Y axis rotation "= (0.0000..1.0000, default: 0.5000)" .P Y axis rotation .P Rotation on the Y axis .P .BR Z axis rotation "= (0.0000..1.0000, default: 0.5000)" .P Z axis rotation .P Rotation on the Z axis .P .BR X axis rotation rate "= (0.0000..1.0000, default: 0.5000)" .P X axis rotation rate .P Rotation rate on the X axis .P .BR Y axis rotation rate "= (0.0000..1.0000, default: 0.5000)" .P Y axis rotation rate .P Rotation rate on the Y axis .P .BR Z axis rotation rate "= (0.0000..1.0000, default: 0.5000)" .P Z axis rotation rate .P Rotation rate on the Z axis .P .BR Center position (X) "= (0.0000..1.0000, default: 0.0000)" .P Center position (X) .P Position of the center of rotation on the X axis .P .BR Center position (Y) "= (0.0000..1.0000, default: 0.0000)" .P Center position (Y) .P Position of the center of rotation on the Y axis .P .BR Invert rotation assignment "=[1|0] (default: 0)" .P Invert rotation assignment .P If true, when mapping rotation, make inverted (wrong) assignment .P .BR Don't blank mask "=[1|0] (default: 0)" .P Don't blank mask .P Mask for frame transposition is not blanked, so a trace of old transpositions is maintained .P .BR Fill with image or black "=[1|0] (default: 0)" .P Fill with image or black .P If true, pixels that are not transposed are black, otherwise, they are copied with the original .P .RE .B Suboptions for bg_f0r_Brightness .P .RS 2 .BR Brightness "= (0.0000..1.0000, default: 0.5000)" .P Brightness .P The brightness value .P .RE .B Suboptions for bg_f0r_Cartoon .P .RS 2 .BR triplevel "= (0.0000..1.0000, default: 1000.0000)" .P triplevel .P level of trip: use high numbers, incremented by 100 .P .BR diffspace "= (0.0000..1.0000, default: 1.0000)" .P diffspace .P difference space: a value from 0 to 256 .P .RE .B Suboptions for bg_f0r_Color Distance .P .RS 2 .BR Color "=,, (default: 0.500,0.500,0.500)" .P , and are in the range 0.0..1.0 .P Color .P The Source Color .P .RE .B Suboptions for bg_f0r_Contrast0r .P .RS 2 .BR Contrast "= (0.0000..1.0000, default: 0.5000)" .P Contrast .P The contrast value .P .RE .B Suboptions for bg_f0r_Curves .P .RS 2 .BR Channel "= (0.0000..1.0000, default: 0.0000)" .P Channel .P Channel to adjust levels (1 = RED; 2 = GREEN; 3 = BLUE; 4 = LUMA) .P .BR Show curves "=[1|0] (default: 1)" .P Show curves .P Draw curve graph on output image .P .BR Graph position "= (0.0000..1.0000, default: 3.0000)" .P Graph position .P Output image corner where curve graph will be drawn (1 = TOP,LEFT; 2 = TOP,RIGHT; 3 = BOTTOM,LEFT; 4 = BOTTOM, RIGHT) .P .BR Curve point number "= (0.0000..1.0000, default: 2.0000)" .P Curve point number .P Number of point to use to build curve .P .BR Point 1 input value "= (0.0000..1.0000, default: 1.0000)" .P Point 1 input value .P Point 1 input value .P .BR Point 1 output value "= (0.0000..1.0000, default: 1.0000)" .P Point 1 output value .P Point 1 output value .P .BR Point 2 input value "= (0.0000..1.0000, default: 1.0000)" .P Point 2 input value .P Point 2 input value .P .BR Point 2 output value "= (0.0000..1.0000, default: 1.0000)" .P Point 2 output value .P Point 2 output value .P .BR Point 3 input value "= (0.0000..1.0000, default: 1.0000)" .P Point 3 input value .P Point 3 input value .P .BR Point 3 output value "= (0.0000..1.0000, default: 1.0000)" .P Point 3 output value .P Point 3 output value .P .BR Point 4 input value "= (0.0000..1.0000, default: 1.0000)" .P Point 4 input value .P Point 4 input value .P .BR Point 4 output value "= (0.0000..1.0000, default: 1.0000)" .P Point 4 output value .P Point 4 output value .P .BR Point 5 input value "= (0.0000..1.0000, default: 1.0000)" .P Point 5 input value .P Point 5 input value .P .BR Point 5 output value "= (0.0000..1.0000, default: 1.0000)" .P Point 5 output value .P Point 5 output value .P .RE .B Suboptions for bg_f0r_Defish0r .P .RS 2 .BR Amount "= (0.0000..1.0000, default: 0.0000)" .P Amount .P Focal Ratio .P .BR DeFish "=[1|0] (default: 0)" .P DeFish .P Fish or Defish .P .BR Type "= (0.0000..1.0000, default: 0.6667)" .P Type .P Mapping function .P .BR Scaling "= (0.0000..1.0000, default: 0.6667)" .P Scaling .P Scaling method .P .BR Manual Scale "= (0.0000..1.0000, default: 0.5000)" .P Manual Scale .P Manual Scale .P .BR Interpolator "= (0.0000..1.0000, default: 0.1667)" .P Interpolator .P Quality of interpolation .P .BR Aspect type "= (0.0000..1.0000, default: 0.0000)" .P Aspect type .P Pixel aspect ratio presets .P .BR Manual Aspect "= (0.0000..1.0000, default: 0.5000)" .P Manual Aspect .P Manual Pixel Aspect ratio .P .RE .B Suboptions for bg_f0r_Distort0r .P .RS 2 .BR Amplitude "= (0.0000..1.0000, default: 1.0000)" .P Amplitude .P The amplitude of the plasma signal .P .BR Frequency "= (0.0000..1.0000, default: 0.0050)" .P Frequency .P The frequency of the plasma signal .P .RE .B Suboptions for bg_f0r_Edgeglow .P .RS 2 .BR lthresh "= (0.0000..1.0000, default: 0.0000)" .P lthresh .P threshold for edge lightening .P .BR lupscale "= (0.0000..1.0000, default: 0.0000)" .P lupscale .P multiplier for upscaling edge brightness .P .BR lredscale "= (0.0000..1.0000, default: 0.0000)" .P lredscale .P multiplier for downscaling non-edge brightness .P .RE .B Suboptions for bg_f0r_Flippo .P .RS 2 .BR X axis "=[1|0] (default: 0)" .P X axis .P Flipping on the horizontal axis .P .BR Y axis "=[1|0] (default: 0)" .P Y axis .P Flipping on the vertical axis .P .RE .B Suboptions for bg_f0r_Gamma .P .RS 2 .BR Gamma "= (0.0000..1.0000, default: 1.0000)" .P Gamma .P The gamma value .P .RE .B Suboptions for bg_f0r_Glow .P .RS 2 .BR Blur "= (0.0000..1.0000, default: 0.0000)" .P Blur .P Blur of the glow .P .RE .B Suboptions for bg_f0r_Hueshift0r .P .RS 2 .BR Hue "= (0.0000..1.0000, default: 0.0000)" .P Hue .P The shift value .P .RE .B Suboptions for bg_f0r_K-Means Clustering .P .RS 2 .BR Num "= (0.0000..1.0000, default: 0.5000)" .P Num .P The number of clusters .P .BR Dist weight "= (0.0000..1.0000, default: 0.5000)" .P Dist weight .P The weight on distance .P .RE .B Suboptions for bg_f0r_Lens Correction .P .RS 2 .BR xcenter "= (0.0000..1.0000, default: 0.5000)" .P xcenter .P .BR ycenter "= (0.0000..1.0000, default: 0.5000)" .P ycenter .P .BR correctionnearcenter "= (0.0000..1.0000, default: 0.5000)" .P correctionnearcenter .P .BR correctionnearedges "= (0.0000..1.0000, default: 0.5000)" .P correctionnearedges .P .BR brightness "= (0.0000..1.0000, default: 0.5000)" .P brightness .P .RE .B Suboptions for bg_f0r_LetterB0xed .P .RS 2 .BR Border Width "= (0.0000..1.0000, default: 0.4000)" .P Border Width .P .BR Transparency "=[1|0] (default: 0)" .P Transparency .P .RE .B Suboptions for bg_f0r_Levels .P .RS 2 .BR Channel "= (0.0000..1.0000, default: 0.0000)" .P Channel .P Channel to adjust levels .P .BR Input black level "= (0.0000..1.0000, default: 0.0000)" .P Input black level .P Input black level .P .BR Input white level "= (0.0000..1.0000, default: 1.0000)" .P Input white level .P Input white level .P .BR Gamma "= (0.0000..1.0000, default: 0.2500)" .P Gamma .P Gamma .P .BR Black output "= (0.0000..1.0000, default: 0.0000)" .P Black output .P Black output .P .BR White output "= (0.0000..1.0000, default: 1.0000)" .P White output .P White output .P .BR Show histogram "=[1|0] (default: 1)" .P Show histogram .P Show histogram .P .BR Histogram position "= (0.0000..1.0000, default: 3.0000)" .P Histogram position .P Histogram position .P .RE .B Suboptions for bg_f0r_Mask0Mate .P .RS 2 .BR Left "= (0.0000..1.0000, default: 0.2000)" .P Left .P .BR Right "= (0.0000..1.0000, default: 0.2000)" .P Right .P .BR Top "= (0.0000..1.0000, default: 0.2000)" .P Top .P .BR Bottom "= (0.0000..1.0000, default: 0.2000)" .P Bottom .P .BR Invert "=[1|0] (default: 0)" .P Invert .P Invert the mask, creates a hole in the frame. .P .BR Blur "= (0.0000..1.0000, default: 0.0000)" .P Blur .P Blur the outline of the mask .P .RE .B Suboptions for bg_f0r_Perspective .P .RS 2 .BR Top Left "=, (default: 0.000,0.000)" .P , and are in the range 0.0..1.0 .P Top Left .P .BR Top Right "=, (default: 1.000,0.000)" .P , and are in the range 0.0..1.0 .P Top Right .P .BR Bottom Left "=, (default: 0.000,1.000)" .P , and are in the range 0.0..1.0 .P Bottom Left .P .BR Bottom Right "=, (default: 1.000,1.000)" .P , and are in the range 0.0..1.0 .P Bottom Right .P .RE .B Suboptions for bg_f0r_SOP/Sat .P .RS 2 .BR rSlope "= (0.0000..1.0000, default: 1.0000)" .P rSlope .P Slope of the red color component .P .BR gSlope "= (0.0000..1.0000, default: 1.0000)" .P gSlope .P Slope of the green color component .P .BR bSlope "= (0.0000..1.0000, default: 1.0000)" .P bSlope .P Slope of the blue color component .P .BR aSlope "= (0.0000..1.0000, default: 1.0000)" .P aSlope .P Slope of the alpha component .P .BR rOffset "= (0.0000..1.0000, default: 0.0000)" .P rOffset .P Offset of the red color component .P .BR gOffset "= (0.0000..1.0000, default: 0.0000)" .P gOffset .P Offset of the green color component .P .BR bOffset "= (0.0000..1.0000, default: 0.0000)" .P bOffset .P Offset of the blue color component .P .BR aOffset "= (0.0000..1.0000, default: 0.0000)" .P aOffset .P Offset of the alpha component .P .BR rPower "= (0.0000..1.0000, default: 1.0000)" .P rPower .P Power (Gamma) of the red color component .P .BR gPower "= (0.0000..1.0000, default: 1.0000)" .P gPower .P Power (Gamma) of the green color component .P .BR bPower "= (0.0000..1.0000, default: 1.0000)" .P bPower .P Power (Gamma) of the blue color component .P .BR aPower "= (0.0000..1.0000, default: 1.0000)" .P aPower .P Power (Gamma) of the alpha component .P .BR saturation "= (0.0000..1.0000, default: 200.0000)" .P saturation .P Overall saturation .P .RE .B Suboptions for bg_f0r_Saturat0r .P .RS 2 .BR Saturation "= (0.0000..1.0000, default: 0.0000)" .P Saturation .P The saturation value .P .RE .B Suboptions for bg_f0r_Scale0Tilt .P .RS 2 .BR Clip left "= (0.0000..1.0000, default: 0.0000)" .P Clip left .P .BR Clip right "= (0.0000..1.0000, default: 0.0000)" .P Clip right .P .BR Clip top "= (0.0000..1.0000, default: 0.0000)" .P Clip top .P .BR Clip bottom "= (0.0000..1.0000, default: 0.0000)" .P Clip bottom .P .BR Scale X "= (0.0000..1.0000, default: 0.5000)" .P Scale X .P .BR Scale Y "= (0.0000..1.0000, default: 0.5000)" .P Scale Y .P .BR Tilt X "= (0.0000..1.0000, default: 0.5000)" .P Tilt X .P .BR Tilt Y "= (0.0000..1.0000, default: 0.5000)" .P Tilt Y .P .RE .B Suboptions for bg_f0r_Squareblur .P .RS 2 .BR Kernel size "= (0.0000..1.0000, default: 0.0000)" .P Kernel size .P The size of the kernel, as a proportion to its coverage of the image .P .RE .B Suboptions for bg_f0r_TehRoxx0r .P .RS 2 .BR Interval "= (0.0000..1.0000, default: 0.0100)" .P Interval .P Changing speed of small blocks .P .RE .B Suboptions for bg_f0r_Threshold0r .P .RS 2 .BR Threshold "= (0.0000..1.0000, default: 0.0000)" .P Threshold .P The threshold .P .RE .B Suboptions for bg_f0r_Tint0r .P .RS 2 .BR Map black to "=,, (default: 0.000,0.000,0.000)" .P , and are in the range 0.0..1.0 .P Map black to .P The color to map source color with null luminance .P .BR Map white to "=,, (default: 0.500,1.000,0.500)" .P , and are in the range 0.0..1.0 .P Map white to .P The color to map source color with full luminance .P .BR Tint amount "= (0.0000..1.0000, default: 0.2500)" .P Tint amount .P Amount of color .P .RE .B Suboptions for bg_f0r_Transparency .P .RS 2 .BR Transparency "= (0.0000..1.0000, default: 0.0000)" .P Transparency .P The transparency value .P .RE .B Suboptions for bg_f0r_Vertigo .P .RS 2 .BR PhaseIncrement "= (0.0000..1.0000, default: 0.0200)" .P PhaseIncrement .P Phase increment .P .BR Zoomrate "= (0.0000..1.0000, default: 1.0100)" .P Zoomrate .P Zoomrate .P .RE .B Suboptions for bg_f0r_Water .P .RS 2 .BR splash "=, (default: 0.000,0.000)" .P , and are in the range 0.0..1.0 .P splash .P make a big splash in the center .P .BR physics "= (0.0000..1.0000, default: 0.0000)" .P physics .P water density: from 1 to 4 .P .BR rain "=[1|0] (default: 0)" .P rain .P rain drops all over .P .BR distort "=[1|0] (default: 0)" .P distort .P distort all surface like dropping a bucket to the floor .P .BR smooth "=[1|0] (default: 0)" .P smooth .P smooth up all perturbations on the surface .P .BR surfer "=[1|0] (default: 0)" .P surfer .P surf the surface with a wandering finger .P .BR swirl "=[1|0] (default: 0)" .P swirl .P swirling whirpool in the center .P .BR randomize_swirl "=[1|0] (default: 0)" .P randomize_swirl .P randomize the swirling angle .P .RE .B Suboptions for bg_f0r_White Balance .P .RS 2 .BR Neutral Color "=,, (default: 1.000,1.000,1.000)" .P , and are in the range 0.0..1.0 .P Neutral Color .P Choose a color from the source image that should be white. .P .BR Green Tint "= (0.0000..1.0000, default: 1.2000)" .P Green Tint .P Adjust the level of green. .P .RE .B Suboptions for bg_f0r_alpha0ps .P .RS 2 .BR Display "= (0.0000..1.0000, default: 0.0000)" .P Display .P .BR Display input alpha "=[1|0] (default: 0)" .P Display input alpha .P .BR Operation "= (0.0000..1.0000, default: 0.0000)" .P Operation .P .BR Threshold "= (0.0000..1.0000, default: 0.5000)" .P Threshold .P .BR Shrink/grow amount "= (0.0000..1.0000, default: 0.3333)" .P Shrink/grow amount .P .BR Invert "=[1|0] (default: 0)" .P Invert .P .RE .B Suboptions for bg_f0r_alphagrad .P .RS 2 .BR Position "= (0.0000..1.0000, default: 0.5000)" .P Position .P .BR Transition width "=[1|0] (default: 0)" .P Transition width .P .BR Tilt "= (0.0000..1.0000, default: 0.5000)" .P Tilt .P .BR Min "= (0.0000..1.0000, default: 0.0000)" .P Min .P .BR Max "= (0.0000..1.0000, default: 1.0000)" .P Max .P .BR Operation "= (0.0000..1.0000, default: 0.0000)" .P Operation .P .RE .B Suboptions for bg_f0r_alphaspot .P .RS 2 .BR Shape "= (0.0000..1.0000, default: 0.0000)" .P Shape .P .BR Position X "= (0.0000..1.0000, default: 0.5000)" .P Position X .P .BR Position Y "= (0.0000..1.0000, default: 0.5000)" .P Position Y .P .BR Size X "= (0.0000..1.0000, default: 0.1000)" .P Size X .P .BR Size Y "= (0.0000..1.0000, default: 0.1000)" .P Size Y .P .BR Tilt "= (0.0000..1.0000, default: 0.5000)" .P Tilt .P .BR Transition width "= (0.0000..1.0000, default: 0.2000)" .P Transition width .P .BR Min "= (0.0000..1.0000, default: 0.0000)" .P Min .P .BR Max "= (0.0000..1.0000, default: 1.0000)" .P Max .P .BR Operation "= (0.0000..1.0000, default: 0.0000)" .P Operation .P .RE .B Suboptions for bg_f0r_bluescreen0r .P .RS 2 .BR Color "=,, (default: 0.000,240.000,0.000)" .P , and are in the range 0.0..1.0 .P Color .P The color to make transparent (B G R) .P .BR Distance "= (0.0000..1.0000, default: 127.0000)" .P Distance .P Distance to Color (127 is good) .P .RE .B Suboptions for bg_f0r_c0rners .P .RS 2 .BR Corner 1 X "= (0.0000..1.0000, default: 0.3333)" .P Corner 1 X .P X coordinate of corner 1 .P .BR Corner 1 Y "= (0.0000..1.0000, default: 0.3333)" .P Corner 1 Y .P Y coordinate of corner 1 .P .BR Corner 2 X "= (0.0000..1.0000, default: 0.6667)" .P Corner 2 X .P X coordinate of corner 2 .P .BR Corner 2 Y "= (0.0000..1.0000, default: 0.3333)" .P Corner 2 Y .P Y coordinate of corner 2 .P .BR Corner 3 X "= (0.0000..1.0000, default: 0.6667)" .P Corner 3 X .P X coordinate of corner 3 .P .BR Corner 3 Y "= (0.0000..1.0000, default: 0.6667)" .P Corner 3 Y .P Y coordinate of corner 3 .P .BR Corner 4 X "= (0.0000..1.0000, default: 0.3333)" .P Corner 4 X .P X coordinate of corner 4 .P .BR Corner 4 Y "= (0.0000..1.0000, default: 0.6667)" .P Corner 4 Y .P Y coordinate of corner 4 .P .BR Enable Stretch "=[1|0] (default: 0)" .P Enable Stretch .P Enable stretching .P .BR Stretch X "= (0.0000..1.0000, default: 0.5000)" .P Stretch X .P Amount of stretching in X direction .P .BR Stretch Y "= (0.0000..1.0000, default: 0.5000)" .P Stretch Y .P Amount of stretching in Y direction .P .BR Interpolator "= (0.0000..1.0000, default: 0.1667)" .P Interpolator .P Quality of interpolation .P .BR Transparent Background "=[1|0] (default: 0)" .P Transparent Background .P Makes background transparent .P .BR Feather Alpha "= (0.0000..1.0000, default: 0.0100)" .P Feather Alpha .P Makes smooth transition into transparent .P .RE .B Suboptions for bg_f0r_coloradj_RGB .P .RS 2 .BR R "= (0.0000..1.0000, default: 0.5000)" .P R .P Amount of red .P .BR G "= (0.0000..1.0000, default: 0.5000)" .P G .P Amount of green .P .BR B "= (0.0000..1.0000, default: 0.5000)" .P B .P Amount of blue .P .BR Action "= (0.0000..1.0000, default: 0.3333)" .P Action .P Type of color adjustment .P .BR Keep luma "=[1|0] (default: 1)" .P Keep luma .P Don't change brightness .P .BR Alpha controlled "=[1|0] (default: 0)" .P Alpha controlled .P Adjust only areas with nonzero alpha .P .BR Luma formula "= (0.0000..1.0000, default: 0.5000)" .P Luma formula .P .RE .B Suboptions for bg_f0r_delay0r .P .RS 2 .BR DelayTime "= (0.0000..1.0000, default: 0.0000)" .P DelayTime .P the delay time .P .RE .B Suboptions for bg_f0r_nosync0r .P .RS 2 .BR HSync "= (0.0000..1.0000, default: 0.0000)" .P HSync .P the hsync offset .P .RE .B Suboptions for bg_f0r_pixeliz0r .P .RS 2 .BR BlockSizeX "= (0.0000..1.0000, default: 0.4375)" .P BlockSizeX .P Horizontal size of one "pixel" .P .BR BlockSizeY "= (0.0000..1.0000, default: 0.4375)" .P BlockSizeY .P Vertical size of one "pixel" .P .RE .B Suboptions for bg_f0r_pr0be .P .RS 2 .BR Measurement "= (0.0000..1.0000, default: 0.0000)" .P Measurement .P What measurement to display .P .BR X "= (0.0000..1.0000, default: 0.5000)" .P X .P X position of probe .P .BR Y "= (0.0000..1.0000, default: 0.5000)" .P Y .P Y position of probe .P .BR X size "= (0.0000..1.0000, default: 0.2500)" .P X size .P X size of probe .P .BR Y size "= (0.0000..1.0000, default: 0.2500)" .P Y size .P Y size of probe .P .BR 256 scale "=[1|0] (default: 0)" .P 256 scale .P use 0-255 instead of 0.0-1.0 .P .BR Show alpha "=[1|0] (default: 0)" .P Show alpha .P Display alpha value too .P .BR Big window "=[1|0] (default: 0)" .P Big window .P Display more data .P .RE .B Suboptions for bg_f0r_pr0file .P .RS 2 .BR X "= (0.0000..1.0000, default: 0.5000)" .P X .P X position of profile .P .BR Y "= (0.0000..1.0000, default: 0.5000)" .P Y .P Y position of profile .P .BR Tilt "= (0.0000..1.0000, default: 0.5000)" .P Tilt .P Tilt of profile .P .BR Length "= (0.0000..1.0000, default: 0.1584)" .P Length .P Length of profile .P .BR Channel "= (0.0000..1.0000, default: 0.3750)" .P Channel .P Channel to numerically display .P .BR Marker 1 "= (0.0000..1.0000, default: -0.2000)" .P Marker 1 .P Position of marker 1 .P .BR Marker 2 "= (0.0000..1.0000, default: -0.2000)" .P Marker 2 .P Position of marker 2 .P .BR R trace "=[1|0] (default: 1)" .P R trace .P Show R trace on scope .P .BR G trace "=[1|0] (default: 1)" .P G trace .P Show G trace on scope .P .BR B trace "=[1|0] (default: 1)" .P B trace .P Show B trace on scope .P .BR Y trace "=[1|0] (default: 0)" .P Y trace .P Show Y' trace on scope .P .BR Pr trace "=[1|0] (default: 0)" .P Pr trace .P Show Pr trace on scope .P .BR Pb trace "=[1|0] (default: 0)" .P Pb trace .P Show Pb trace on scope .P .BR Alpha trace "=[1|0] (default: 0)" .P Alpha trace .P Show Alpha trace on scope .P .BR Display average "=[1|0] (default: 1)" .P Display average .P e .P .BR Display RMS "=[1|0] (default: 1)" .P Display RMS .P .BR Display minimum "=[1|0] (default: 0)" .P Display minimum .P .BR Display maximum "=[1|0] (default: 0)" .P Display maximum .P .BR 256 scale "=[1|0] (default: 0)" .P 256 scale .P use 0-255 instead of 0.0-1.0 .P .BR Color "= (0.0000..1.0000, default: 0.0000)" .P Color .P rec 601 or rec 709 .P .BR Crosshair color "= (0.0000..1.0000, default: 0.0000)" .P Crosshair color .P Color of the profile marker .P .RE .B Suboptions for bg_f0r_primaries .P .RS 2 .BR Factor "= (0.0000..1.0000, default: 1.0000)" .P Factor .P influence of mean px value. > 32 = 0 .P .RE .B Suboptions for bg_f0r_select0r .P .RS 2 .BR Color to select "=,, (default: 0.000,0.800,0.000)" .P , and are in the range 0.0..1.0 .P Color to select .P .BR Invert selection "=[1|0] (default: 0)" .P Invert selection .P .BR Delta R / A / Hue "= (0.0000..1.0000, default: 0.2000)" .P Delta R / A / Hue .P .BR Delta G / B / Chroma "= (0.0000..1.0000, default: 0.2000)" .P Delta G / B / Chroma .P .BR Delta B / I / I "= (0.0000..1.0000, default: 0.2000)" .P Delta B / I / I .P .BR Selection subspace "= (0.0000..1.0000, default: 0.0000)" .P Selection subspace .P .BR Subspace shape "= (0.0000..1.0000, default: 0.0000)" .P Subspace shape .P .BR Edge mode "= (0.0000..1.0000, default: 0.0000)" .P Edge mode .P .BR Operation "= (0.0000..1.0000, default: 0.0000)" .P Operation .P .RE .RE .B -vm .I (default: 1.000,1.000,1.000,1.000)" .P , , and are in the range 0.0..1.0 .P Text color .P .BR bg_color "=,,, (default: 0.000,0.000,0.000,1.000)" .P , , and are in the range 0.0..1.0 .P Background color .P .BR default_timescale "= (default: 25)" .P Default timescale .P For formats, which support only constant framerates, set the default timescale here .P .BR default_frame_duration "= (default: 1)" .P Default frame duration .P For formats, which support only constant framerates, set the default frame duration here .P .BR codec "=option[{suboptions}]" .P Supported options: raw v308 v408 v410 yuv2 yuv4 yv12 2vuy v210 rtjpeg jpeg mjpa png ffmpeg_mpg4 ffmpeg_msmpeg4v3 ffmpeg_msmpeg4v3_wmp ffmpeg_h263 ffmpeg_h263p ffmpeg_mjpg ffmpeg_rle ffmpeg_dv ffmpeg_dvcpro ffmpeg_dv50 ffmpeg_ffvhuff ffmpeg_ffv1 ffmpeg_dnxhd ffmpeg_imx x264 schroedinger yuvs .P Default: raw .P Codec .P .B Suboptions for codec=rtjpeg .P .RS 2 .BR rtjpeg_quality "= (0..100, default: 100)" .P Quality setting .P .BR rtjpeg_key_rate "= (default: 25)" .P Key frame interval .P .BR rtjpeg_luma_quant "= (default: 1)" .P Luma quantiser .P .BR rtjpeg_chroma_quant "= (default: 1)" .P Chroma quantiser .P .RE .B Suboptions for codec=jpeg .P .RS 2 .BR jpeg_quality "= (1..100, default: 95)" .P Quality .P .BR jpeg_usefloat "=[1|0] (default: 0)" .P Use float .P .RE .B Suboptions for codec=mjpa .P .RS 2 .BR jpeg_quality "= (1..100, default: 95)" .P Quality .P .BR jpeg_usefloat "=[1|0] (default: 0)" .P Use float .P .RE .B Suboptions for codec=png .P .RS 2 .BR png_compression_level "= (0..9, default: 9)" .P Compression Level .P .RE .B Suboptions for codec=ffmpeg_mpg4 .P .RS 2 .BR gop_size "= (0..300, default: 250)" .P GOP size (0 = intra only) .P .BR ff_scenechange_threshold "= (-1000000000..1000000000, default: 0)" .P Scenechange threshold .P Threshold for scene change detection. Negative values mean more sensitivity (more keyframes) .P .BR ff_scenechange_factor "= (default: 0)" .P Scenechange factor .P Multiplied by qscale for each frame and added to scene_change_score .P .BR ff_flag_closed_gop "=[1|0] (default: 0)" .P Close all GOPs .P .BR ff_flag2_strict_gop "=[1|0] (default: 0)" .P Strictly enforce GOP size .P .BR ff_max_b_frames "= (0..16, default: 0)" .P Max B-Frames .P Maximum number of B-frames between non B-frames .P .BR ff_b_frame_strategy "=[1|0] (default: 0)" .P Avoid B-frames in high motion scenes .P .BR ff_flag_ac_pred "=[1|0] (default: 0)" .P MPEG-4 AC prediction .P .BR ff_bit_rate_video "= (default: 800)" .P Bit rate (kbps) .P .BR ff_bit_rate_tolerance "= (default: 8000)" .P Bitrate tolerance (kbps) .P Number of bits the bitstream is allowed to diverge from the reference. Unused for constant quantizer encoding .P .BR ff_rc_min_rate "= (default: 0)" .P Minimum bitrate (kbps) .P Minimum bitrate (0 means arbitrary) .P .BR ff_rc_max_rate "= (default: 0)" .P Maximum bitrate (kbps) .P Maximum bitrate (0 means arbitrary) .P .BR ff_rc_buffer_size "= (default: 0)" .P RC buffer size .P Decoder bitstream buffer size in kbits. When encoding with max and/or min bitrate, this must be specified. .P .BR ff_rc_initial_cplx "= (0.0..99.0, default: 0.0)" .P Initial RC complexity .P .BR ff_rc_initial_buffer_occupancy "= (default: 0)" .P Initial RC buffer occupancy .P Number of kilobits which should be loaded into the rc buffer before encoding starts. Must not be larger than RC buffer size .P .BR ff_qmin "= (0..31, default: 2)" .P Minimum quantizer scale .P .BR ff_qmax "= (0..31, default: 31)" .P Maximum quantizer scale .P .BR ff_max_qdiff "= (0..31, default: 3)" .P Maximum quantizer difference .P Maximum quantizer difference between frames .P .BR ff_flag_qscale "=[1|0] (default: 0)" .P Use fixed quantizer .P Use fixed quality encoding .P .BR ff_qscale "= (1..31, default: 10)" .P Fixed quantizer .P Quantizer for fixed quality encoding. Lower means better, 1 is not recommended .P .BR ff_qcompress "= (0.00..1.00, default: 0.50)" .P Quantizer compression .P Amount of qscale change between easy & hard scenes .P .BR ff_qblur "= (0.00..1.00, default: 0.00)" .P Quantizer blur .P Amount of qscale smoothing over time .P .BR ff_quantizer_noise_shaping "= (0..3, default: 0)" .P Quantizer noise shaping .P Choose quantization such that noise will be masked by similar-frequency content in the image .P .BR ff_trellis "=[1|0] (default: 0)" .P Use trellis quantization .P Use trellis quantization (improves quality) .P .BR ff_i_quant_factor "= (-31.0..31.0, default: -0.8)" .P I quantizer factor .P Quantizer factor between P-frames and I-frames. If > 0 then the last P frame quantizer will be used (q= lastp_q*factor+offset). If < 0 then normal ratecontrol will be done (q= -normal_q*factor+offset) .P .BR ff_i_quant_offset "= (0.0..31.0, default: 0.0)" .P I quantizer offset .P Quantizer offset between P-frames and I-frames .P .BR ff_b_quant_factor "= (-31.00..31.00, default: 1.25)" .P B quantizer factor .P Quantizer factor between B-frames and non-B-frames .P .BR ff_b_quant_offset "= (0.00..31.00, default: 1.25)" .P B quantizer offset .P Quantizer offset between B-frames and non-B-frames if > 0 then the last p frame quantizer will be used (q= lastp_q*factor+offset) if < 0 then normal ratecontrol will be done (q= -normal_q*factor+offset) .P .BR ff_flag_cbp_rd "=[1|0] (default: 0)" .P CBP RD .P Use rate distortion optimization for cbp. This can only be used together with trellis quantization. .P .BR ff_me_method "=" .P Supported strings: Zero Phods Log X1 Epzs Full .P Default: Zero .P Motion estimation method .P .BR ff_me_cmp "=" .P Supported strings: SAD SSE SATD DCT PSNR BIT RD ZERO VSAD VSSE NSSE .P Default: SAD .P ME compare function .P Motion estimation compare function. SAD: Sum of absolute differences SSE: Sum of squared errors SATD: Sum of absolute Hadamard transformed differences DCT: Sum of absolute DCT transformed differences PSNR: Sum of squared quantization errors (low quality) BIT: Number of bits needed for the block RD: Rate distortion optimal (slow) ZERO: 0 VSAD: Sum of absolute vertical differences VSSE: Sum of squared vertical differences NSSE: Noise preserving sum of squared differences .P .BR ff_me_cmp_chroma "=[1|0] (default: 0)" .P Enable chroma ME compare .P .BR ff_me_range "= (0..1000, default: 0)" .P Motion estimation range .P Motion estimation search range (0 means unlimited) .P .BR ff_me_threshold "= (0..4000000, default: 0)" .P ME Theshold .P Motion estimation threshold. under which no motion estimation is performed, but instead the user specified motion vectors are used .P .BR ff_mb_decision "=" .P Supported strings: Use compare function Fewest bits Rate distoration .P Default: Use compare function .P MB decision mode .P .BR ff_dia_size "= (-9..9, default: 0)" .P ME diamond size & shape .P Motion estimation diamond size. Negative means shape adaptive. .P .BR ff_flag_gmc "=[1|0] (default: 0)" .P Use global motion compensation .P Warning: GMC is not supported by all decoders .P .BR ff_flag_4mv "=[1|0] (default: 0)" .P 4 MV per MB allowed .P Allow 4 motion vectors per macroblock (slightly better quality). Works better if MB decision mode is "Fewest bits" or "Rate distoration". .P .BR ff_flag_mv0 "=[1|0] (default: 0)" .P Always try a MB with MV=<0,0> .P .BR ff_flag_qp_rd "=[1|0] (default: 0)" .P QP RD .P Use rate distortion optimization for qp selection. Can only be used if MB decision mode is "Rate distoration" .P .BR ff_pre_me "= (0..2, default: 0)" .P ME pre-pass .P Motion estimation pre-pass 0: disabled 1: only after I-frames 2: always .P .BR ff_me_pre_cmp "=" .P Supported strings: SAD SSE SATD DCT PSNR BIT RD ZERO VSAD VSSE NSSE .P Default: SAD .P ME pre-pass compare function .P Motion estimation pre-pass compare function. SAD: Sum of absolute differences SSE: Sum of squared errors SATD: Sum of absolute Hadamard transformed differences DCT: Sum of absolute DCT transformed differences PSNR: Sum of squared quantization errors (low quality) BIT: Number of bits needed for the block RD: Rate distortion optimal (slow) ZERO: 0 VSAD: Sum of absolute vertical differences VSSE: Sum of squared vertical differences NSSE: Noise preserving sum of squared differences .P .BR ff_me_pre_cmp_chroma "=[1|0] (default: 0)" .P Enable chroma ME pre-pass compare .P .BR ff_pre_dia_size "= (-9..9, default: 0)" .P ME pre-pass diamond size & shape .P Motion estimation pre-pass diamond size. Negative means shape adaptive. .P .BR ff_flag_qpel "=[1|0] (default: 0)" .P Use qpel MC .P Use 1/4 pixel motion compensation. Warning: QPEL is not supported by all decoders. .P .BR ff_me_sub_cmp "=" .P Supported strings: SAD SSE SATD DCT PSNR BIT RD ZERO VSAD VSSE NSSE .P Default: SAD .P Subpixel ME compare function .P Subpixel motion estimation compare function. SAD: Sum of absolute differences SSE: Sum of squared errors SATD: Sum of absolute Hadamard transformed differences DCT: Sum of absolute DCT transformed differences PSNR: Sum of squared quantization errors (low quality) BIT: Number of bits needed for the block RD: Rate distortion optimal (slow) ZERO: 0 VSAD: Sum of absolute vertical differences VSSE: Sum of squared vertical differences NSSE: Noise preserving sum of squared differences .P .BR ff_me_sub_cmp_chroma "=[1|0] (default: 0)" .P Enable chroma subpixel ME compare .P .BR ff_me_subpel_quality "= (1..8, default: 8)" .P Subpel ME quality .P Subpel motion estimation refinement quality (for qpel). Higher values mean higher quality but slower encoding. .P .BR ff_lumi_masking "= (0.00..1.00, default: 0.00)" .P Luminance masking .P Encode very bright image parts with reduced quality. 0 means disabled, 0-0.3 is a sane range. .P .BR ff_dark_masking "= (0.00..1.00, default: 0.00)" .P Darkness masking .P Encode very dark image parts with reduced quality. 0 means disabled, 0-0.3 is a sane range. .P .BR ff_temporal_cplx_masking "= (0.00..1.00, default: 0.00)" .P Temporary complexity masking .P Encode very fast moving image parts with reduced quality. 0 means disabled. .P .BR ff_spatial_cplx_masking "= (0.00..1.00, default: 0.00)" .P Spatial complexity masking .P Encode very complex image parts with reduced quality. 0 means disabled, 0-0.5 is a sane range. .P .BR ff_border_masking "= (0.00..1.00, default: 0.00)" .P Border masking .P Encode image parts near the border with reduced quality.0 means disabled .P .BR ff_p_masking "= (0.00..1.00, default: 0.00)" .P Inter block masking .P Encode inter blocks with reduced quality (increases the quality of intra blocks). 0 means disabled, 1 will double the bits allocated for intra blocks. .P .BR ff_flag_normalize_aqp "=[1|0] (default: 0)" .P Normalize adaptive quantization .P When using masking, try to adjust the per macroblock quantizers to maintain the desired average .P .BR ff_strict_std_compliance "= (-2..2, default: 0)" .P Standards compliance .P 2 = Strictly conform to a older more strict version of the spec or reference software 1: Strictly conform to all the things in the spec no matter what consequences 0: Default -1: Allow unofficial extensions -2: Allow non standarized experimental things .P .BR ff_noise_reduction "= (0..2000, default: 0)" .P Noise reduction .P .BR ff_flag_gray "=[1|0] (default: 0)" .P Grayscale mode .P .BR ff_flag_bitexact "=[1|0] (default: 0)" .P Use only bitexact stuff .P Use only bitexact stuff (except (i)dct) .P .BR ff_thread_count "= (default: 1)" .P Number of threads to launch .P Spcify how many threads to launch .P .RE .B Suboptions for codec=ffmpeg_msmpeg4v3 .P .RS 2 .BR gop_size "= (0..300, default: 250)" .P GOP size (0 = intra only) .P .BR ff_scenechange_threshold "= (-1000000000..1000000000, default: 0)" .P Scenechange threshold .P Threshold for scene change detection. Negative values mean more sensitivity (more keyframes) .P .BR ff_scenechange_factor "= (default: 0)" .P Scenechange factor .P Multiplied by qscale for each frame and added to scene_change_score .P .BR ff_flag_closed_gop "=[1|0] (default: 0)" .P Close all GOPs .P .BR ff_flag2_strict_gop "=[1|0] (default: 0)" .P Strictly enforce GOP size .P .BR ff_bit_rate_video "= (default: 800)" .P Bit rate (kbps) .P .BR ff_bit_rate_tolerance "= (default: 8000)" .P Bitrate tolerance (kbps) .P Number of bits the bitstream is allowed to diverge from the reference. Unused for constant quantizer encoding .P .BR ff_rc_min_rate "= (default: 0)" .P Minimum bitrate (kbps) .P Minimum bitrate (0 means arbitrary) .P .BR ff_rc_max_rate "= (default: 0)" .P Maximum bitrate (kbps) .P Maximum bitrate (0 means arbitrary) .P .BR ff_rc_buffer_size "= (default: 0)" .P RC buffer size .P Decoder bitstream buffer size in kbits. When encoding with max and/or min bitrate, this must be specified. .P .BR ff_rc_initial_cplx "= (0.0..99.0, default: 0.0)" .P Initial RC complexity .P .BR ff_rc_initial_buffer_occupancy "= (default: 0)" .P Initial RC buffer occupancy .P Number of kilobits which should be loaded into the rc buffer before encoding starts. Must not be larger than RC buffer size .P .BR ff_qmin "= (0..31, default: 2)" .P Minimum quantizer scale .P .BR ff_qmax "= (0..31, default: 31)" .P Maximum quantizer scale .P .BR ff_max_qdiff "= (0..31, default: 3)" .P Maximum quantizer difference .P Maximum quantizer difference between frames .P .BR ff_flag_qscale "=[1|0] (default: 0)" .P Use fixed quantizer .P Use fixed quality encoding .P .BR ff_qscale "= (1..31, default: 10)" .P Fixed quantizer .P Quantizer for fixed quality encoding. Lower means better, 1 is not recommended .P .BR ff_qcompress "= (0.00..1.00, default: 0.50)" .P Quantizer compression .P Amount of qscale change between easy & hard scenes .P .BR ff_qblur "= (0.00..1.00, default: 0.00)" .P Quantizer blur .P Amount of qscale smoothing over time .P .BR ff_quantizer_noise_shaping "= (0..3, default: 0)" .P Quantizer noise shaping .P Choose quantization such that noise will be masked by similar-frequency content in the image .P .BR ff_trellis "=[1|0] (default: 0)" .P Use trellis quantization .P Use trellis quantization (improves quality) .P .BR ff_i_quant_factor "= (-31.0..31.0, default: -0.8)" .P I quantizer factor .P Quantizer factor between P-frames and I-frames. If > 0 then the last P frame quantizer will be used (q= lastp_q*factor+offset). If < 0 then normal ratecontrol will be done (q= -normal_q*factor+offset) .P .BR ff_i_quant_offset "= (0.0..31.0, default: 0.0)" .P I quantizer offset .P Quantizer offset between P-frames and I-frames .P .BR ff_me_method "=" .P Supported strings: Zero Phods Log X1 Epzs Full .P Default: Zero .P Motion estimation method .P .BR ff_me_cmp "=" .P Supported strings: SAD SSE SATD DCT PSNR BIT RD ZERO VSAD VSSE NSSE .P Default: SAD .P ME compare function .P Motion estimation compare function. SAD: Sum of absolute differences SSE: Sum of squared errors SATD: Sum of absolute Hadamard transformed differences DCT: Sum of absolute DCT transformed differences PSNR: Sum of squared quantization errors (low quality) BIT: Number of bits needed for the block RD: Rate distortion optimal (slow) ZERO: 0 VSAD: Sum of absolute vertical differences VSSE: Sum of squared vertical differences NSSE: Noise preserving sum of squared differences .P .BR ff_me_cmp_chroma "=[1|0] (default: 0)" .P Enable chroma ME compare .P .BR ff_me_range "= (0..1000, default: 0)" .P Motion estimation range .P Motion estimation search range (0 means unlimited) .P .BR ff_me_threshold "= (0..4000000, default: 0)" .P ME Theshold .P Motion estimation threshold. under which no motion estimation is performed, but instead the user specified motion vectors are used .P .BR ff_mb_decision "=" .P Supported strings: Use compare function Fewest bits Rate distoration .P Default: Use compare function .P MB decision mode .P .BR ff_dia_size "= (-9..9, default: 0)" .P ME diamond size & shape .P Motion estimation diamond size. Negative means shape adaptive. .P .BR ff_pre_me "= (0..2, default: 0)" .P ME pre-pass .P Motion estimation pre-pass 0: disabled 1: only after I-frames 2: always .P .BR ff_me_pre_cmp "=" .P Supported strings: SAD SSE SATD DCT PSNR BIT RD ZERO VSAD VSSE NSSE .P Default: SAD .P ME pre-pass compare function .P Motion estimation pre-pass compare function. SAD: Sum of absolute differences SSE: Sum of squared errors SATD: Sum of absolute Hadamard transformed differences DCT: Sum of absolute DCT transformed differences PSNR: Sum of squared quantization errors (low quality) BIT: Number of bits needed for the block RD: Rate distortion optimal (slow) ZERO: 0 VSAD: Sum of absolute vertical differences VSSE: Sum of squared vertical differences NSSE: Noise preserving sum of squared differences .P .BR ff_me_pre_cmp_chroma "=[1|0] (default: 0)" .P Enable chroma ME pre-pass compare .P .BR ff_pre_dia_size "= (-9..9, default: 0)" .P ME pre-pass diamond size & shape .P Motion estimation pre-pass diamond size. Negative means shape adaptive. .P .BR ff_lumi_masking "= (0.00..1.00, default: 0.00)" .P Luminance masking .P Encode very bright image parts with reduced quality. 0 means disabled, 0-0.3 is a sane range. .P .BR ff_dark_masking "= (0.00..1.00, default: 0.00)" .P Darkness masking .P Encode very dark image parts with reduced quality. 0 means disabled, 0-0.3 is a sane range. .P .BR ff_temporal_cplx_masking "= (0.00..1.00, default: 0.00)" .P Temporary complexity masking .P Encode very fast moving image parts with reduced quality. 0 means disabled. .P .BR ff_spatial_cplx_masking "= (0.00..1.00, default: 0.00)" .P Spatial complexity masking .P Encode very complex image parts with reduced quality. 0 means disabled, 0-0.5 is a sane range. .P .BR ff_border_masking "= (0.00..1.00, default: 0.00)" .P Border masking .P Encode image parts near the border with reduced quality.0 means disabled .P .BR ff_p_masking "= (0.00..1.00, default: 0.00)" .P Inter block masking .P Encode inter blocks with reduced quality (increases the quality of intra blocks). 0 means disabled, 1 will double the bits allocated for intra blocks. .P .BR ff_flag_normalize_aqp "=[1|0] (default: 0)" .P Normalize adaptive quantization .P When using masking, try to adjust the per macroblock quantizers to maintain the desired average .P .BR ff_strict_std_compliance "= (-2..2, default: 0)" .P Standards compliance .P 2 = Strictly conform to a older more strict version of the spec or reference software 1: Strictly conform to all the things in the spec no matter what consequences 0: Default -1: Allow unofficial extensions -2: Allow non standarized experimental things .P .BR ff_noise_reduction "= (0..2000, default: 0)" .P Noise reduction .P .BR ff_flag_gray "=[1|0] (default: 0)" .P Grayscale mode .P .BR ff_flag_bitexact "=[1|0] (default: 0)" .P Use only bitexact stuff .P Use only bitexact stuff (except (i)dct) .P .BR ff_thread_count "= (default: 1)" .P Number of threads to launch .P Spcify how many threads to launch .P .RE .B Suboptions for codec=ffmpeg_msmpeg4v3_wmp .P .RS 2 .BR gop_size "= (0..300, default: 250)" .P GOP size (0 = intra only) .P .BR ff_scenechange_threshold "= (-1000000000..1000000000, default: 0)" .P Scenechange threshold .P Threshold for scene change detection. Negative values mean more sensitivity (more keyframes) .P .BR ff_scenechange_factor "= (default: 0)" .P Scenechange factor .P Multiplied by qscale for each frame and added to scene_change_score .P .BR ff_flag_closed_gop "=[1|0] (default: 0)" .P Close all GOPs .P .BR ff_flag2_strict_gop "=[1|0] (default: 0)" .P Strictly enforce GOP size .P .BR ff_bit_rate_video "= (default: 800)" .P Bit rate (kbps) .P .BR ff_bit_rate_tolerance "= (default: 8000)" .P Bitrate tolerance (kbps) .P Number of bits the bitstream is allowed to diverge from the reference. Unused for constant quantizer encoding .P .BR ff_rc_min_rate "= (default: 0)" .P Minimum bitrate (kbps) .P Minimum bitrate (0 means arbitrary) .P .BR ff_rc_max_rate "= (default: 0)" .P Maximum bitrate (kbps) .P Maximum bitrate (0 means arbitrary) .P .BR ff_rc_buffer_size "= (default: 0)" .P RC buffer size .P Decoder bitstream buffer size in kbits. When encoding with max and/or min bitrate, this must be specified. .P .BR ff_rc_initial_cplx "= (0.0..99.0, default: 0.0)" .P Initial RC complexity .P .BR ff_rc_initial_buffer_occupancy "= (default: 0)" .P Initial RC buffer occupancy .P Number of kilobits which should be loaded into the rc buffer before encoding starts. Must not be larger than RC buffer size .P .BR ff_qmin "= (0..31, default: 2)" .P Minimum quantizer scale .P .BR ff_qmax "= (0..31, default: 31)" .P Maximum quantizer scale .P .BR ff_max_qdiff "= (0..31, default: 3)" .P Maximum quantizer difference .P Maximum quantizer difference between frames .P .BR ff_flag_qscale "=[1|0] (default: 0)" .P Use fixed quantizer .P Use fixed quality encoding .P .BR ff_qscale "= (1..31, default: 10)" .P Fixed quantizer .P Quantizer for fixed quality encoding. Lower means better, 1 is not recommended .P .BR ff_qcompress "= (0.00..1.00, default: 0.50)" .P Quantizer compression .P Amount of qscale change between easy & hard scenes .P .BR ff_qblur "= (0.00..1.00, default: 0.00)" .P Quantizer blur .P Amount of qscale smoothing over time .P .BR ff_quantizer_noise_shaping "= (0..3, default: 0)" .P Quantizer noise shaping .P Choose quantization such that noise will be masked by similar-frequency content in the image .P .BR ff_trellis "=[1|0] (default: 0)" .P Use trellis quantization .P Use trellis quantization (improves quality) .P .BR ff_i_quant_factor "= (-31.0..31.0, default: -0.8)" .P I quantizer factor .P Quantizer factor between P-frames and I-frames. If > 0 then the last P frame quantizer will be used (q= lastp_q*factor+offset). If < 0 then normal ratecontrol will be done (q= -normal_q*factor+offset) .P .BR ff_i_quant_offset "= (0.0..31.0, default: 0.0)" .P I quantizer offset .P Quantizer offset between P-frames and I-frames .P .BR ff_me_method "=" .P Supported strings: Zero Phods Log X1 Epzs Full .P Default: Zero .P Motion estimation method .P .BR ff_me_cmp "=" .P Supported strings: SAD SSE SATD DCT PSNR BIT RD ZERO VSAD VSSE NSSE .P Default: SAD .P ME compare function .P Motion estimation compare function. SAD: Sum of absolute differences SSE: Sum of squared errors SATD: Sum of absolute Hadamard transformed differences DCT: Sum of absolute DCT transformed differences PSNR: Sum of squared quantization errors (low quality) BIT: Number of bits needed for the block RD: Rate distortion optimal (slow) ZERO: 0 VSAD: Sum of absolute vertical differences VSSE: Sum of squared vertical differences NSSE: Noise preserving sum of squared differences .P .BR ff_me_cmp_chroma "=[1|0] (default: 0)" .P Enable chroma ME compare .P .BR ff_me_range "= (0..1000, default: 0)" .P Motion estimation range .P Motion estimation search range (0 means unlimited) .P .BR ff_me_threshold "= (0..4000000, default: 0)" .P ME Theshold .P Motion estimation threshold. under which no motion estimation is performed, but instead the user specified motion vectors are used .P .BR ff_mb_decision "=" .P Supported strings: Use compare function Fewest bits Rate distoration .P Default: Use compare function .P MB decision mode .P .BR ff_dia_size "= (-9..9, default: 0)" .P ME diamond size & shape .P Motion estimation diamond size. Negative means shape adaptive. .P .BR ff_pre_me "= (0..2, default: 0)" .P ME pre-pass .P Motion estimation pre-pass 0: disabled 1: only after I-frames 2: always .P .BR ff_me_pre_cmp "=" .P Supported strings: SAD SSE SATD DCT PSNR BIT RD ZERO VSAD VSSE NSSE .P Default: SAD .P ME pre-pass compare function .P Motion estimation pre-pass compare function. SAD: Sum of absolute differences SSE: Sum of squared errors SATD: Sum of absolute Hadamard transformed differences DCT: Sum of absolute DCT transformed differences PSNR: Sum of squared quantization errors (low quality) BIT: Number of bits needed for the block RD: Rate distortion optimal (slow) ZERO: 0 VSAD: Sum of absolute vertical differences VSSE: Sum of squared vertical differences NSSE: Noise preserving sum of squared differences .P .BR ff_me_pre_cmp_chroma "=[1|0] (default: 0)" .P Enable chroma ME pre-pass compare .P .BR ff_pre_dia_size "= (-9..9, default: 0)" .P ME pre-pass diamond size & shape .P Motion estimation pre-pass diamond size. Negative means shape adaptive. .P .BR ff_lumi_masking "= (0.00..1.00, default: 0.00)" .P Luminance masking .P Encode very bright image parts with reduced quality. 0 means disabled, 0-0.3 is a sane range. .P .BR ff_dark_masking "= (0.00..1.00, default: 0.00)" .P Darkness masking .P Encode very dark image parts with reduced quality. 0 means disabled, 0-0.3 is a sane range. .P .BR ff_temporal_cplx_masking "= (0.00..1.00, default: 0.00)" .P Temporary complexity masking .P Encode very fast moving image parts with reduced quality. 0 means disabled. .P .BR ff_spatial_cplx_masking "= (0.00..1.00, default: 0.00)" .P Spatial complexity masking .P Encode very complex image parts with reduced quality. 0 means disabled, 0-0.5 is a sane range. .P .BR ff_border_masking "= (0.00..1.00, default: 0.00)" .P Border masking .P Encode image parts near the border with reduced quality.0 means disabled .P .BR ff_p_masking "= (0.00..1.00, default: 0.00)" .P Inter block masking .P Encode inter blocks with reduced quality (increases the quality of intra blocks). 0 means disabled, 1 will double the bits allocated for intra blocks. .P .BR ff_flag_normalize_aqp "=[1|0] (default: 0)" .P Normalize adaptive quantization .P When using masking, try to adjust the per macroblock quantizers to maintain the desired average .P .BR ff_strict_std_compliance "= (-2..2, default: 0)" .P Standards compliance .P 2 = Strictly conform to a older more strict version of the spec or reference software 1: Strictly conform to all the things in the spec no matter what consequences 0: Default -1: Allow unofficial extensions -2: Allow non standarized experimental things .P .BR ff_noise_reduction "= (0..2000, default: 0)" .P Noise reduction .P .BR ff_flag_gray "=[1|0] (default: 0)" .P Grayscale mode .P .BR ff_flag_bitexact "=[1|0] (default: 0)" .P Use only bitexact stuff .P Use only bitexact stuff (except (i)dct) .P .BR ff_thread_count "= (default: 1)" .P Number of threads to launch .P Spcify how many threads to launch .P .RE .B Suboptions for codec=ffmpeg_h263 .P .RS 2 .BR gop_size "= (0..300, default: 250)" .P GOP size (0 = intra only) .P .BR ff_scenechange_threshold "= (-1000000000..1000000000, default: 0)" .P Scenechange threshold .P Threshold for scene change detection. Negative values mean more sensitivity (more keyframes) .P .BR ff_scenechange_factor "= (default: 0)" .P Scenechange factor .P Multiplied by qscale for each frame and added to scene_change_score .P .BR ff_flag_closed_gop "=[1|0] (default: 0)" .P Close all GOPs .P .BR ff_flag2_strict_gop "=[1|0] (default: 0)" .P Strictly enforce GOP size .P .BR ff_bit_rate_video "= (default: 800)" .P Bit rate (kbps) .P .BR ff_bit_rate_tolerance "= (default: 8000)" .P Bitrate tolerance (kbps) .P Number of bits the bitstream is allowed to diverge from the reference. Unused for constant quantizer encoding .P .BR ff_rc_min_rate "= (default: 0)" .P Minimum bitrate (kbps) .P Minimum bitrate (0 means arbitrary) .P .BR ff_rc_max_rate "= (default: 0)" .P Maximum bitrate (kbps) .P Maximum bitrate (0 means arbitrary) .P .BR ff_rc_buffer_size "= (default: 0)" .P RC buffer size .P Decoder bitstream buffer size in kbits. When encoding with max and/or min bitrate, this must be specified. .P .BR ff_rc_initial_cplx "= (0.0..99.0, default: 0.0)" .P Initial RC complexity .P .BR ff_rc_initial_buffer_occupancy "= (default: 0)" .P Initial RC buffer occupancy .P Number of kilobits which should be loaded into the rc buffer before encoding starts. Must not be larger than RC buffer size .P .BR ff_qmin "= (0..31, default: 2)" .P Minimum quantizer scale .P .BR ff_qmax "= (0..31, default: 31)" .P Maximum quantizer scale .P .BR ff_max_qdiff "= (0..31, default: 3)" .P Maximum quantizer difference .P Maximum quantizer difference between frames .P .BR ff_flag_qscale "=[1|0] (default: 0)" .P Use fixed quantizer .P Use fixed quality encoding .P .BR ff_qscale "= (1..31, default: 10)" .P Fixed quantizer .P Quantizer for fixed quality encoding. Lower means better, 1 is not recommended .P .BR ff_qcompress "= (0.00..1.00, default: 0.50)" .P Quantizer compression .P Amount of qscale change between easy & hard scenes .P .BR ff_qblur "= (0.00..1.00, default: 0.00)" .P Quantizer blur .P Amount of qscale smoothing over time .P .BR ff_quantizer_noise_shaping "= (0..3, default: 0)" .P Quantizer noise shaping .P Choose quantization such that noise will be masked by similar-frequency content in the image .P .BR ff_trellis "=[1|0] (default: 0)" .P Use trellis quantization .P Use trellis quantization (improves quality) .P .BR ff_i_quant_factor "= (-31.0..31.0, default: -0.8)" .P I quantizer factor .P Quantizer factor between P-frames and I-frames. If > 0 then the last P frame quantizer will be used (q= lastp_q*factor+offset). If < 0 then normal ratecontrol will be done (q= -normal_q*factor+offset) .P .BR ff_i_quant_offset "= (0.0..31.0, default: 0.0)" .P I quantizer offset .P Quantizer offset between P-frames and I-frames .P .BR ff_me_method "=" .P Supported strings: Zero Phods Log X1 Epzs Full .P Default: Zero .P Motion estimation method .P .BR ff_me_cmp "=" .P Supported strings: SAD SSE SATD DCT PSNR BIT RD ZERO VSAD VSSE NSSE .P Default: SAD .P ME compare function .P Motion estimation compare function. SAD: Sum of absolute differences SSE: Sum of squared errors SATD: Sum of absolute Hadamard transformed differences DCT: Sum of absolute DCT transformed differences PSNR: Sum of squared quantization errors (low quality) BIT: Number of bits needed for the block RD: Rate distortion optimal (slow) ZERO: 0 VSAD: Sum of absolute vertical differences VSSE: Sum of squared vertical differences NSSE: Noise preserving sum of squared differences .P .BR ff_me_cmp_chroma "=[1|0] (default: 0)" .P Enable chroma ME compare .P .BR ff_me_range "= (0..1000, default: 0)" .P Motion estimation range .P Motion estimation search range (0 means unlimited) .P .BR ff_me_threshold "= (0..4000000, default: 0)" .P ME Theshold .P Motion estimation threshold. under which no motion estimation is performed, but instead the user specified motion vectors are used .P .BR ff_mb_decision "=" .P Supported strings: Use compare function Fewest bits Rate distoration .P Default: Use compare function .P MB decision mode .P .BR ff_dia_size "= (-9..9, default: 0)" .P ME diamond size & shape .P Motion estimation diamond size. Negative means shape adaptive. .P .BR ff_flag_4mv "=[1|0] (default: 0)" .P 4 MV per MB allowed .P Allow 4 motion vectors per macroblock (slightly better quality). Works better if MB decision mode is "Fewest bits" or "Rate distoration". .P .BR ff_pre_me "= (0..2, default: 0)" .P ME pre-pass .P Motion estimation pre-pass 0: disabled 1: only after I-frames 2: always .P .BR ff_me_pre_cmp "=" .P Supported strings: SAD SSE SATD DCT PSNR BIT RD ZERO VSAD VSSE NSSE .P Default: SAD .P ME pre-pass compare function .P Motion estimation pre-pass compare function. SAD: Sum of absolute differences SSE: Sum of squared errors SATD: Sum of absolute Hadamard transformed differences DCT: Sum of absolute DCT transformed differences PSNR: Sum of squared quantization errors (low quality) BIT: Number of bits needed for the block RD: Rate distortion optimal (slow) ZERO: 0 VSAD: Sum of absolute vertical differences VSSE: Sum of squared vertical differences NSSE: Noise preserving sum of squared differences .P .BR ff_me_pre_cmp_chroma "=[1|0] (default: 0)" .P Enable chroma ME pre-pass compare .P .BR ff_pre_dia_size "= (-9..9, default: 0)" .P ME pre-pass diamond size & shape .P Motion estimation pre-pass diamond size. Negative means shape adaptive. .P .BR ff_lumi_masking "= (0.00..1.00, default: 0.00)" .P Luminance masking .P Encode very bright image parts with reduced quality. 0 means disabled, 0-0.3 is a sane range. .P .BR ff_dark_masking "= (0.00..1.00, default: 0.00)" .P Darkness masking .P Encode very dark image parts with reduced quality. 0 means disabled, 0-0.3 is a sane range. .P .BR ff_temporal_cplx_masking "= (0.00..1.00, default: 0.00)" .P Temporary complexity masking .P Encode very fast moving image parts with reduced quality. 0 means disabled. .P .BR ff_spatial_cplx_masking "= (0.00..1.00, default: 0.00)" .P Spatial complexity masking .P Encode very complex image parts with reduced quality. 0 means disabled, 0-0.5 is a sane range. .P .BR ff_border_masking "= (0.00..1.00, default: 0.00)" .P Border masking .P Encode image parts near the border with reduced quality.0 means disabled .P .BR ff_p_masking "= (0.00..1.00, default: 0.00)" .P Inter block masking .P Encode inter blocks with reduced quality (increases the quality of intra blocks). 0 means disabled, 1 will double the bits allocated for intra blocks. .P .BR ff_flag_normalize_aqp "=[1|0] (default: 0)" .P Normalize adaptive quantization .P When using masking, try to adjust the per macroblock quantizers to maintain the desired average .P .BR ff_strict_std_compliance "= (-2..2, default: 0)" .P Standards compliance .P 2 = Strictly conform to a older more strict version of the spec or reference software 1: Strictly conform to all the things in the spec no matter what consequences 0: Default -1: Allow unofficial extensions -2: Allow non standarized experimental things .P .BR ff_noise_reduction "= (0..2000, default: 0)" .P Noise reduction .P .BR ff_flag_gray "=[1|0] (default: 0)" .P Grayscale mode .P .BR ff_flag_bitexact "=[1|0] (default: 0)" .P Use only bitexact stuff .P Use only bitexact stuff (except (i)dct) .P .BR ff_thread_count "= (default: 1)" .P Number of threads to launch .P Spcify how many threads to launch .P .BR ff_flag_obmc "=[1|0] (default: 0)" .P OBMC .P Overlapped block motion compensation (only supported with simple MB decision) .P .RE .B Suboptions for codec=ffmpeg_h263p .P .RS 2 .BR gop_size "= (0..300, default: 250)" .P GOP size (0 = intra only) .P .BR ff_scenechange_threshold "= (-1000000000..1000000000, default: 0)" .P Scenechange threshold .P Threshold for scene change detection. Negative values mean more sensitivity (more keyframes) .P .BR ff_scenechange_factor "= (default: 0)" .P Scenechange factor .P Multiplied by qscale for each frame and added to scene_change_score .P .BR ff_flag_closed_gop "=[1|0] (default: 0)" .P Close all GOPs .P .BR ff_flag2_strict_gop "=[1|0] (default: 0)" .P Strictly enforce GOP size .P .BR ff_bit_rate_video "= (default: 800)" .P Bit rate (kbps) .P .BR ff_bit_rate_tolerance "= (default: 8000)" .P Bitrate tolerance (kbps) .P Number of bits the bitstream is allowed to diverge from the reference. Unused for constant quantizer encoding .P .BR ff_rc_min_rate "= (default: 0)" .P Minimum bitrate (kbps) .P Minimum bitrate (0 means arbitrary) .P .BR ff_rc_max_rate "= (default: 0)" .P Maximum bitrate (kbps) .P Maximum bitrate (0 means arbitrary) .P .BR ff_rc_buffer_size "= (default: 0)" .P RC buffer size .P Decoder bitstream buffer size in kbits. When encoding with max and/or min bitrate, this must be specified. .P .BR ff_rc_initial_cplx "= (0.0..99.0, default: 0.0)" .P Initial RC complexity .P .BR ff_rc_initial_buffer_occupancy "= (default: 0)" .P Initial RC buffer occupancy .P Number of kilobits which should be loaded into the rc buffer before encoding starts. Must not be larger than RC buffer size .P .BR ff_qmin "= (0..31, default: 2)" .P Minimum quantizer scale .P .BR ff_qmax "= (0..31, default: 31)" .P Maximum quantizer scale .P .BR ff_max_qdiff "= (0..31, default: 3)" .P Maximum quantizer difference .P Maximum quantizer difference between frames .P .BR ff_flag_qscale "=[1|0] (default: 0)" .P Use fixed quantizer .P Use fixed quality encoding .P .BR ff_qscale "= (1..31, default: 10)" .P Fixed quantizer .P Quantizer for fixed quality encoding. Lower means better, 1 is not recommended .P .BR ff_qcompress "= (0.00..1.00, default: 0.50)" .P Quantizer compression .P Amount of qscale change between easy & hard scenes .P .BR ff_qblur "= (0.00..1.00, default: 0.00)" .P Quantizer blur .P Amount of qscale smoothing over time .P .BR ff_quantizer_noise_shaping "= (0..3, default: 0)" .P Quantizer noise shaping .P Choose quantization such that noise will be masked by similar-frequency content in the image .P .BR ff_trellis "=[1|0] (default: 0)" .P Use trellis quantization .P Use trellis quantization (improves quality) .P .BR ff_i_quant_factor "= (-31.0..31.0, default: -0.8)" .P I quantizer factor .P Quantizer factor between P-frames and I-frames. If > 0 then the last P frame quantizer will be used (q= lastp_q*factor+offset). If < 0 then normal ratecontrol will be done (q= -normal_q*factor+offset) .P .BR ff_i_quant_offset "= (0.0..31.0, default: 0.0)" .P I quantizer offset .P Quantizer offset between P-frames and I-frames .P .BR ff_me_method "=" .P Supported strings: Zero Phods Log X1 Epzs Full .P Default: Zero .P Motion estimation method .P .BR ff_me_cmp "=" .P Supported strings: SAD SSE SATD DCT PSNR BIT RD ZERO VSAD VSSE NSSE .P Default: SAD .P ME compare function .P Motion estimation compare function. SAD: Sum of absolute differences SSE: Sum of squared errors SATD: Sum of absolute Hadamard transformed differences DCT: Sum of absolute DCT transformed differences PSNR: Sum of squared quantization errors (low quality) BIT: Number of bits needed for the block RD: Rate distortion optimal (slow) ZERO: 0 VSAD: Sum of absolute vertical differences VSSE: Sum of squared vertical differences NSSE: Noise preserving sum of squared differences .P .BR ff_me_cmp_chroma "=[1|0] (default: 0)" .P Enable chroma ME compare .P .BR ff_me_range "= (0..1000, default: 0)" .P Motion estimation range .P Motion estimation search range (0 means unlimited) .P .BR ff_me_threshold "= (0..4000000, default: 0)" .P ME Theshold .P Motion estimation threshold. under which no motion estimation is performed, but instead the user specified motion vectors are used .P .BR ff_mb_decision "=" .P Supported strings: Use compare function Fewest bits Rate distoration .P Default: Use compare function .P MB decision mode .P .BR ff_dia_size "= (-9..9, default: 0)" .P ME diamond size & shape .P Motion estimation diamond size. Negative means shape adaptive. .P .BR ff_flag_4mv "=[1|0] (default: 0)" .P 4 MV per MB allowed .P Allow 4 motion vectors per macroblock (slightly better quality). Works better if MB decision mode is "Fewest bits" or "Rate distoration". .P .BR ff_pre_me "= (0..2, default: 0)" .P ME pre-pass .P Motion estimation pre-pass 0: disabled 1: only after I-frames 2: always .P .BR ff_me_pre_cmp "=" .P Supported strings: SAD SSE SATD DCT PSNR BIT RD ZERO VSAD VSSE NSSE .P Default: SAD .P ME pre-pass compare function .P Motion estimation pre-pass compare function. SAD: Sum of absolute differences SSE: Sum of squared errors SATD: Sum of absolute Hadamard transformed differences DCT: Sum of absolute DCT transformed differences PSNR: Sum of squared quantization errors (low quality) BIT: Number of bits needed for the block RD: Rate distortion optimal (slow) ZERO: 0 VSAD: Sum of absolute vertical differences VSSE: Sum of squared vertical differences NSSE: Noise preserving sum of squared differences .P .BR ff_me_pre_cmp_chroma "=[1|0] (default: 0)" .P Enable chroma ME pre-pass compare .P .BR ff_pre_dia_size "= (-9..9, default: 0)" .P ME pre-pass diamond size & shape .P Motion estimation pre-pass diamond size. Negative means shape adaptive. .P .BR ff_lumi_masking "= (0.00..1.00, default: 0.00)" .P Luminance masking .P Encode very bright image parts with reduced quality. 0 means disabled, 0-0.3 is a sane range. .P .BR ff_dark_masking "= (0.00..1.00, default: 0.00)" .P Darkness masking .P Encode very dark image parts with reduced quality. 0 means disabled, 0-0.3 is a sane range. .P .BR ff_temporal_cplx_masking "= (0.00..1.00, default: 0.00)" .P Temporary complexity masking .P Encode very fast moving image parts with reduced quality. 0 means disabled. .P .BR ff_spatial_cplx_masking "= (0.00..1.00, default: 0.00)" .P Spatial complexity masking .P Encode very complex image parts with reduced quality. 0 means disabled, 0-0.5 is a sane range. .P .BR ff_border_masking "= (0.00..1.00, default: 0.00)" .P Border masking .P Encode image parts near the border with reduced quality.0 means disabled .P .BR ff_p_masking "= (0.00..1.00, default: 0.00)" .P Inter block masking .P Encode inter blocks with reduced quality (increases the quality of intra blocks). 0 means disabled, 1 will double the bits allocated for intra blocks. .P .BR ff_flag_normalize_aqp "=[1|0] (default: 0)" .P Normalize adaptive quantization .P When using masking, try to adjust the per macroblock quantizers to maintain the desired average .P .BR ff_strict_std_compliance "= (-2..2, default: 0)" .P Standards compliance .P 2 = Strictly conform to a older more strict version of the spec or reference software 1: Strictly conform to all the things in the spec no matter what consequences 0: Default -1: Allow unofficial extensions -2: Allow non standarized experimental things .P .BR ff_noise_reduction "= (0..2000, default: 0)" .P Noise reduction .P .BR ff_flag_gray "=[1|0] (default: 0)" .P Grayscale mode .P .BR ff_flag_bitexact "=[1|0] (default: 0)" .P Use only bitexact stuff .P Use only bitexact stuff (except (i)dct) .P .BR ff_thread_count "= (default: 1)" .P Number of threads to launch .P Spcify how many threads to launch .P .BR ff_flag_h263p_aiv "=[1|0] (default: 0)" .P Alternative inter vlc .P .BR ff_flag_obmc "=[1|0] (default: 0)" .P OBMC .P Overlapped block motion compensation (only supported with simple MB decision) .P .RE .B Suboptions for codec=ffmpeg_mjpg .P .RS 2 .BR ff_bit_rate_video "= (default: 800)" .P Bit rate (kbps) .P .BR ff_bit_rate_tolerance "= (default: 8000)" .P Bitrate tolerance (kbps) .P Number of bits the bitstream is allowed to diverge from the reference. Unused for constant quantizer encoding .P .BR ff_rc_min_rate "= (default: 0)" .P Minimum bitrate (kbps) .P Minimum bitrate (0 means arbitrary) .P .BR ff_rc_max_rate "= (default: 0)" .P Maximum bitrate (kbps) .P Maximum bitrate (0 means arbitrary) .P .BR ff_rc_buffer_size "= (default: 0)" .P RC buffer size .P Decoder bitstream buffer size in kbits. When encoding with max and/or min bitrate, this must be specified. .P .BR ff_rc_initial_cplx "= (0.0..99.0, default: 0.0)" .P Initial RC complexity .P .BR ff_rc_initial_buffer_occupancy "= (default: 0)" .P Initial RC buffer occupancy .P Number of kilobits which should be loaded into the rc buffer before encoding starts. Must not be larger than RC buffer size .P .BR ff_qmin "= (0..31, default: 2)" .P Minimum quantizer scale .P .BR ff_qmax "= (0..31, default: 31)" .P Maximum quantizer scale .P .BR ff_max_qdiff "= (0..31, default: 3)" .P Maximum quantizer difference .P Maximum quantizer difference between frames .P .BR ff_flag_qscale "=[1|0] (default: 0)" .P Use fixed quantizer .P Use fixed quality encoding .P .BR ff_qscale "= (1..31, default: 10)" .P Fixed quantizer .P Quantizer for fixed quality encoding. Lower means better, 1 is not recommended .P .BR ff_qcompress "= (0.00..1.00, default: 0.50)" .P Quantizer compression .P Amount of qscale change between easy & hard scenes .P .BR ff_qblur "= (0.00..1.00, default: 0.00)" .P Quantizer blur .P Amount of qscale smoothing over time .P .BR ff_quantizer_noise_shaping "= (0..3, default: 0)" .P Quantizer noise shaping .P Choose quantization such that noise will be masked by similar-frequency content in the image .P .BR ff_trellis "=[1|0] (default: 0)" .P Use trellis quantization .P Use trellis quantization (improves quality) .P .BR ff_lumi_masking "= (0.00..1.00, default: 0.00)" .P Luminance masking .P Encode very bright image parts with reduced quality. 0 means disabled, 0-0.3 is a sane range. .P .BR ff_dark_masking "= (0.00..1.00, default: 0.00)" .P Darkness masking .P Encode very dark image parts with reduced quality. 0 means disabled, 0-0.3 is a sane range. .P .BR ff_temporal_cplx_masking "= (0.00..1.00, default: 0.00)" .P Temporary complexity masking .P Encode very fast moving image parts with reduced quality. 0 means disabled. .P .BR ff_spatial_cplx_masking "= (0.00..1.00, default: 0.00)" .P Spatial complexity masking .P Encode very complex image parts with reduced quality. 0 means disabled, 0-0.5 is a sane range. .P .BR ff_border_masking "= (0.00..1.00, default: 0.00)" .P Border masking .P Encode image parts near the border with reduced quality.0 means disabled .P .BR ff_p_masking "= (0.00..1.00, default: 0.00)" .P Inter block masking .P Encode inter blocks with reduced quality (increases the quality of intra blocks). 0 means disabled, 1 will double the bits allocated for intra blocks. .P .BR ff_flag_normalize_aqp "=[1|0] (default: 0)" .P Normalize adaptive quantization .P When using masking, try to adjust the per macroblock quantizers to maintain the desired average .P .BR ff_strict_std_compliance "= (-2..2, default: 0)" .P Standards compliance .P 2 = Strictly conform to a older more strict version of the spec or reference software 1: Strictly conform to all the things in the spec no matter what consequences 0: Default -1: Allow unofficial extensions -2: Allow non standarized experimental things .P .BR ff_noise_reduction "= (0..2000, default: 0)" .P Noise reduction .P .BR ff_flag_gray "=[1|0] (default: 0)" .P Grayscale mode .P .BR ff_flag_bitexact "=[1|0] (default: 0)" .P Use only bitexact stuff .P Use only bitexact stuff (except (i)dct) .P .BR ff_thread_count "= (default: 1)" .P Number of threads to launch .P Spcify how many threads to launch .P .RE .B Suboptions for codec=ffmpeg_ffv1 .P .RS 2 .BR ff_coder_type "=" .P Supported strings: VLC Arithmetic .P Default: VLC .P Coder type .P .RE .B Suboptions for codec=ffmpeg_imx .P .RS 2 .BR imx_bitrate "=" .P Supported strings: 30 40 50 .P Default: 50 .P Bitrate (Mbps) .P .BR imx_strip_vbi "= (default: 1)" .P Strip VBI .P .RE .B Suboptions for codec=x264 .P .RS 2 .BR x264_i_keyint_max "= (default: 250)" .P Maximum GOP size .P .BR x264_i_keyint_min "= (default: 25)" .P Minimum GOP size .P .BR x264_i_scenecut_threshold "= (default: 40)" .P Scenecut threshold .P How aggressively to insert extra I-frames .P .BR x264_i_bframe "= (0..16, default: 0)" .P B-Frames .P Number of B-frames between I and P .P .BR x264_i_bframe_adaptive "=" .P Supported strings: None Fast Trellis .P Default: Fast .P Adaptive B-frame decision .P .BR x264_i_bframe_bias "= (-90..100, default: 0)" .P B-frame bias .P Influences how often B-frames are used .P .BR x264_i_bframe_pyramid "=" .P Supported strings: None Strict Normal .P Default: Normal .P B-frame pyramid .P Keep some B-frames as references .P .BR x264_i_rc_method "=" .P Supported strings: Constant quality CRF based VBR Average bitrate .P Default: CRF based VBR .P Ratecontrol method .P Ratecontrol method: Constant quality: Specify a quantizer parameter below CRF based VBR: Specify a rate factor below Average bitrate: Specify a bitrate below Selecting 2-pass encoding will force Average bitrate. .P .BR x264_i_bitrate "= (default: 0)" .P Bitrate .P Bitrate in kbit/s. 0 means VBR (recommended) .P .BR x264_f_rate_tolerance "= (0.0..100.0, default: 1.0)" .P Bitrate tolerance .P Allowed variance of average bitrate .P .BR x264_i_vbv_max_bitrate "= (default: 0)" .P Maximum local bitrate .P Sets a maximum local bitrate in kbits/s. .P .BR x264_i_vbv_buffer_size "= (default: 0)" .P VBV Buffer size .P Averaging period for the maximum local bitrate. Measured in kbits. .P .BR x264_f_vbv_buffer_init "= (0.00..1.00, default: 0.90)" .P Initial VBV buffer occupancy .P Sets the initial VBV buffer occupancy as a fraction of the buffer size. .P .BR x264_b_psy "=[1|0] (default: 1)" .P Psy optimizations .P Psychovisual optimization .P .BR x264_f_psy_rd "= (0.00..10.00, default: 1.00)" .P Psy RD strength .P Strength of psychovisual optimization: RD (requires Partition decision >= 6) .P .BR x264_f_psy_trellis "= (0.00..10.00, default: 0.00)" .P Psy trellis strength .P Strength of psychovisual optimization (requires trellis) .P .BR x264_b_mb_tree "=[1|0] (default: 1)" .P Macroblock-tree ratecontrol .P .BR x264_i_lookahead "= (0..250, default: 40)" .P Lookahead .P Number of frames for frametype lookahead .P .BR x264_f_rf_constant "= (0..51, default: 23)" .P Nominal Quantizer parameter .P This selects the nominal quantizer to use (1 to 51). Lower values result in better fidelity, but higher bitrates. 26 is a good default value. 0 means lossless. .P .BR x264_i_qp_constant "= (0..51, default: 23)" .P Quantizer parameter .P This selects the quantizer to use (1 to 51). Lower values result in better fidelity, but higher bitrates. 26 is a good default value. 0 means lossless. .P .BR x264_i_qp_min "= (0..51, default: 10)" .P Minimum quantizer parameter .P Minimum quantizer parameter .P .BR x264_i_qp_max "= (0..51, default: 51)" .P Maximum quantizer parameter .P Maximum quantizer parameter .P .BR x264_i_qp_step "= (1..50, default: 4)" .P Maximum QP step .P Maximum quantizer step .P .BR x264_f_ip_factor "= (default: 1.40)" .P QP factor between I and P .P .BR x264_f_pb_factor "= (default: 1.30)" .P QP factor between P and B .P .BR x264_i_aq_mode "=" .P Supported strings: None Variance AQ (complexity mask) Autovariance AQ (experimental) .P Default: Variance AQ (complexity mask) .P Adaptive quantization .P .BR x264_f_aq_strength "= (0.50..1.50, default: 1.00)" .P AQ strength .P Adaptive quantization strength: Reduces blocking and blurring in flat and textured areas .P .BR x264_f_qcompress "= (0.00..1.00, default: 0.60)" .P QP curve compression .P Only for 2-pass encoding .P .BR x264_f_qblur "= (default: 0.50)" .P QP Reduce fluctuations in QP (after curve compression) .P Only for 2-pass encoding .P .BR x264_f_complexity_blur "= (default: 20.00)" .P Temporally blur complexity .P Only for 2-pass encoding .P .BR x264_i_chroma_qp_offset "= (default: 0)" .P QP difference between chroma and luma .P .BR x264_i_luma_deadzone_0 "= (default: 21)" .P Inter luma quantization deadzone .P .BR x264_i_luma_deadzone_1 "= (default: 11)" .P Intra luma quantization deadzone .P .BR x264_analyse_8x8_transform "=[1|0] (default: 0)" .P 8x8 transform .P .BR x264_analyse_psub16x16 "=[1|0] (default: 1)" .P 8x16, 16x8 and 8x8 P-frame search .P .BR x264_analyse_bsub16x16 "=[1|0] (default: 1)" .P 8x16, 16x8 and 8x8 B-frame search .P .BR x264_analyse_psub8x8 "=[1|0] (default: 0)" .P 4x8, 8x4 and 4x4 P-frame search .P .BR x264_analyse_i8x8 "=[1|0] (default: 1)" .P 8x8 Intra search .P 8x8 Intra search requires 8x8 transform .P .BR x264_analyse_i4x4 "=[1|0] (default: 1)" .P 4x4 Intra search .P .BR x264_i_me_method "=" .P Supported strings: Diamond search Hexagonal search Uneven Multi-Hexagon Exhaustive search Hadamard exhaustive search (slow) .P Default: Hexagonal search .P Method .P Motion estimation method Diamond search: fastest Hexagonal search: default setting Uneven Multi-Hexagon: better but slower Exhaustive search: extremely slow, primarily for testing .P .BR x264_i_subpel_refine "= (1..9, default: 7)" .P Partition decision .P Subpixel motion estimation and partition decision quality: 1=fast, 9=best. .P .BR x264_i_me_range "= (default: 16)" .P Search range .P Maximum distance to search for motion estimation, measured from predicted position(s). Default of 16 is good for most footage, high motion sequences may benefit from settings between 24-32. .P .BR x264_i_frame_reference "= (1..16, default: 1)" .P Max Ref. frames .P This is effective in Anime, but seems to make little difference in live-action source material. Some decoders are unable to deal with large frameref values. .P .BR x264_b_chroma_me "=[1|0] (default: 1)" .P Chroma motion estimation .P .BR x264_b_mixed_references "=[1|0] (default: 1)" .P Mixed references .P Allow each MB partition in P-frames to have it's own reference number .P .BR x264_b_weighted_bipred "=[1|0] (default: 0)" .P Weighted biprediction .P Implicit weighting for B-frames .P .BR x264_i_weighted_pred "=" .P Supported strings: Disabled Blind offset Smart analysis .P Default: Smart analysis .P Weighted prediction for P-frames .P .BR x264_i_direct_mv_pred "=" .P Supported strings: None Spatial Temporal Auto .P Default: Spatial .P Direct MV prediction mode .P .BR x264_b_deblocking_filter "=[1|0] (default: 1)" .P Deblocking filter .P Use deblocking loop filter (increases quality). .P .BR x264_i_deblocking_filter_alphac0 "= (-6..6, default: 0)" .P Deblocking filter strength .P Loop filter AlphaC0 parameter .P .BR x264_i_deblocking_filter_beta "= (-6..6, default: 0)" .P Deblocking filter threshold .P Loop filter Beta parameter .P .BR x264_b_cabac "=[1|0] (default: 1)" .P Enable CABAC .P Enable CABAC (Context-Adaptive Binary Arithmetic Coding). Slightly slows down encoding and decoding, but should save 10-15% bitrate. .P .BR x264_i_trellis "=" .P Supported strings: Disabled Enabled (final) Enabled (always) .P Default: Enabled (final) .P Trellis RD quantization .P Trellis RD quantization. Requires CABAC. Can be enabled either for the final encode of a MB or for all mode desisions .P .BR x264_i_noise_reduction "= (0..65536, default: 0)" .P Noise reduction .P .BR x264_i_threads "= (default: 1)" .P Threads .P Number of threads .P .BR x264_b_fast_pskip "=[1|0] (default: 1)" .P early SKIP detection on P-frames .P .BR x264_b_dct_decimate "=[1|0] (default: 1)" .P Transform coefficient thresholding on P-frames .P .RE .B Suboptions for codec=schroedinger .P .RS 2 .BR enc_rate_control "=" .P Supported strings: Constant noise threshold Constant bitrate Low delay Lossless Constant lambda Constant error Constant quality .P Default: Constant quality .P Rate control .P .BR enc_bitrate "= (default: 13824000)" .P Bitrate .P .BR enc_buffer_size "= (default: 0)" .P Buffer size .P .BR enc_buffer_level "= (default: 0)" .P Buffer level .P .BR enc_noise_threshold "= (0.00..100.00, default: 25.00)" .P Noise Threshold .P .BR enc_quality "= (0.00..10.00, default: 5.00)" .P Quality .P .BR enc_enable_rdo_cbr "=[1|0] (default: 1)" .P rdo cbr .P .BR enc_gop_structure "=" .P Supported strings: Adaptive Intra only Backref Chained backref Biref Chained biref .P Default: Adaptive .P GOP Stucture .P .BR enc_au_distance "= (default: 30)" .P GOP size .P .BR enc_open_gop "=[1|0] (default: 1)" .P Open GOPs .P Choose whether GOPs should be open or closed. Closed GOPs improve seeking accuracy for buggy decoders, open GOPs have a slightly better compression .P .BR enc_mv_precision "= (default: 0)" .P MV Precision .P .BR enc_motion_block_size "=" .P Supported strings: Automatic Small Medium Large .P Default: Automatic .P Block size .P .BR enc_motion_block_overlap "=" .P Supported strings: Automatic None Partial Full .P Default: Automatic .P Block overlap .P .BR enc_enable_chroma_me "=[1|0] (default: 0)" .P Enable chroma ME .P .BR enc_enable_global_motion "=[1|0] (default: 0)" .P Enable GMC .P Enable global motion estimation .P .BR enc_enable_phasecorr_estimation "=[1|0] (default: 0)" .P Enable phasecorrelation estimation .P .BR enc_enable_hierarchical_estimation "=[1|0] (default: 1)" .P Hierarchical estimation .P .BR enc_enable_phasecorr_estimation "=[1|0] (default: 0)" .P Phasecorr estimation .P .BR enc_enable_bigblock_estimation "=[1|0] (default: 1)" .P Bigblock estimation .P .BR enc_enable_global_motion "=[1|0] (default: 0)" .P Global motion estimation .P .BR enc_enable_deep_estimation "=[1|0] (default: 1)" .P Deep estimation .P .BR enc_enable_scene_change_detection "=[1|0] (default: 1)" .P Scene change detection .P .BR enc_intra_wavelet "=" .P Supported strings: Deslauriers-Debuc (9,3) LeGall (5,3) Deslauriers-Debuc (13,5) Haar (no shift) Haar (single shift) Fidelity Daubechies (9,7) .P Default: Deslauriers-Debuc (9,3) .P Intra wavelet .P .BR enc_inter_wavelet "=" .P Supported strings: Deslauriers-Debuc (9,3) LeGall (5,3) Deslauriers-Debuc (13,5) Haar (no shift) Haar (single shift) Fidelity Daubechies (9,7) .P Default: LeGall (5,3) .P Inter wavelet .P .BR enc_filtering "=" .P Supported strings: None Center weighted median Gaussian Add noise Adaptive Gaussian .P Default: None .P Filter .P .BR enc_filter_value "= (0..100, default: 5)" .P Filter value .P .BR enc_force_profile "=" .P Supported strings: Auto VC-2 low delay VC-2 simple VC-2 main Main .P Default: Auto .P Force profile .P .BR enc_codeblock_size "=" .P Supported strings: Auto Small Medium Large Full .P Default: Auto .P Codeblock size .P .BR enc_enable_multiquant "=[1|0] (default: 1)" .P Enable multiquant .P .BR enc_enable_dc_multiquant "=[1|0] (default: 0)" .P Enable DC multiquant .P .BR enc_enable_noarith "=[1|0] (default: 0)" .P Disable arithmetic coding .P .BR enc_downsample_levels "= (2..8, default: 5)" .P Downsample levels .P .BR enc_transform_depth "= (0..6, default: 3)" .P Transform depth .P .RE .RE .B Suboptions for video_encoder=e_y4m .P .RS 2 .BR chroma_mode "=" .P Supported strings: auto 420jpeg 420mpeg2 420paldv 444 422 411 mono yuva4444 .P Default: auto .P Chroma mode .P Set the chroma mode of the output file. Auto means to take the format most similar to the source. .P .BR default_timescale "= (default: 25)" .P Default timescale .P For formats, which support only constant framerates, set the default timescale here .P .BR default_frame_duration "= (default: 1)" .P Default frame duration .P For formats, which support only constant framerates, set the default frame duration here .P .RE .B Suboptions for video_encoder=e_mpegvideo .P .RS 2 .BR format "=" .P Supported strings: mpeg1 mpeg2 vcd svcd dvd .P Default: mpeg1 .P Format .P Sets the MPEG flavour. Note, that for VCD, SVCD and DVD, you MUST provide valid frame sizes .P .BR bitrate_mode "=" .P Supported strings: auto vbr cbr .P Default: auto .P Bitrate Mode .P Specify constant or variable bitrate. For "Auto", constant bitrate will be used for MPEG-1, variable bitrate will be used for MPEG-2. For formats, which require CBR, this option is ignored .P .BR bitrate "= (200..99999, default: 1150)" .P Bitrate (kbps) .P Video bitrate in kbps. For VBR, it's the maximum bitrate. If the format requires a fixed bitrate (e.g. VCD) this option is ignored .P .BR quantization "= (1..31, default: 8)" .P Quantization .P Minimum quantization for VBR. Lower numbers mean higher quality. For CBR, this option is ignored. .P .BR quant_matrix "=" .P Supported strings: default kvcd tmpgenc hi-res .P Default: default .P Quantization matrices .P .BR bframes "= (0..2, default: 0)" .P Number of B-Frames .P Specify the number of B-frames between 2 P/I frames. More B-frames slow down encoding and increase memory usage, but might give better compression results. For VCD, this option is ignored, since the VCD standard requires 2 B-frames, no matter if you like them or not. .P .BR user_options "=" .P User options .P Enter further commandline options for mpeg2enc here. Check the mpeg2enc manual page for details .P .BR default_timescale "= (default: 25)" .P Default timescale .P For formats, which support only constant framerates, set the default timescale here .P .BR default_frame_duration "= (default: 1)" .P Default frame duration .P For formats, which support only constant framerates, set the default frame duration here .P .RE .B Suboptions for video_encoder=e_singlepic .P .RS 2 .BR plugin "=option[{suboptions}]" .P Supported options: iw_jpeg iw_png iw_tiff iw_tga iw_bmp iw_pnm iw_gavl .P Default: iw_jpeg .P Plugin .P .B Suboptions for plugin=iw_jpeg .P .RS 2 .BR quality "= (0..100, default: 95)" .P Quality .P .BR chroma_sampling "=" .P Supported strings: 4:2:0 4:2:2 4:4:4 .P Default: 4:2:0 .P Chroma sampling .P .RE .B Suboptions for plugin=iw_png .P .RS 2 .BR compression "= (0..9, default: 9)" .P Compression level .P .BR bit_mode "=" .P Supported strings: Auto 8 16 .P Default: 8 .P Bits per channel .P If you select auto, the depth will be chosen according to the input format .P .RE .B Suboptions for plugin=iw_tiff .P .RS 2 .BR compression "=" .P Supported strings: none packbits deflate jpeg .P Default: none .P Compression .P .BR jpeg_quality "= (0..100, default: 75)" .P JPEG quality .P .BR zip_quality "= (0..9, default: 6)" .P Deflate compression level .P .RE .B Suboptions for plugin=iw_tga .P .RS 2 .BR rle "=[1|0] (default: 0)" .P Do RLE compression .P .RE .B Suboptions for plugin=iw_pnm .P .RS 2 .BR format "=" .P Supported strings: binary ascii .P Default: binary .P Format .P .BR comment "= (Default: Created with gmerlin)" .P Comment .P Comment which will be written in front of every file .P .RE .BR frame_digits "= (1..9, default: 4)" .P Framenumber digits .P .BR frame_offset "= (0..1000000, default: 0)" .P Framenumber offset .P .RE .B Suboptions for video_encoder=e_theora .P .RS 2 .BR codec "=option[{suboptions}]" .P Supported options: vorbis speex flacogg .P Default: vorbis .P Codec .P .B Suboptions for codec=vorbis .P .RS 2 .BR bitrate_mode "=" .P Supported strings: vbr vbr_bitrate managed .P Default: VBR .P Bitrate mode .P Bitrate mode: VBR: You specify a quality and (optionally) a minimum and maximum bitrate VBR (bitrate): The specified nominal bitrate will be used for selecting the encoder mode. Managed: You specify a nominal bitrate and (optionally) a minimum and maximum bitrate VBR is recommended, managed bitrate might result in a worse quality .P .BR nominal_bitrate "= (0..1000, default: 128)" .P Nominal bitrate (kbps) .P Nominal bitrate (in kbps) for managed mode .P .BR quality "= (0.0..10.0, default: 3.0)" .P VBR Quality (10: best) .P Quality for VBR mode 10: best (largest output file) 0: worst (smallest output file) .P .BR min_bitrate "= (0..1000, default: 0)" .P Minimum bitrate (kbps) .P Optional minimum bitrate (in kbps) 0 = unspecified .P .BR max_bitrate "= (0..1000, default: 0)" .P Maximum bitrate (kbps) .P Optional maximum bitrate (in kbps) 0 = unspecified .P .RE .B Suboptions for codec=speex .P .RS 2 .BR mode "=" .P Supported strings: auto nb wb uwb .P Default: auto .P Speex mode .P Encoding mode. If you select Auto, the mode will be taken from the samplerate. .P .BR quality "= (0..10, default: 3)" .P Quality (10: best) .P .BR complexity "= (0..10, default: 3)" .P Encoding complexity .P .BR nframes "= (1..10, default: 1)" .P Frames per Ogg packet .P .BR bitrate "= (0..128, default: 8)" .P Bitrate (kbps) .P Bitrate (in kbps). Set to 0 for seleting the standard bitrates for the encoding mode. .P .BR vbr "=[1|0] (default: 0)" .P Variable bitrate .P .BR abr_bitrate "= (0..128, default: 0)" .P Average bitrate (kbps) .P Average bitrate (in kbps). Set to 0 for disabling ABR. .P .BR vad "=[1|0] (default: 0)" .P Use voice activity detection .P .BR dtx "=[1|0] (default: 0)" .P Enable file-based discontinuous transmission .P .RE .B Suboptions for codec=flacogg .P .RS 2 .BR bits "=" .P Supported strings: 8 12 16 20 24 .P Default: 16 .P Bits .P .BR compression_level "= (0..8, default: 5)" .P Compression Level .P 0: Fastest encoding, biggest files 8: Slowest encoding, smallest files .P .RE .BR cbr "=[1|0] (default: 0)" .P Use constant bitrate .P For constant bitrate, choose a target bitrate. For variable bitrate, choose a nominal quality. .P .BR target_bitrate "= (45..2000, default: 250)" .P Target bitrate (kbps) .P .BR quality "= (0..63, default: 10)" .P Nominal quality .P Quality for VBR mode 63: best (largest output file) 0: worst (smallest output file) .P .BR max_keyframe_interval "= (1..1000, default: 64)" .P Maximum keyframe interval .P .BR drop_frames "=[1|0] (default: 1)" .P Enable frame dropping .P Drop frames to keep within bitrate buffer constraints. This can have a severe impact on quality, but is the only way to ensure that bitrate targets are met at low rates during sudden bursts of activity. .P .BR cap_overflow "=[1|0] (default: 1)" .P Don't bank excess bits for later use .P Ignore bitrate buffer overflows. If the encoder uses so few bits that the reservoir of available bits overflows, ignore the excess. The encoder will not try to use these extra bits in future frames. At high rates this may cause the result to be undersized, but allows a client to play the stream using a finite buffer; it should normally be enabled. .P .BR cap_underflow "=[1|0] (default: 0)" .P Don't try to make up shortfalls later .P Ignore bitrate buffer underflows. If the encoder uses so many bits that the reservoir of available bits underflows, ignore the deficit. The encoder will not try to make up these extra bits in future frames. At low rates this may cause the result to be oversized; it should normally be disabled. .P .BR speed "= (0.00..1.00, default: 0.00)" .P Encoding speed .P Higher speed levels favor quicker encoding over better quality per bit. Depending on the encoding mode, and the internal algorithms used, quality may actually improve, but in this case bitrate will also likely increase. In any case, overall rate/distortion performance will probably decrease. .P .BR default_timescale "= (default: 25)" .P Default timescale .P For formats, which support only constant framerates, set the default timescale here .P .BR default_frame_duration "= (default: 1)" .P Default frame duration .P For formats, which support only constant framerates, set the default frame duration here .P .RE .B Suboptions for video_encoder=e_mpeg .P .RS 2 .BR format "=" .P Supported strings: mpeg1 vcd mpeg2 svcd dvd_nav dvd .P Default: mpeg1 .P Format .P Output format. Note that for some output formats (e.g. VCD), you MUST use proper settings for the audio and video streams also, since this isn't done automatically .P .BR tmp_dir "=" .P Directory for temporary files .P Leave empty to use the same directory as the final output file .P .BR aux_stream_1 "=" .P Additional stream 1 .P Additional stream to multiplex into the final output file. Use this if you want e.g. create mp3 or AC3 audio with some other encoder .P .BR aux_stream_2 "=" .P Additional stream 2 .P Additional stream to multiplex into the final output file. Use this if you want e.g. create mp3 or AC3 audio with some other encoder .P .BR aux_stream_3 "=" .P Additional stream 3 .P Additional stream to multiplex into the final output file. Use this if you want e.g. create mp3 or AC3 audio with some other encoder .P .BR bitrate "= (32..448, default: 224)" .P Bitrate (kbps) .P .BR layer "= (1..2, default: 2)" .P Layer (1 or 2) .P Audio layer .P .BR vcd "=[1|0] (default: 1)" .P VCD Compatible .P Make VCD compliant output. This forces layer II, 224 kbps and 44.1 KHz stereo .P .BR format "=" .P Supported strings: mpeg1 mpeg2 vcd svcd dvd .P Default: mpeg1 .P Format .P Sets the MPEG flavour. Note, that for VCD, SVCD and DVD, you MUST provide valid frame sizes .P .BR bitrate_mode "=" .P Supported strings: auto vbr cbr .P Default: auto .P Bitrate Mode .P Specify constant or variable bitrate. For "Auto", constant bitrate will be used for MPEG-1, variable bitrate will be used for MPEG-2. For formats, which require CBR, this option is ignored .P .BR bitrate "= (200..99999, default: 1150)" .P Bitrate (kbps) .P Video bitrate in kbps. For VBR, it's the maximum bitrate. If the format requires a fixed bitrate (e.g. VCD) this option is ignored .P .BR quantization "= (1..31, default: 8)" .P Quantization .P Minimum quantization for VBR. Lower numbers mean higher quality. For CBR, this option is ignored. .P .BR quant_matrix "=" .P Supported strings: default kvcd tmpgenc hi-res .P Default: default .P Quantization matrices .P .BR bframes "= (0..2, default: 0)" .P Number of B-Frames .P Specify the number of B-frames between 2 P/I frames. More B-frames slow down encoding and increase memory usage, but might give better compression results. For VCD, this option is ignored, since the VCD standard requires 2 B-frames, no matter if you like them or not. .P .BR user_options "=" .P User options .P Enter further commandline options for mpeg2enc here. Check the mpeg2enc manual page for details .P .BR default_timescale "= (default: 25)" .P Default timescale .P For formats, which support only constant framerates, set the default timescale here .P .BR default_frame_duration "= (default: 1)" .P Default frame duration .P For formats, which support only constant framerates, set the default frame duration here .P .RE .B Suboptions for video_encoder=e_ffmpeg_video .P .RS 2 .BR format "=" .P Supported strings: mpeg1video mpeg2video .P Default: mpeg1video .P Format .P .BR codec "=option[{suboptions}]" .P Supported options: mpeg1video mpeg2video .P Default: mpeg1video .P Codec .P .B Suboptions for codec=mpeg1video .P .RS 2 .BR gop_size "= (0..300, default: 250)" .P GOP size (0 = intra only) .P .BR ff_scenechange_threshold "= (-1000000000..1000000000, default: 0)" .P Scenechange threshold .P Threshold for scene change detection. Negative values mean more sensitivity (more keyframes) .P .BR ff_scenechange_factor "= (default: 0)" .P Scenechange factor .P Multiplied by qscale for each frame and added to scene_change_score .P .BR ff_flag_closed_gop "=[1|0] (default: 0)" .P Close all GOPs .P .BR ff_flag2_strict_gop "=[1|0] (default: 0)" .P Strictly enforce GOP size .P .BR ff_max_b_frames "= (0..16, default: 0)" .P Max B-Frames .P Maximum number of B-frames between non B-frames .P .BR ff_b_frame_strategy "=[1|0] (default: 0)" .P Avoid B-frames in high motion scenes .P .BR ff_bit_rate_video "= (default: 800)" .P Bit rate (kbps) .P .BR ff_bit_rate_tolerance "= (default: 8000)" .P Bitrate tolerance (kbps) .P Number of bits the bitstream is allowed to diverge from the reference. Unused for constant quantizer encoding .P .BR ff_rc_min_rate "= (default: 0)" .P Minimum bitrate (kbps) .P Minimum bitrate (0 means arbitrary) .P .BR ff_rc_max_rate "= (default: 0)" .P Maximum bitrate (kbps) .P Maximum bitrate (0 means arbitrary) .P .BR ff_rc_buffer_size "= (default: 0)" .P RC buffer size .P Decoder bitstream buffer size in kbits. When encoding with max and/or min bitrate, this must be specified. .P .BR ff_rc_initial_cplx "= (0.0..99.0, default: 0.0)" .P Initial RC complexity .P .BR ff_rc_initial_buffer_occupancy "= (default: 0)" .P Initial RC buffer occupancy .P Number of kilobits which should be loaded into the rc buffer before encoding starts. Must not be larger than RC buffer size .P .BR ff_qmin "= (0..31, default: 2)" .P Minimum quantizer scale .P .BR ff_qmax "= (0..31, default: 31)" .P Maximum quantizer scale .P .BR ff_max_qdiff "= (0..31, default: 3)" .P Maximum quantizer difference .P Maximum quantizer difference between frames .P .BR ff_flag_qscale "=[1|0] (default: 0)" .P Use fixed quantizer .P Use fixed quality encoding .P .BR ff_qscale "= (1..31, default: 10)" .P Fixed quantizer .P Quantizer for fixed quality encoding. Lower means better, 1 is not recommended .P .BR ff_qcompress "= (0.00..1.00, default: 0.50)" .P Quantizer compression .P Amount of qscale change between easy & hard scenes .P .BR ff_qblur "= (0.00..1.00, default: 0.00)" .P Quantizer blur .P Amount of qscale smoothing over time .P .BR ff_quantizer_noise_shaping "= (0..3, default: 0)" .P Quantizer noise shaping .P Choose quantization such that noise will be masked by similar-frequency content in the image .P .BR ff_trellis "=[1|0] (default: 0)" .P Use trellis quantization .P Use trellis quantization (improves quality) .P .BR ff_i_quant_factor "= (-31.0..31.0, default: -0.8)" .P I quantizer factor .P Quantizer factor between P-frames and I-frames. If > 0 then the last P frame quantizer will be used (q= lastp_q*factor+offset). If < 0 then normal ratecontrol will be done (q= -normal_q*factor+offset) .P .BR ff_i_quant_offset "= (0.0..31.0, default: 0.0)" .P I quantizer offset .P Quantizer offset between P-frames and I-frames .P .BR ff_b_quant_factor "= (-31.00..31.00, default: 1.25)" .P B quantizer factor .P Quantizer factor between B-frames and non-B-frames .P .BR ff_b_quant_offset "= (0.00..31.00, default: 1.25)" .P B quantizer offset .P Quantizer offset between B-frames and non-B-frames if > 0 then the last p frame quantizer will be used (q= lastp_q*factor+offset) if < 0 then normal ratecontrol will be done (q= -normal_q*factor+offset) .P .BR ff_me_method "=" .P Supported strings: Zero Phods Log X1 Epzs Full .P Default: Zero .P Motion estimation method .P .BR ff_me_cmp "=" .P Supported strings: SAD SSE SATD DCT PSNR BIT RD ZERO VSAD VSSE NSSE .P Default: SAD .P ME compare function .P Motion estimation compare function.SAD: Sum of absolute differences SSE: Sum of squared errors SATD: Sum of absolute Hadamard transformed differences DCT: Sum of absolute DCT transformed differences PSNR: Sum of squared quantization errors (low quality) BIT: Number of bits needed for the block RD: Rate distortion optimal (slow) ZERO: 0 VSAD: Sum of absolute vertical differences VSSE: Sum of squared vertical differences NSSE: Noise preserving sum of squared differences .P .BR ff_me_cmp_chroma "=[1|0] (default: 0)" .P Enable chroma ME compare .P .BR ff_me_range "= (0..1000, default: 0)" .P Motion estimation range .P Motion estimation search range (0 means unlimited) .P .BR ff_me_threshold "= (0..4000000, default: 0)" .P ME Theshold .P Motion estimation threshold. under which no motion estimation is performed, but instead the user specified motion vectors are used .P .BR ff_mb_decision "=" .P Supported strings: Use compare function Fewest bits Rate distoration .P Default: Use compare function .P MB decision mode .P .BR ff_dia_size "= (-9..9, default: 0)" .P ME diamond size & shape .P Motion estimation diamond size. Negative means shape adaptive. .P .BR ff_pre_me "= (0..2, default: 0)" .P ME pre-pass .P Motion estimation pre-pass 0: disabled 1: only after I-frames 2: always .P .BR ff_me_pre_cmp "=" .P Supported strings: SAD SSE SATD DCT PSNR BIT RD ZERO VSAD VSSE NSSE .P Default: SAD .P ME pre-pass compare function .P Motion estimation pre-pass compare function. SAD: Sum of absolute differences SSE: Sum of squared errors SATD: Sum of absolute Hadamard transformed differences DCT: Sum of absolute DCT transformed differences PSNR: Sum of squared quantization errors (low quality) BIT: Number of bits needed for the block RD: Rate distortion optimal (slow) ZERO: 0 VSAD: Sum of absolute vertical differences VSSE: Sum of squared vertical differences NSSE: Noise preserving sum of squared differences .P .BR ff_me_pre_cmp_chroma "=[1|0] (default: 0)" .P Enable chroma ME pre-pass compare .P .BR ff_pre_dia_size "= (-9..9, default: 0)" .P ME pre-pass diamond size & shape .P Motion estimation pre-pass diamond size. Negative means shape adaptive. .P .BR ff_lumi_masking "= (0.00..1.00, default: 0.00)" .P Luminance masking .P Encode very bright image parts with reduced quality. 0 means disabled, 0-0.3 is a sane range. .P .BR ff_dark_masking "= (0.00..1.00, default: 0.00)" .P Darkness masking .P Encode very dark image parts with reduced quality. 0 means disabled, 0-0.3 is a sane range. .P .BR ff_temporal_cplx_masking "= (0.00..1.00, default: 0.00)" .P Temporary complexity masking .P Encode very fast moving image parts with reduced quality. 0 means disabled. .P .BR ff_spatial_cplx_masking "= (0.00..1.00, default: 0.00)" .P Spatial complexity masking .P Encode very complex image parts with reduced quality. 0 means disabled, 0-0.5 is a sane range. .P .BR ff_border_masking "= (0.00..1.00, default: 0.00)" .P Border masking .P Encode image parts near the border with reduced quality. 0 means disabled .P .BR ff_p_masking "= (0.00..1.00, default: 0.00)" .P Inter block masking .P Encode inter blocks with reduced quality (increases the quality of intra blocks). 0 means disabled, 1 will double the bits allocated for intra blocks. .P .BR ff_flag_normalize_aqp "=[1|0] (default: 0)" .P Normalize adaptive quantization .P When using masking, try to adjust the per macroblock quantizers to maintain the desired average .P .BR ff_strict_std_compliance "= (-2..2, default: 0)" .P Standards compliance .P 2: Strictly conform to a older more strict version of the spec or reference software 1: Strictly conform to all the things in the spec no matter what consequences 0: Default -1: Allow inofficial extensions -2: Allow non standarized experimental things .P .BR ff_noise_reduction "= (0..2000, default: 0)" .P Noise reduction .P .BR ff_flag_gray "=[1|0] (default: 0)" .P Grayscale mode .P .BR ff_flag_bitexact "=[1|0] (default: 0)" .P Use only bitexact stuff .P Use only bitexact stuff (except (i)dct) .P .RE .B Suboptions for codec=mpeg2video .P .RS 2 .BR gop_size "= (0..300, default: 250)" .P GOP size (0 = intra only) .P .BR ff_scenechange_threshold "= (-1000000000..1000000000, default: 0)" .P Scenechange threshold .P Threshold for scene change detection. Negative values mean more sensitivity (more keyframes) .P .BR ff_scenechange_factor "= (default: 0)" .P Scenechange factor .P Multiplied by qscale for each frame and added to scene_change_score .P .BR ff_flag_closed_gop "=[1|0] (default: 0)" .P Close all GOPs .P .BR ff_flag2_strict_gop "=[1|0] (default: 0)" .P Strictly enforce GOP size .P .BR ff_max_b_frames "= (0..16, default: 0)" .P Max B-Frames .P Maximum number of B-frames between non B-frames .P .BR ff_b_frame_strategy "=[1|0] (default: 0)" .P Avoid B-frames in high motion scenes .P .BR ff_bit_rate_video "= (default: 800)" .P Bit rate (kbps) .P .BR ff_bit_rate_tolerance "= (default: 8000)" .P Bitrate tolerance (kbps) .P Number of bits the bitstream is allowed to diverge from the reference. Unused for constant quantizer encoding .P .BR ff_rc_min_rate "= (default: 0)" .P Minimum bitrate (kbps) .P Minimum bitrate (0 means arbitrary) .P .BR ff_rc_max_rate "= (default: 0)" .P Maximum bitrate (kbps) .P Maximum bitrate (0 means arbitrary) .P .BR ff_rc_buffer_size "= (default: 0)" .P RC buffer size .P Decoder bitstream buffer size in kbits. When encoding with max and/or min bitrate, this must be specified. .P .BR ff_rc_initial_cplx "= (0.0..99.0, default: 0.0)" .P Initial RC complexity .P .BR ff_rc_initial_buffer_occupancy "= (default: 0)" .P Initial RC buffer occupancy .P Number of kilobits which should be loaded into the rc buffer before encoding starts. Must not be larger than RC buffer size .P .BR ff_qmin "= (0..31, default: 2)" .P Minimum quantizer scale .P .BR ff_qmax "= (0..31, default: 31)" .P Maximum quantizer scale .P .BR ff_max_qdiff "= (0..31, default: 3)" .P Maximum quantizer difference .P Maximum quantizer difference between frames .P .BR ff_flag_qscale "=[1|0] (default: 0)" .P Use fixed quantizer .P Use fixed quality encoding .P .BR ff_qscale "= (1..31, default: 10)" .P Fixed quantizer .P Quantizer for fixed quality encoding. Lower means better, 1 is not recommended .P .BR ff_qcompress "= (0.00..1.00, default: 0.50)" .P Quantizer compression .P Amount of qscale change between easy & hard scenes .P .BR ff_qblur "= (0.00..1.00, default: 0.00)" .P Quantizer blur .P Amount of qscale smoothing over time .P .BR ff_quantizer_noise_shaping "= (0..3, default: 0)" .P Quantizer noise shaping .P Choose quantization such that noise will be masked by similar-frequency content in the image .P .BR ff_trellis "=[1|0] (default: 0)" .P Use trellis quantization .P Use trellis quantization (improves quality) .P .BR ff_i_quant_factor "= (-31.0..31.0, default: -0.8)" .P I quantizer factor .P Quantizer factor between P-frames and I-frames. If > 0 then the last P frame quantizer will be used (q= lastp_q*factor+offset). If < 0 then normal ratecontrol will be done (q= -normal_q*factor+offset) .P .BR ff_i_quant_offset "= (0.0..31.0, default: 0.0)" .P I quantizer offset .P Quantizer offset between P-frames and I-frames .P .BR ff_b_quant_factor "= (-31.00..31.00, default: 1.25)" .P B quantizer factor .P Quantizer factor between B-frames and non-B-frames .P .BR ff_b_quant_offset "= (0.00..31.00, default: 1.25)" .P B quantizer offset .P Quantizer offset between B-frames and non-B-frames if > 0 then the last p frame quantizer will be used (q= lastp_q*factor+offset) if < 0 then normal ratecontrol will be done (q= -normal_q*factor+offset) .P .BR ff_me_method "=" .P Supported strings: Zero Phods Log X1 Epzs Full .P Default: Zero .P Motion estimation method .P .BR ff_me_cmp "=" .P Supported strings: SAD SSE SATD DCT PSNR BIT RD ZERO VSAD VSSE NSSE .P Default: SAD .P ME compare function .P Motion estimation compare function.SAD: Sum of absolute differences SSE: Sum of squared errors SATD: Sum of absolute Hadamard transformed differences DCT: Sum of absolute DCT transformed differences PSNR: Sum of squared quantization errors (low quality) BIT: Number of bits needed for the block RD: Rate distortion optimal (slow) ZERO: 0 VSAD: Sum of absolute vertical differences VSSE: Sum of squared vertical differences NSSE: Noise preserving sum of squared differences .P .BR ff_me_cmp_chroma "=[1|0] (default: 0)" .P Enable chroma ME compare .P .BR ff_me_range "= (0..1000, default: 0)" .P Motion estimation range .P Motion estimation search range (0 means unlimited) .P .BR ff_me_threshold "= (0..4000000, default: 0)" .P ME Theshold .P Motion estimation threshold. under which no motion estimation is performed, but instead the user specified motion vectors are used .P .BR ff_mb_decision "=" .P Supported strings: Use compare function Fewest bits Rate distoration .P Default: Use compare function .P MB decision mode .P .BR ff_dia_size "= (-9..9, default: 0)" .P ME diamond size & shape .P Motion estimation diamond size. Negative means shape adaptive. .P .BR ff_pre_me "= (0..2, default: 0)" .P ME pre-pass .P Motion estimation pre-pass 0: disabled 1: only after I-frames 2: always .P .BR ff_me_pre_cmp "=" .P Supported strings: SAD SSE SATD DCT PSNR BIT RD ZERO VSAD VSSE NSSE .P Default: SAD .P ME pre-pass compare function .P Motion estimation pre-pass compare function. SAD: Sum of absolute differences SSE: Sum of squared errors SATD: Sum of absolute Hadamard transformed differences DCT: Sum of absolute DCT transformed differences PSNR: Sum of squared quantization errors (low quality) BIT: Number of bits needed for the block RD: Rate distortion optimal (slow) ZERO: 0 VSAD: Sum of absolute vertical differences VSSE: Sum of squared vertical differences NSSE: Noise preserving sum of squared differences .P .BR ff_me_pre_cmp_chroma "=[1|0] (default: 0)" .P Enable chroma ME pre-pass compare .P .BR ff_pre_dia_size "= (-9..9, default: 0)" .P ME pre-pass diamond size & shape .P Motion estimation pre-pass diamond size. Negative means shape adaptive. .P .BR ff_lumi_masking "= (0.00..1.00, default: 0.00)" .P Luminance masking .P Encode very bright image parts with reduced quality. 0 means disabled, 0-0.3 is a sane range. .P .BR ff_dark_masking "= (0.00..1.00, default: 0.00)" .P Darkness masking .P Encode very dark image parts with reduced quality. 0 means disabled, 0-0.3 is a sane range. .P .BR ff_temporal_cplx_masking "= (0.00..1.00, default: 0.00)" .P Temporary complexity masking .P Encode very fast moving image parts with reduced quality. 0 means disabled. .P .BR ff_spatial_cplx_masking "= (0.00..1.00, default: 0.00)" .P Spatial complexity masking .P Encode very complex image parts with reduced quality. 0 means disabled, 0-0.5 is a sane range. .P .BR ff_border_masking "= (0.00..1.00, default: 0.00)" .P Border masking .P Encode image parts near the border with reduced quality. 0 means disabled .P .BR ff_p_masking "= (0.00..1.00, default: 0.00)" .P Inter block masking .P Encode inter blocks with reduced quality (increases the quality of intra blocks). 0 means disabled, 1 will double the bits allocated for intra blocks. .P .BR ff_flag_normalize_aqp "=[1|0] (default: 0)" .P Normalize adaptive quantization .P When using masking, try to adjust the per macroblock quantizers to maintain the desired average .P .BR ff_strict_std_compliance "= (-2..2, default: 0)" .P Standards compliance .P 2: Strictly conform to a older more strict version of the spec or reference software 1: Strictly conform to all the things in the spec no matter what consequences 0: Default -1: Allow inofficial extensions -2: Allow non standarized experimental things .P .BR ff_noise_reduction "= (0..2000, default: 0)" .P Noise reduction .P .BR ff_flag_gray "=[1|0] (default: 0)" .P Grayscale mode .P .BR ff_flag_bitexact "=[1|0] (default: 0)" .P Use only bitexact stuff .P Use only bitexact stuff (except (i)dct) .P .RE .BR default_timescale "= (default: 25)" .P Default timescale .P For formats, which support only constant framerates, set the default timescale here .P .BR default_frame_duration "= (default: 1)" .P Default frame duration .P For formats, which support only constant framerates, set the default frame duration here .P .RE .B Suboptions for video_encoder=e_ffmpeg .P .RS 2 .BR format "=" .P Supported strings: avi mpeg vob dvd flv asf mpegts .P Default: avi .P Format .P .BR codec "=option[{suboptions}]" .P Supported options: pcm_s16le pcm_u8 pcm_alaw pcm_mulaw mp3 mp2 ac3 wma2 wma1 .P Default: pcm_s16le .P Codec .P .B Suboptions for codec=mp3 .P .RS 2 .BR ff_bit_rate_str "=" .P Supported strings: 32 40 48 56 64 80 96 112 128 160 192 224 256 320 .P Default: 128 .P Bit rate (kbps) .P .RE .B Suboptions for codec=mp2 .P .RS 2 .BR ff_bit_rate_str "=" .P Supported strings: 32 48 56 64 80 96 112 128 160 192 224 256 320 384 .P Default: 128 .P Bit rate (kbps) .P .RE .B Suboptions for codec=ac3 .P .RS 2 .BR ff_bit_rate_str "=" .P Supported strings: 32 40 48 56 64 80 96 112 128 160 192 224 256 320 384 448 512 576 640 .P Default: 128 .P Bit rate (kbps) .P .RE .B Suboptions for codec=wma2 .P .RS 2 .BR ff_bit_rate_str "=" .P Supported strings: 24 48 64 96 128 .P Default: 128 .P Bit rate (kbps) .P .RE .B Suboptions for codec=wma1 .P .RS 2 .BR ff_bit_rate_str "=" .P Supported strings: 24 48 64 96 128 .P Default: 128 .P Bit rate (kbps) .P .RE .BR codec "=option[{suboptions}]" .P Supported options: mpeg4 msmpeg4v3 mjpeg mpeg1video mpeg2video flv1 wmv1 .P Default: mpeg4 .P Codec .P .B Suboptions for codec=mpeg4 .P .RS 2 .BR gop_size "= (0..300, default: 250)" .P GOP size (0 = intra only) .P .BR ff_scenechange_threshold "= (-1000000000..1000000000, default: 0)" .P Scenechange threshold .P Threshold for scene change detection. Negative values mean more sensitivity (more keyframes) .P .BR ff_scenechange_factor "= (default: 0)" .P Scenechange factor .P Multiplied by qscale for each frame and added to scene_change_score .P .BR ff_flag_closed_gop "=[1|0] (default: 0)" .P Close all GOPs .P .BR ff_flag2_strict_gop "=[1|0] (default: 0)" .P Strictly enforce GOP size .P .BR ff_max_b_frames "= (0..16, default: 0)" .P Max B-Frames .P Maximum number of B-frames between non B-frames .P .BR ff_b_frame_strategy "=[1|0] (default: 0)" .P Avoid B-frames in high motion scenes .P .BR ff_flag_ac_pred "=[1|0] (default: 0)" .P MPEG-4 AC prediction .P .BR ff_bit_rate_video "= (default: 800)" .P Bit rate (kbps) .P .BR ff_bit_rate_tolerance "= (default: 8000)" .P Bitrate tolerance (kbps) .P Number of bits the bitstream is allowed to diverge from the reference. Unused for constant quantizer encoding .P .BR ff_rc_min_rate "= (default: 0)" .P Minimum bitrate (kbps) .P Minimum bitrate (0 means arbitrary) .P .BR ff_rc_max_rate "= (default: 0)" .P Maximum bitrate (kbps) .P Maximum bitrate (0 means arbitrary) .P .BR ff_rc_buffer_size "= (default: 0)" .P RC buffer size .P Decoder bitstream buffer size in kbits. When encoding with max and/or min bitrate, this must be specified. .P .BR ff_rc_initial_cplx "= (0.0..99.0, default: 0.0)" .P Initial RC complexity .P .BR ff_rc_initial_buffer_occupancy "= (default: 0)" .P Initial RC buffer occupancy .P Number of kilobits which should be loaded into the rc buffer before encoding starts. Must not be larger than RC buffer size .P .BR ff_qmin "= (0..31, default: 2)" .P Minimum quantizer scale .P .BR ff_qmax "= (0..31, default: 31)" .P Maximum quantizer scale .P .BR ff_max_qdiff "= (0..31, default: 3)" .P Maximum quantizer difference .P Maximum quantizer difference between frames .P .BR ff_flag_qscale "=[1|0] (default: 0)" .P Use fixed quantizer .P Use fixed quality encoding .P .BR ff_qscale "= (1..31, default: 10)" .P Fixed quantizer .P Quantizer for fixed quality encoding. Lower means better, 1 is not recommended .P .BR ff_qcompress "= (0.00..1.00, default: 0.50)" .P Quantizer compression .P Amount of qscale change between easy & hard scenes .P .BR ff_qblur "= (0.00..1.00, default: 0.00)" .P Quantizer blur .P Amount of qscale smoothing over time .P .BR ff_quantizer_noise_shaping "= (0..3, default: 0)" .P Quantizer noise shaping .P Choose quantization such that noise will be masked by similar-frequency content in the image .P .BR ff_trellis "=[1|0] (default: 0)" .P Use trellis quantization .P Use trellis quantization (improves quality) .P .BR ff_i_quant_factor "= (-31.0..31.0, default: -0.8)" .P I quantizer factor .P Quantizer factor between P-frames and I-frames. If > 0 then the last P frame quantizer will be used (q= lastp_q*factor+offset). If < 0 then normal ratecontrol will be done (q= -normal_q*factor+offset) .P .BR ff_i_quant_offset "= (0.0..31.0, default: 0.0)" .P I quantizer offset .P Quantizer offset between P-frames and I-frames .P .BR ff_b_quant_factor "= (-31.00..31.00, default: 1.25)" .P B quantizer factor .P Quantizer factor between B-frames and non-B-frames .P .BR ff_b_quant_offset "= (0.00..31.00, default: 1.25)" .P B quantizer offset .P Quantizer offset between B-frames and non-B-frames if > 0 then the last p frame quantizer will be used (q= lastp_q*factor+offset) if < 0 then normal ratecontrol will be done (q= -normal_q*factor+offset) .P .BR ff_flag_cbp_rd "=[1|0] (default: 0)" .P CBP RD .P Use rate distortion optimization for cbp .P .BR ff_me_method "=" .P Supported strings: Zero Phods Log X1 Epzs Full .P Default: Zero .P Motion estimation method .P .BR ff_me_cmp "=" .P Supported strings: SAD SSE SATD DCT PSNR BIT RD ZERO VSAD VSSE NSSE .P Default: SAD .P ME compare function .P Motion estimation compare function.SAD: Sum of absolute differences SSE: Sum of squared errors SATD: Sum of absolute Hadamard transformed differences DCT: Sum of absolute DCT transformed differences PSNR: Sum of squared quantization errors (low quality) BIT: Number of bits needed for the block RD: Rate distortion optimal (slow) ZERO: 0 VSAD: Sum of absolute vertical differences VSSE: Sum of squared vertical differences NSSE: Noise preserving sum of squared differences .P .BR ff_me_cmp_chroma "=[1|0] (default: 0)" .P Enable chroma ME compare .P .BR ff_me_range "= (0..1000, default: 0)" .P Motion estimation range .P Motion estimation search range (0 means unlimited) .P .BR ff_me_threshold "= (0..4000000, default: 0)" .P ME Theshold .P Motion estimation threshold. under which no motion estimation is performed, but instead the user specified motion vectors are used .P .BR ff_mb_decision "=" .P Supported strings: Use compare function Fewest bits Rate distoration .P Default: Use compare function .P MB decision mode .P .BR ff_dia_size "= (-9..9, default: 0)" .P ME diamond size & shape .P Motion estimation diamond size. Negative means shape adaptive. .P .BR ff_flag_gmc "=[1|0] (default: 0)" .P Use global motion compensation .P Warning: GMC is not supported by all decoders .P .BR ff_flag_4mv "=[1|0] (default: 0)" .P 4 MV per MB allowed .P Allow 4 motion vectors per macroblock (slightly better quality). Works better if MB decision mode is "Fewest bits" or "Rate distoration". .P .BR ff_flag_mv0 "=[1|0] (default: 0)" .P Always try a MB with MV=<0,0> .P .BR ff_flag_qp_rd "=[1|0] (default: 0)" .P QP RD .P Use rate distortion optimization for qp selection .P .BR ff_pre_me "= (0..2, default: 0)" .P ME pre-pass .P Motion estimation pre-pass 0: disabled 1: only after I-frames 2: always .P .BR ff_me_pre_cmp "=" .P Supported strings: SAD SSE SATD DCT PSNR BIT RD ZERO VSAD VSSE NSSE .P Default: SAD .P ME pre-pass compare function .P Motion estimation pre-pass compare function. SAD: Sum of absolute differences SSE: Sum of squared errors SATD: Sum of absolute Hadamard transformed differences DCT: Sum of absolute DCT transformed differences PSNR: Sum of squared quantization errors (low quality) BIT: Number of bits needed for the block RD: Rate distortion optimal (slow) ZERO: 0 VSAD: Sum of absolute vertical differences VSSE: Sum of squared vertical differences NSSE: Noise preserving sum of squared differences .P .BR ff_me_pre_cmp_chroma "=[1|0] (default: 0)" .P Enable chroma ME pre-pass compare .P .BR ff_pre_dia_size "= (-9..9, default: 0)" .P ME pre-pass diamond size & shape .P Motion estimation pre-pass diamond size. Negative means shape adaptive. .P .BR ff_flag_qpel "=[1|0] (default: 0)" .P Use qpel MC .P Use 1/4 pixel motion compensation. Warning: QPEL is not supported by all decoders. .P .BR ff_me_sub_cmp "=" .P Supported strings: SAD SSE SATD DCT PSNR BIT RD ZERO VSAD VSSE NSSE .P Default: SAD .P Subpixel ME compare function .P Subpixel motion estimation compare function. SAD: Sum of absolute differences SSE: Sum of squared errors SATD: Sum of absolute Hadamard transformed differences DCT: Sum of absolute DCT transformed differences PSNR: Sum of squared quantization errors (low quality) BIT: Number of bits needed for the block RD: Rate distortion optimal (slow) ZERO: 0 VSAD: Sum of absolute vertical differences VSSE: Sum of squared vertical differences NSSE: Noise preserving sum of squared differences .P .BR ff_me_sub_cmp_chroma "=[1|0] (default: 0)" .P Enable chroma subpixel ME compare .P .BR ff_me_subpel_quality "= (1..8, default: 8)" .P Subpel ME quality .P Subpel motion estimation refinement quality (for qpel). Higher values mean higher quality but slower encoding. .P .BR ff_lumi_masking "= (0.00..1.00, default: 0.00)" .P Luminance masking .P Encode very bright image parts with reduced quality. 0 means disabled, 0-0.3 is a sane range. .P .BR ff_dark_masking "= (0.00..1.00, default: 0.00)" .P Darkness masking .P Encode very dark image parts with reduced quality. 0 means disabled, 0-0.3 is a sane range. .P .BR ff_temporal_cplx_masking "= (0.00..1.00, default: 0.00)" .P Temporary complexity masking .P Encode very fast moving image parts with reduced quality. 0 means disabled. .P .BR ff_spatial_cplx_masking "= (0.00..1.00, default: 0.00)" .P Spatial complexity masking .P Encode very complex image parts with reduced quality. 0 means disabled, 0-0.5 is a sane range. .P .BR ff_border_masking "= (0.00..1.00, default: 0.00)" .P Border masking .P Encode image parts near the border with reduced quality. 0 means disabled .P .BR ff_p_masking "= (0.00..1.00, default: 0.00)" .P Inter block masking .P Encode inter blocks with reduced quality (increases the quality of intra blocks). 0 means disabled, 1 will double the bits allocated for intra blocks. .P .BR ff_flag_normalize_aqp "=[1|0] (default: 0)" .P Normalize adaptive quantization .P When using masking, try to adjust the per macroblock quantizers to maintain the desired average .P .BR ff_strict_std_compliance "= (-2..2, default: 0)" .P Standards compliance .P 2: Strictly conform to a older more strict version of the spec or reference software 1: Strictly conform to all the things in the spec no matter what consequences 0: Default -1: Allow inofficial extensions -2: Allow non standarized experimental things .P .BR ff_noise_reduction "= (0..2000, default: 0)" .P Noise reduction .P .BR ff_flag_gray "=[1|0] (default: 0)" .P Grayscale mode .P .BR ff_flag_bitexact "=[1|0] (default: 0)" .P Use only bitexact stuff .P Use only bitexact stuff (except (i)dct) .P .RE .B Suboptions for codec=msmpeg4v3 .P .RS 2 .BR gop_size "= (0..300, default: 250)" .P GOP size (0 = intra only) .P .BR ff_scenechange_threshold "= (-1000000000..1000000000, default: 0)" .P Scenechange threshold .P Threshold for scene change detection. Negative values mean more sensitivity (more keyframes) .P .BR ff_scenechange_factor "= (default: 0)" .P Scenechange factor .P Multiplied by qscale for each frame and added to scene_change_score .P .BR ff_flag_closed_gop "=[1|0] (default: 0)" .P Close all GOPs .P .BR ff_flag2_strict_gop "=[1|0] (default: 0)" .P Strictly enforce GOP size .P .BR ff_bit_rate_video "= (default: 800)" .P Bit rate (kbps) .P .BR ff_bit_rate_tolerance "= (default: 8000)" .P Bitrate tolerance (kbps) .P Number of bits the bitstream is allowed to diverge from the reference. Unused for constant quantizer encoding .P .BR ff_rc_min_rate "= (default: 0)" .P Minimum bitrate (kbps) .P Minimum bitrate (0 means arbitrary) .P .BR ff_rc_max_rate "= (default: 0)" .P Maximum bitrate (kbps) .P Maximum bitrate (0 means arbitrary) .P .BR ff_rc_buffer_size "= (default: 0)" .P RC buffer size .P Decoder bitstream buffer size in kbits. When encoding with max and/or min bitrate, this must be specified. .P .BR ff_rc_initial_cplx "= (0.0..99.0, default: 0.0)" .P Initial RC complexity .P .BR ff_rc_initial_buffer_occupancy "= (default: 0)" .P Initial RC buffer occupancy .P Number of kilobits which should be loaded into the rc buffer before encoding starts. Must not be larger than RC buffer size .P .BR ff_qmin "= (0..31, default: 2)" .P Minimum quantizer scale .P .BR ff_qmax "= (0..31, default: 31)" .P Maximum quantizer scale .P .BR ff_max_qdiff "= (0..31, default: 3)" .P Maximum quantizer difference .P Maximum quantizer difference between frames .P .BR ff_flag_qscale "=[1|0] (default: 0)" .P Use fixed quantizer .P Use fixed quality encoding .P .BR ff_qscale "= (1..31, default: 10)" .P Fixed quantizer .P Quantizer for fixed quality encoding. Lower means better, 1 is not recommended .P .BR ff_qcompress "= (0.00..1.00, default: 0.50)" .P Quantizer compression .P Amount of qscale change between easy & hard scenes .P .BR ff_qblur "= (0.00..1.00, default: 0.00)" .P Quantizer blur .P Amount of qscale smoothing over time .P .BR ff_quantizer_noise_shaping "= (0..3, default: 0)" .P Quantizer noise shaping .P Choose quantization such that noise will be masked by similar-frequency content in the image .P .BR ff_trellis "=[1|0] (default: 0)" .P Use trellis quantization .P Use trellis quantization (improves quality) .P .BR ff_i_quant_factor "= (-31.0..31.0, default: -0.8)" .P I quantizer factor .P Quantizer factor between P-frames and I-frames. If > 0 then the last P frame quantizer will be used (q= lastp_q*factor+offset). If < 0 then normal ratecontrol will be done (q= -normal_q*factor+offset) .P .BR ff_i_quant_offset "= (0.0..31.0, default: 0.0)" .P I quantizer offset .P Quantizer offset between P-frames and I-frames .P .BR ff_me_method "=" .P Supported strings: Zero Phods Log X1 Epzs Full .P Default: Zero .P Motion estimation method .P .BR ff_me_cmp "=" .P Supported strings: SAD SSE SATD DCT PSNR BIT RD ZERO VSAD VSSE NSSE .P Default: SAD .P ME compare function .P Motion estimation compare function.SAD: Sum of absolute differences SSE: Sum of squared errors SATD: Sum of absolute Hadamard transformed differences DCT: Sum of absolute DCT transformed differences PSNR: Sum of squared quantization errors (low quality) BIT: Number of bits needed for the block RD: Rate distortion optimal (slow) ZERO: 0 VSAD: Sum of absolute vertical differences VSSE: Sum of squared vertical differences NSSE: Noise preserving sum of squared differences .P .BR ff_me_cmp_chroma "=[1|0] (default: 0)" .P Enable chroma ME compare .P .BR ff_me_range "= (0..1000, default: 0)" .P Motion estimation range .P Motion estimation search range (0 means unlimited) .P .BR ff_me_threshold "= (0..4000000, default: 0)" .P ME Theshold .P Motion estimation threshold. under which no motion estimation is performed, but instead the user specified motion vectors are used .P .BR ff_mb_decision "=" .P Supported strings: Use compare function Fewest bits Rate distoration .P Default: Use compare function .P MB decision mode .P .BR ff_dia_size "= (-9..9, default: 0)" .P ME diamond size & shape .P Motion estimation diamond size. Negative means shape adaptive. .P .BR ff_pre_me "= (0..2, default: 0)" .P ME pre-pass .P Motion estimation pre-pass 0: disabled 1: only after I-frames 2: always .P .BR ff_me_pre_cmp "=" .P Supported strings: SAD SSE SATD DCT PSNR BIT RD ZERO VSAD VSSE NSSE .P Default: SAD .P ME pre-pass compare function .P Motion estimation pre-pass compare function. SAD: Sum of absolute differences SSE: Sum of squared errors SATD: Sum of absolute Hadamard transformed differences DCT: Sum of absolute DCT transformed differences PSNR: Sum of squared quantization errors (low quality) BIT: Number of bits needed for the block RD: Rate distortion optimal (slow) ZERO: 0 VSAD: Sum of absolute vertical differences VSSE: Sum of squared vertical differences NSSE: Noise preserving sum of squared differences .P .BR ff_me_pre_cmp_chroma "=[1|0] (default: 0)" .P Enable chroma ME pre-pass compare .P .BR ff_pre_dia_size "= (-9..9, default: 0)" .P ME pre-pass diamond size & shape .P Motion estimation pre-pass diamond size. Negative means shape adaptive. .P .BR ff_lumi_masking "= (0.00..1.00, default: 0.00)" .P Luminance masking .P Encode very bright image parts with reduced quality. 0 means disabled, 0-0.3 is a sane range. .P .BR ff_dark_masking "= (0.00..1.00, default: 0.00)" .P Darkness masking .P Encode very dark image parts with reduced quality. 0 means disabled, 0-0.3 is a sane range. .P .BR ff_temporal_cplx_masking "= (0.00..1.00, default: 0.00)" .P Temporary complexity masking .P Encode very fast moving image parts with reduced quality. 0 means disabled. .P .BR ff_spatial_cplx_masking "= (0.00..1.00, default: 0.00)" .P Spatial complexity masking .P Encode very complex image parts with reduced quality. 0 means disabled, 0-0.5 is a sane range. .P .BR ff_border_masking "= (0.00..1.00, default: 0.00)" .P Border masking .P Encode image parts near the border with reduced quality. 0 means disabled .P .BR ff_p_masking "= (0.00..1.00, default: 0.00)" .P Inter block masking .P Encode inter blocks with reduced quality (increases the quality of intra blocks). 0 means disabled, 1 will double the bits allocated for intra blocks. .P .BR ff_flag_normalize_aqp "=[1|0] (default: 0)" .P Normalize adaptive quantization .P When using masking, try to adjust the per macroblock quantizers to maintain the desired average .P .BR ff_strict_std_compliance "= (-2..2, default: 0)" .P Standards compliance .P 2: Strictly conform to a older more strict version of the spec or reference software 1: Strictly conform to all the things in the spec no matter what consequences 0: Default -1: Allow inofficial extensions -2: Allow non standarized experimental things .P .BR ff_noise_reduction "= (0..2000, default: 0)" .P Noise reduction .P .BR ff_flag_gray "=[1|0] (default: 0)" .P Grayscale mode .P .BR ff_flag_bitexact "=[1|0] (default: 0)" .P Use only bitexact stuff .P Use only bitexact stuff (except (i)dct) .P .RE .B Suboptions for codec=mjpeg .P .RS 2 .BR ff_bit_rate_video "= (default: 800)" .P Bit rate (kbps) .P .BR ff_bit_rate_tolerance "= (default: 8000)" .P Bitrate tolerance (kbps) .P Number of bits the bitstream is allowed to diverge from the reference. Unused for constant quantizer encoding .P .BR ff_rc_min_rate "= (default: 0)" .P Minimum bitrate (kbps) .P Minimum bitrate (0 means arbitrary) .P .BR ff_rc_max_rate "= (default: 0)" .P Maximum bitrate (kbps) .P Maximum bitrate (0 means arbitrary) .P .BR ff_rc_buffer_size "= (default: 0)" .P RC buffer size .P Decoder bitstream buffer size in kbits. When encoding with max and/or min bitrate, this must be specified. .P .BR ff_rc_initial_cplx "= (0.0..99.0, default: 0.0)" .P Initial RC complexity .P .BR ff_rc_initial_buffer_occupancy "= (default: 0)" .P Initial RC buffer occupancy .P Number of kilobits which should be loaded into the rc buffer before encoding starts. Must not be larger than RC buffer size .P .BR ff_qmin "= (0..31, default: 2)" .P Minimum quantizer scale .P .BR ff_qmax "= (0..31, default: 31)" .P Maximum quantizer scale .P .BR ff_max_qdiff "= (0..31, default: 3)" .P Maximum quantizer difference .P Maximum quantizer difference between frames .P .BR ff_flag_qscale "=[1|0] (default: 0)" .P Use fixed quantizer .P Use fixed quality encoding .P .BR ff_qscale "= (1..31, default: 10)" .P Fixed quantizer .P Quantizer for fixed quality encoding. Lower means better, 1 is not recommended .P .BR ff_qcompress "= (0.00..1.00, default: 0.50)" .P Quantizer compression .P Amount of qscale change between easy & hard scenes .P .BR ff_qblur "= (0.00..1.00, default: 0.00)" .P Quantizer blur .P Amount of qscale smoothing over time .P .BR ff_quantizer_noise_shaping "= (0..3, default: 0)" .P Quantizer noise shaping .P Choose quantization such that noise will be masked by similar-frequency content in the image .P .BR ff_trellis "=[1|0] (default: 0)" .P Use trellis quantization .P Use trellis quantization (improves quality) .P .BR ff_strict_std_compliance "= (-2..2, default: 0)" .P Standards compliance .P 2: Strictly conform to a older more strict version of the spec or reference software 1: Strictly conform to all the things in the spec no matter what consequences 0: Default -1: Allow inofficial extensions -2: Allow non standarized experimental things .P .BR ff_noise_reduction "= (0..2000, default: 0)" .P Noise reduction .P .BR ff_flag_gray "=[1|0] (default: 0)" .P Grayscale mode .P .BR ff_flag_bitexact "=[1|0] (default: 0)" .P Use only bitexact stuff .P Use only bitexact stuff (except (i)dct) .P .RE .B Suboptions for codec=mpeg1video .P .RS 2 .BR gop_size "= (0..300, default: 250)" .P GOP size (0 = intra only) .P .BR ff_scenechange_threshold "= (-1000000000..1000000000, default: 0)" .P Scenechange threshold .P Threshold for scene change detection. Negative values mean more sensitivity (more keyframes) .P .BR ff_scenechange_factor "= (default: 0)" .P Scenechange factor .P Multiplied by qscale for each frame and added to scene_change_score .P .BR ff_flag_closed_gop "=[1|0] (default: 0)" .P Close all GOPs .P .BR ff_flag2_strict_gop "=[1|0] (default: 0)" .P Strictly enforce GOP size .P .BR ff_max_b_frames "= (0..16, default: 0)" .P Max B-Frames .P Maximum number of B-frames between non B-frames .P .BR ff_b_frame_strategy "=[1|0] (default: 0)" .P Avoid B-frames in high motion scenes .P .BR ff_bit_rate_video "= (default: 800)" .P Bit rate (kbps) .P .BR ff_bit_rate_tolerance "= (default: 8000)" .P Bitrate tolerance (kbps) .P Number of bits the bitstream is allowed to diverge from the reference. Unused for constant quantizer encoding .P .BR ff_rc_min_rate "= (default: 0)" .P Minimum bitrate (kbps) .P Minimum bitrate (0 means arbitrary) .P .BR ff_rc_max_rate "= (default: 0)" .P Maximum bitrate (kbps) .P Maximum bitrate (0 means arbitrary) .P .BR ff_rc_buffer_size "= (default: 0)" .P RC buffer size .P Decoder bitstream buffer size in kbits. When encoding with max and/or min bitrate, this must be specified. .P .BR ff_rc_initial_cplx "= (0.0..99.0, default: 0.0)" .P Initial RC complexity .P .BR ff_rc_initial_buffer_occupancy "= (default: 0)" .P Initial RC buffer occupancy .P Number of kilobits which should be loaded into the rc buffer before encoding starts. Must not be larger than RC buffer size .P .BR ff_qmin "= (0..31, default: 2)" .P Minimum quantizer scale .P .BR ff_qmax "= (0..31, default: 31)" .P Maximum quantizer scale .P .BR ff_max_qdiff "= (0..31, default: 3)" .P Maximum quantizer difference .P Maximum quantizer difference between frames .P .BR ff_flag_qscale "=[1|0] (default: 0)" .P Use fixed quantizer .P Use fixed quality encoding .P .BR ff_qscale "= (1..31, default: 10)" .P Fixed quantizer .P Quantizer for fixed quality encoding. Lower means better, 1 is not recommended .P .BR ff_qcompress "= (0.00..1.00, default: 0.50)" .P Quantizer compression .P Amount of qscale change between easy & hard scenes .P .BR ff_qblur "= (0.00..1.00, default: 0.00)" .P Quantizer blur .P Amount of qscale smoothing over time .P .BR ff_quantizer_noise_shaping "= (0..3, default: 0)" .P Quantizer noise shaping .P Choose quantization such that noise will be masked by similar-frequency content in the image .P .BR ff_trellis "=[1|0] (default: 0)" .P Use trellis quantization .P Use trellis quantization (improves quality) .P .BR ff_i_quant_factor "= (-31.0..31.0, default: -0.8)" .P I quantizer factor .P Quantizer factor between P-frames and I-frames. If > 0 then the last P frame quantizer will be used (q= lastp_q*factor+offset). If < 0 then normal ratecontrol will be done (q= -normal_q*factor+offset) .P .BR ff_i_quant_offset "= (0.0..31.0, default: 0.0)" .P I quantizer offset .P Quantizer offset between P-frames and I-frames .P .BR ff_b_quant_factor "= (-31.00..31.00, default: 1.25)" .P B quantizer factor .P Quantizer factor between B-frames and non-B-frames .P .BR ff_b_quant_offset "= (0.00..31.00, default: 1.25)" .P B quantizer offset .P Quantizer offset between B-frames and non-B-frames if > 0 then the last p frame quantizer will be used (q= lastp_q*factor+offset) if < 0 then normal ratecontrol will be done (q= -normal_q*factor+offset) .P .BR ff_me_method "=" .P Supported strings: Zero Phods Log X1 Epzs Full .P Default: Zero .P Motion estimation method .P .BR ff_me_cmp "=" .P Supported strings: SAD SSE SATD DCT PSNR BIT RD ZERO VSAD VSSE NSSE .P Default: SAD .P ME compare function .P Motion estimation compare function.SAD: Sum of absolute differences SSE: Sum of squared errors SATD: Sum of absolute Hadamard transformed differences DCT: Sum of absolute DCT transformed differences PSNR: Sum of squared quantization errors (low quality) BIT: Number of bits needed for the block RD: Rate distortion optimal (slow) ZERO: 0 VSAD: Sum of absolute vertical differences VSSE: Sum of squared vertical differences NSSE: Noise preserving sum of squared differences .P .BR ff_me_cmp_chroma "=[1|0] (default: 0)" .P Enable chroma ME compare .P .BR ff_me_range "= (0..1000, default: 0)" .P Motion estimation range .P Motion estimation search range (0 means unlimited) .P .BR ff_me_threshold "= (0..4000000, default: 0)" .P ME Theshold .P Motion estimation threshold. under which no motion estimation is performed, but instead the user specified motion vectors are used .P .BR ff_mb_decision "=" .P Supported strings: Use compare function Fewest bits Rate distoration .P Default: Use compare function .P MB decision mode .P .BR ff_dia_size "= (-9..9, default: 0)" .P ME diamond size & shape .P Motion estimation diamond size. Negative means shape adaptive. .P .BR ff_pre_me "= (0..2, default: 0)" .P ME pre-pass .P Motion estimation pre-pass 0: disabled 1: only after I-frames 2: always .P .BR ff_me_pre_cmp "=" .P Supported strings: SAD SSE SATD DCT PSNR BIT RD ZERO VSAD VSSE NSSE .P Default: SAD .P ME pre-pass compare function .P Motion estimation pre-pass compare function. SAD: Sum of absolute differences SSE: Sum of squared errors SATD: Sum of absolute Hadamard transformed differences DCT: Sum of absolute DCT transformed differences PSNR: Sum of squared quantization errors (low quality) BIT: Number of bits needed for the block RD: Rate distortion optimal (slow) ZERO: 0 VSAD: Sum of absolute vertical differences VSSE: Sum of squared vertical differences NSSE: Noise preserving sum of squared differences .P .BR ff_me_pre_cmp_chroma "=[1|0] (default: 0)" .P Enable chroma ME pre-pass compare .P .BR ff_pre_dia_size "= (-9..9, default: 0)" .P ME pre-pass diamond size & shape .P Motion estimation pre-pass diamond size. Negative means shape adaptive. .P .BR ff_lumi_masking "= (0.00..1.00, default: 0.00)" .P Luminance masking .P Encode very bright image parts with reduced quality. 0 means disabled, 0-0.3 is a sane range. .P .BR ff_dark_masking "= (0.00..1.00, default: 0.00)" .P Darkness masking .P Encode very dark image parts with reduced quality. 0 means disabled, 0-0.3 is a sane range. .P .BR ff_temporal_cplx_masking "= (0.00..1.00, default: 0.00)" .P Temporary complexity masking .P Encode very fast moving image parts with reduced quality. 0 means disabled. .P .BR ff_spatial_cplx_masking "= (0.00..1.00, default: 0.00)" .P Spatial complexity masking .P Encode very complex image parts with reduced quality. 0 means disabled, 0-0.5 is a sane range. .P .BR ff_border_masking "= (0.00..1.00, default: 0.00)" .P Border masking .P Encode image parts near the border with reduced quality. 0 means disabled .P .BR ff_p_masking "= (0.00..1.00, default: 0.00)" .P Inter block masking .P Encode inter blocks with reduced quality (increases the quality of intra blocks). 0 means disabled, 1 will double the bits allocated for intra blocks. .P .BR ff_flag_normalize_aqp "=[1|0] (default: 0)" .P Normalize adaptive quantization .P When using masking, try to adjust the per macroblock quantizers to maintain the desired average .P .BR ff_strict_std_compliance "= (-2..2, default: 0)" .P Standards compliance .P 2: Strictly conform to a older more strict version of the spec or reference software 1: Strictly conform to all the things in the spec no matter what consequences 0: Default -1: Allow inofficial extensions -2: Allow non standarized experimental things .P .BR ff_noise_reduction "= (0..2000, default: 0)" .P Noise reduction .P .BR ff_flag_gray "=[1|0] (default: 0)" .P Grayscale mode .P .BR ff_flag_bitexact "=[1|0] (default: 0)" .P Use only bitexact stuff .P Use only bitexact stuff (except (i)dct) .P .RE .B Suboptions for codec=mpeg2video .P .RS 2 .BR gop_size "= (0..300, default: 250)" .P GOP size (0 = intra only) .P .BR ff_scenechange_threshold "= (-1000000000..1000000000, default: 0)" .P Scenechange threshold .P Threshold for scene change detection. Negative values mean more sensitivity (more keyframes) .P .BR ff_scenechange_factor "= (default: 0)" .P Scenechange factor .P Multiplied by qscale for each frame and added to scene_change_score .P .BR ff_flag_closed_gop "=[1|0] (default: 0)" .P Close all GOPs .P .BR ff_flag2_strict_gop "=[1|0] (default: 0)" .P Strictly enforce GOP size .P .BR ff_max_b_frames "= (0..16, default: 0)" .P Max B-Frames .P Maximum number of B-frames between non B-frames .P .BR ff_b_frame_strategy "=[1|0] (default: 0)" .P Avoid B-frames in high motion scenes .P .BR ff_bit_rate_video "= (default: 800)" .P Bit rate (kbps) .P .BR ff_bit_rate_tolerance "= (default: 8000)" .P Bitrate tolerance (kbps) .P Number of bits the bitstream is allowed to diverge from the reference. Unused for constant quantizer encoding .P .BR ff_rc_min_rate "= (default: 0)" .P Minimum bitrate (kbps) .P Minimum bitrate (0 means arbitrary) .P .BR ff_rc_max_rate "= (default: 0)" .P Maximum bitrate (kbps) .P Maximum bitrate (0 means arbitrary) .P .BR ff_rc_buffer_size "= (default: 0)" .P RC buffer size .P Decoder bitstream buffer size in kbits. When encoding with max and/or min bitrate, this must be specified. .P .BR ff_rc_initial_cplx "= (0.0..99.0, default: 0.0)" .P Initial RC complexity .P .BR ff_rc_initial_buffer_occupancy "= (default: 0)" .P Initial RC buffer occupancy .P Number of kilobits which should be loaded into the rc buffer before encoding starts. Must not be larger than RC buffer size .P .BR ff_qmin "= (0..31, default: 2)" .P Minimum quantizer scale .P .BR ff_qmax "= (0..31, default: 31)" .P Maximum quantizer scale .P .BR ff_max_qdiff "= (0..31, default: 3)" .P Maximum quantizer difference .P Maximum quantizer difference between frames .P .BR ff_flag_qscale "=[1|0] (default: 0)" .P Use fixed quantizer .P Use fixed quality encoding .P .BR ff_qscale "= (1..31, default: 10)" .P Fixed quantizer .P Quantizer for fixed quality encoding. Lower means better, 1 is not recommended .P .BR ff_qcompress "= (0.00..1.00, default: 0.50)" .P Quantizer compression .P Amount of qscale change between easy & hard scenes .P .BR ff_qblur "= (0.00..1.00, default: 0.00)" .P Quantizer blur .P Amount of qscale smoothing over time .P .BR ff_quantizer_noise_shaping "= (0..3, default: 0)" .P Quantizer noise shaping .P Choose quantization such that noise will be masked by similar-frequency content in the image .P .BR ff_trellis "=[1|0] (default: 0)" .P Use trellis quantization .P Use trellis quantization (improves quality) .P .BR ff_i_quant_factor "= (-31.0..31.0, default: -0.8)" .P I quantizer factor .P Quantizer factor between P-frames and I-frames. If > 0 then the last P frame quantizer will be used (q= lastp_q*factor+offset). If < 0 then normal ratecontrol will be done (q= -normal_q*factor+offset) .P .BR ff_i_quant_offset "= (0.0..31.0, default: 0.0)" .P I quantizer offset .P Quantizer offset between P-frames and I-frames .P .BR ff_b_quant_factor "= (-31.00..31.00, default: 1.25)" .P B quantizer factor .P Quantizer factor between B-frames and non-B-frames .P .BR ff_b_quant_offset "= (0.00..31.00, default: 1.25)" .P B quantizer offset .P Quantizer offset between B-frames and non-B-frames if > 0 then the last p frame quantizer will be used (q= lastp_q*factor+offset) if < 0 then normal ratecontrol will be done (q= -normal_q*factor+offset) .P .BR ff_me_method "=" .P Supported strings: Zero Phods Log X1 Epzs Full .P Default: Zero .P Motion estimation method .P .BR ff_me_cmp "=" .P Supported strings: SAD SSE SATD DCT PSNR BIT RD ZERO VSAD VSSE NSSE .P Default: SAD .P ME compare function .P Motion estimation compare function.SAD: Sum of absolute differences SSE: Sum of squared errors SATD: Sum of absolute Hadamard transformed differences DCT: Sum of absolute DCT transformed differences PSNR: Sum of squared quantization errors (low quality) BIT: Number of bits needed for the block RD: Rate distortion optimal (slow) ZERO: 0 VSAD: Sum of absolute vertical differences VSSE: Sum of squared vertical differences NSSE: Noise preserving sum of squared differences .P .BR ff_me_cmp_chroma "=[1|0] (default: 0)" .P Enable chroma ME compare .P .BR ff_me_range "= (0..1000, default: 0)" .P Motion estimation range .P Motion estimation search range (0 means unlimited) .P .BR ff_me_threshold "= (0..4000000, default: 0)" .P ME Theshold .P Motion estimation threshold. under which no motion estimation is performed, but instead the user specified motion vectors are used .P .BR ff_mb_decision "=" .P Supported strings: Use compare function Fewest bits Rate distoration .P Default: Use compare function .P MB decision mode .P .BR ff_dia_size "= (-9..9, default: 0)" .P ME diamond size & shape .P Motion estimation diamond size. Negative means shape adaptive. .P .BR ff_pre_me "= (0..2, default: 0)" .P ME pre-pass .P Motion estimation pre-pass 0: disabled 1: only after I-frames 2: always .P .BR ff_me_pre_cmp "=" .P Supported strings: SAD SSE SATD DCT PSNR BIT RD ZERO VSAD VSSE NSSE .P Default: SAD .P ME pre-pass compare function .P Motion estimation pre-pass compare function. SAD: Sum of absolute differences SSE: Sum of squared errors SATD: Sum of absolute Hadamard transformed differences DCT: Sum of absolute DCT transformed differences PSNR: Sum of squared quantization errors (low quality) BIT: Number of bits needed for the block RD: Rate distortion optimal (slow) ZERO: 0 VSAD: Sum of absolute vertical differences VSSE: Sum of squared vertical differences NSSE: Noise preserving sum of squared differences .P .BR ff_me_pre_cmp_chroma "=[1|0] (default: 0)" .P Enable chroma ME pre-pass compare .P .BR ff_pre_dia_size "= (-9..9, default: 0)" .P ME pre-pass diamond size & shape .P Motion estimation pre-pass diamond size. Negative means shape adaptive. .P .BR ff_lumi_masking "= (0.00..1.00, default: 0.00)" .P Luminance masking .P Encode very bright image parts with reduced quality. 0 means disabled, 0-0.3 is a sane range. .P .BR ff_dark_masking "= (0.00..1.00, default: 0.00)" .P Darkness masking .P Encode very dark image parts with reduced quality. 0 means disabled, 0-0.3 is a sane range. .P .BR ff_temporal_cplx_masking "= (0.00..1.00, default: 0.00)" .P Temporary complexity masking .P Encode very fast moving image parts with reduced quality. 0 means disabled. .P .BR ff_spatial_cplx_masking "= (0.00..1.00, default: 0.00)" .P Spatial complexity masking .P Encode very complex image parts with reduced quality. 0 means disabled, 0-0.5 is a sane range. .P .BR ff_border_masking "= (0.00..1.00, default: 0.00)" .P Border masking .P Encode image parts near the border with reduced quality. 0 means disabled .P .BR ff_p_masking "= (0.00..1.00, default: 0.00)" .P Inter block masking .P Encode inter blocks with reduced quality (increases the quality of intra blocks). 0 means disabled, 1 will double the bits allocated for intra blocks. .P .BR ff_flag_normalize_aqp "=[1|0] (default: 0)" .P Normalize adaptive quantization .P When using masking, try to adjust the per macroblock quantizers to maintain the desired average .P .BR ff_strict_std_compliance "= (-2..2, default: 0)" .P Standards compliance .P 2: Strictly conform to a older more strict version of the spec or reference software 1: Strictly conform to all the things in the spec no matter what consequences 0: Default -1: Allow inofficial extensions -2: Allow non standarized experimental things .P .BR ff_noise_reduction "= (0..2000, default: 0)" .P Noise reduction .P .BR ff_flag_gray "=[1|0] (default: 0)" .P Grayscale mode .P .BR ff_flag_bitexact "=[1|0] (default: 0)" .P Use only bitexact stuff .P Use only bitexact stuff (except (i)dct) .P .RE .B Suboptions for codec=flv1 .P .RS 2 .BR gop_size "= (0..300, default: 250)" .P GOP size (0 = intra only) .P .BR ff_scenechange_threshold "= (-1000000000..1000000000, default: 0)" .P Scenechange threshold .P Threshold for scene change detection. Negative values mean more sensitivity (more keyframes) .P .BR ff_scenechange_factor "= (default: 0)" .P Scenechange factor .P Multiplied by qscale for each frame and added to scene_change_score .P .BR ff_flag_closed_gop "=[1|0] (default: 0)" .P Close all GOPs .P .BR ff_flag2_strict_gop "=[1|0] (default: 0)" .P Strictly enforce GOP size .P .BR ff_bit_rate_video "= (default: 800)" .P Bit rate (kbps) .P .BR ff_bit_rate_tolerance "= (default: 8000)" .P Bitrate tolerance (kbps) .P Number of bits the bitstream is allowed to diverge from the reference. Unused for constant quantizer encoding .P .BR ff_rc_min_rate "= (default: 0)" .P Minimum bitrate (kbps) .P Minimum bitrate (0 means arbitrary) .P .BR ff_rc_max_rate "= (default: 0)" .P Maximum bitrate (kbps) .P Maximum bitrate (0 means arbitrary) .P .BR ff_rc_buffer_size "= (default: 0)" .P RC buffer size .P Decoder bitstream buffer size in kbits. When encoding with max and/or min bitrate, this must be specified. .P .BR ff_rc_initial_cplx "= (0.0..99.0, default: 0.0)" .P Initial RC complexity .P .BR ff_rc_initial_buffer_occupancy "= (default: 0)" .P Initial RC buffer occupancy .P Number of kilobits which should be loaded into the rc buffer before encoding starts. Must not be larger than RC buffer size .P .BR ff_qmin "= (0..31, default: 2)" .P Minimum quantizer scale .P .BR ff_qmax "= (0..31, default: 31)" .P Maximum quantizer scale .P .BR ff_max_qdiff "= (0..31, default: 3)" .P Maximum quantizer difference .P Maximum quantizer difference between frames .P .BR ff_flag_qscale "=[1|0] (default: 0)" .P Use fixed quantizer .P Use fixed quality encoding .P .BR ff_qscale "= (1..31, default: 10)" .P Fixed quantizer .P Quantizer for fixed quality encoding. Lower means better, 1 is not recommended .P .BR ff_qcompress "= (0.00..1.00, default: 0.50)" .P Quantizer compression .P Amount of qscale change between easy & hard scenes .P .BR ff_qblur "= (0.00..1.00, default: 0.00)" .P Quantizer blur .P Amount of qscale smoothing over time .P .BR ff_quantizer_noise_shaping "= (0..3, default: 0)" .P Quantizer noise shaping .P Choose quantization such that noise will be masked by similar-frequency content in the image .P .BR ff_trellis "=[1|0] (default: 0)" .P Use trellis quantization .P Use trellis quantization (improves quality) .P .BR ff_i_quant_factor "= (-31.0..31.0, default: -0.8)" .P I quantizer factor .P Quantizer factor between P-frames and I-frames. If > 0 then the last P frame quantizer will be used (q= lastp_q*factor+offset). If < 0 then normal ratecontrol will be done (q= -normal_q*factor+offset) .P .BR ff_i_quant_offset "= (0.0..31.0, default: 0.0)" .P I quantizer offset .P Quantizer offset between P-frames and I-frames .P .BR ff_me_method "=" .P Supported strings: Zero Phods Log X1 Epzs Full .P Default: Zero .P Motion estimation method .P .BR ff_me_cmp "=" .P Supported strings: SAD SSE SATD DCT PSNR BIT RD ZERO VSAD VSSE NSSE .P Default: SAD .P ME compare function .P Motion estimation compare function.SAD: Sum of absolute differences SSE: Sum of squared errors SATD: Sum of absolute Hadamard transformed differences DCT: Sum of absolute DCT transformed differences PSNR: Sum of squared quantization errors (low quality) BIT: Number of bits needed for the block RD: Rate distortion optimal (slow) ZERO: 0 VSAD: Sum of absolute vertical differences VSSE: Sum of squared vertical differences NSSE: Noise preserving sum of squared differences .P .BR ff_me_cmp_chroma "=[1|0] (default: 0)" .P Enable chroma ME compare .P .BR ff_me_range "= (0..1000, default: 0)" .P Motion estimation range .P Motion estimation search range (0 means unlimited) .P .BR ff_me_threshold "= (0..4000000, default: 0)" .P ME Theshold .P Motion estimation threshold. under which no motion estimation is performed, but instead the user specified motion vectors are used .P .BR ff_mb_decision "=" .P Supported strings: Use compare function Fewest bits Rate distoration .P Default: Use compare function .P MB decision mode .P .BR ff_dia_size "= (-9..9, default: 0)" .P ME diamond size & shape .P Motion estimation diamond size. Negative means shape adaptive. .P .BR ff_pre_me "= (0..2, default: 0)" .P ME pre-pass .P Motion estimation pre-pass 0: disabled 1: only after I-frames 2: always .P .BR ff_me_pre_cmp "=" .P Supported strings: SAD SSE SATD DCT PSNR BIT RD ZERO VSAD VSSE NSSE .P Default: SAD .P ME pre-pass compare function .P Motion estimation pre-pass compare function. SAD: Sum of absolute differences SSE: Sum of squared errors SATD: Sum of absolute Hadamard transformed differences DCT: Sum of absolute DCT transformed differences PSNR: Sum of squared quantization errors (low quality) BIT: Number of bits needed for the block RD: Rate distortion optimal (slow) ZERO: 0 VSAD: Sum of absolute vertical differences VSSE: Sum of squared vertical differences NSSE: Noise preserving sum of squared differences .P .BR ff_me_pre_cmp_chroma "=[1|0] (default: 0)" .P Enable chroma ME pre-pass compare .P .BR ff_pre_dia_size "= (-9..9, default: 0)" .P ME pre-pass diamond size & shape .P Motion estimation pre-pass diamond size. Negative means shape adaptive. .P .BR ff_lumi_masking "= (0.00..1.00, default: 0.00)" .P Luminance masking .P Encode very bright image parts with reduced quality. 0 means disabled, 0-0.3 is a sane range. .P .BR ff_dark_masking "= (0.00..1.00, default: 0.00)" .P Darkness masking .P Encode very dark image parts with reduced quality. 0 means disabled, 0-0.3 is a sane range. .P .BR ff_temporal_cplx_masking "= (0.00..1.00, default: 0.00)" .P Temporary complexity masking .P Encode very fast moving image parts with reduced quality. 0 means disabled. .P .BR ff_spatial_cplx_masking "= (0.00..1.00, default: 0.00)" .P Spatial complexity masking .P Encode very complex image parts with reduced quality. 0 means disabled, 0-0.5 is a sane range. .P .BR ff_border_masking "= (0.00..1.00, default: 0.00)" .P Border masking .P Encode image parts near the border with reduced quality. 0 means disabled .P .BR ff_p_masking "= (0.00..1.00, default: 0.00)" .P Inter block masking .P Encode inter blocks with reduced quality (increases the quality of intra blocks). 0 means disabled, 1 will double the bits allocated for intra blocks. .P .BR ff_flag_normalize_aqp "=[1|0] (default: 0)" .P Normalize adaptive quantization .P When using masking, try to adjust the per macroblock quantizers to maintain the desired average .P .BR ff_strict_std_compliance "= (-2..2, default: 0)" .P Standards compliance .P 2: Strictly conform to a older more strict version of the spec or reference software 1: Strictly conform to all the things in the spec no matter what consequences 0: Default -1: Allow inofficial extensions -2: Allow non standarized experimental things .P .BR ff_noise_reduction "= (0..2000, default: 0)" .P Noise reduction .P .BR ff_flag_gray "=[1|0] (default: 0)" .P Grayscale mode .P .BR ff_flag_bitexact "=[1|0] (default: 0)" .P Use only bitexact stuff .P Use only bitexact stuff (except (i)dct) .P .RE .B Suboptions for codec=wmv1 .P .RS 2 .BR gop_size "= (0..300, default: 250)" .P GOP size (0 = intra only) .P .BR ff_scenechange_threshold "= (-1000000000..1000000000, default: 0)" .P Scenechange threshold .P Threshold for scene change detection. Negative values mean more sensitivity (more keyframes) .P .BR ff_scenechange_factor "= (default: 0)" .P Scenechange factor .P Multiplied by qscale for each frame and added to scene_change_score .P .BR ff_flag_closed_gop "=[1|0] (default: 0)" .P Close all GOPs .P .BR ff_flag2_strict_gop "=[1|0] (default: 0)" .P Strictly enforce GOP size .P .BR ff_bit_rate_video "= (default: 800)" .P Bit rate (kbps) .P .BR ff_bit_rate_tolerance "= (default: 8000)" .P Bitrate tolerance (kbps) .P Number of bits the bitstream is allowed to diverge from the reference. Unused for constant quantizer encoding .P .BR ff_rc_min_rate "= (default: 0)" .P Minimum bitrate (kbps) .P Minimum bitrate (0 means arbitrary) .P .BR ff_rc_max_rate "= (default: 0)" .P Maximum bitrate (kbps) .P Maximum bitrate (0 means arbitrary) .P .BR ff_rc_buffer_size "= (default: 0)" .P RC buffer size .P Decoder bitstream buffer size in kbits. When encoding with max and/or min bitrate, this must be specified. .P .BR ff_rc_initial_cplx "= (0.0..99.0, default: 0.0)" .P Initial RC complexity .P .BR ff_rc_initial_buffer_occupancy "= (default: 0)" .P Initial RC buffer occupancy .P Number of kilobits which should be loaded into the rc buffer before encoding starts. Must not be larger than RC buffer size .P .BR ff_qmin "= (0..31, default: 2)" .P Minimum quantizer scale .P .BR ff_qmax "= (0..31, default: 31)" .P Maximum quantizer scale .P .BR ff_max_qdiff "= (0..31, default: 3)" .P Maximum quantizer difference .P Maximum quantizer difference between frames .P .BR ff_flag_qscale "=[1|0] (default: 0)" .P Use fixed quantizer .P Use fixed quality encoding .P .BR ff_qscale "= (1..31, default: 10)" .P Fixed quantizer .P Quantizer for fixed quality encoding. Lower means better, 1 is not recommended .P .BR ff_qcompress "= (0.00..1.00, default: 0.50)" .P Quantizer compression .P Amount of qscale change between easy & hard scenes .P .BR ff_qblur "= (0.00..1.00, default: 0.00)" .P Quantizer blur .P Amount of qscale smoothing over time .P .BR ff_quantizer_noise_shaping "= (0..3, default: 0)" .P Quantizer noise shaping .P Choose quantization such that noise will be masked by similar-frequency content in the image .P .BR ff_trellis "=[1|0] (default: 0)" .P Use trellis quantization .P Use trellis quantization (improves quality) .P .BR ff_i_quant_factor "= (-31.0..31.0, default: -0.8)" .P I quantizer factor .P Quantizer factor between P-frames and I-frames. If > 0 then the last P frame quantizer will be used (q= lastp_q*factor+offset). If < 0 then normal ratecontrol will be done (q= -normal_q*factor+offset) .P .BR ff_i_quant_offset "= (0.0..31.0, default: 0.0)" .P I quantizer offset .P Quantizer offset between P-frames and I-frames .P .BR ff_me_method "=" .P Supported strings: Zero Phods Log X1 Epzs Full .P Default: Zero .P Motion estimation method .P .BR ff_me_cmp "=" .P Supported strings: SAD SSE SATD DCT PSNR BIT RD ZERO VSAD VSSE NSSE .P Default: SAD .P ME compare function .P Motion estimation compare function.SAD: Sum of absolute differences SSE: Sum of squared errors SATD: Sum of absolute Hadamard transformed differences DCT: Sum of absolute DCT transformed differences PSNR: Sum of squared quantization errors (low quality) BIT: Number of bits needed for the block RD: Rate distortion optimal (slow) ZERO: 0 VSAD: Sum of absolute vertical differences VSSE: Sum of squared vertical differences NSSE: Noise preserving sum of squared differences .P .BR ff_me_cmp_chroma "=[1|0] (default: 0)" .P Enable chroma ME compare .P .BR ff_me_range "= (0..1000, default: 0)" .P Motion estimation range .P Motion estimation search range (0 means unlimited) .P .BR ff_me_threshold "= (0..4000000, default: 0)" .P ME Theshold .P Motion estimation threshold. under which no motion estimation is performed, but instead the user specified motion vectors are used .P .BR ff_mb_decision "=" .P Supported strings: Use compare function Fewest bits Rate distoration .P Default: Use compare function .P MB decision mode .P .BR ff_dia_size "= (-9..9, default: 0)" .P ME diamond size & shape .P Motion estimation diamond size. Negative means shape adaptive. .P .BR ff_pre_me "= (0..2, default: 0)" .P ME pre-pass .P Motion estimation pre-pass 0: disabled 1: only after I-frames 2: always .P .BR ff_me_pre_cmp "=" .P Supported strings: SAD SSE SATD DCT PSNR BIT RD ZERO VSAD VSSE NSSE .P Default: SAD .P ME pre-pass compare function .P Motion estimation pre-pass compare function. SAD: Sum of absolute differences SSE: Sum of squared errors SATD: Sum of absolute Hadamard transformed differences DCT: Sum of absolute DCT transformed differences PSNR: Sum of squared quantization errors (low quality) BIT: Number of bits needed for the block RD: Rate distortion optimal (slow) ZERO: 0 VSAD: Sum of absolute vertical differences VSSE: Sum of squared vertical differences NSSE: Noise preserving sum of squared differences .P .BR ff_me_pre_cmp_chroma "=[1|0] (default: 0)" .P Enable chroma ME pre-pass compare .P .BR ff_pre_dia_size "= (-9..9, default: 0)" .P ME pre-pass diamond size & shape .P Motion estimation pre-pass diamond size. Negative means shape adaptive. .P .BR ff_lumi_masking "= (0.00..1.00, default: 0.00)" .P Luminance masking .P Encode very bright image parts with reduced quality. 0 means disabled, 0-0.3 is a sane range. .P .BR ff_dark_masking "= (0.00..1.00, default: 0.00)" .P Darkness masking .P Encode very dark image parts with reduced quality. 0 means disabled, 0-0.3 is a sane range. .P .BR ff_temporal_cplx_masking "= (0.00..1.00, default: 0.00)" .P Temporary complexity masking .P Encode very fast moving image parts with reduced quality. 0 means disabled. .P .BR ff_spatial_cplx_masking "= (0.00..1.00, default: 0.00)" .P Spatial complexity masking .P Encode very complex image parts with reduced quality. 0 means disabled, 0-0.5 is a sane range. .P .BR ff_border_masking "= (0.00..1.00, default: 0.00)" .P Border masking .P Encode image parts near the border with reduced quality. 0 means disabled .P .BR ff_p_masking "= (0.00..1.00, default: 0.00)" .P Inter block masking .P Encode inter blocks with reduced quality (increases the quality of intra blocks). 0 means disabled, 1 will double the bits allocated for intra blocks. .P .BR ff_flag_normalize_aqp "=[1|0] (default: 0)" .P Normalize adaptive quantization .P When using masking, try to adjust the per macroblock quantizers to maintain the desired average .P .BR ff_strict_std_compliance "= (-2..2, default: 0)" .P Standards compliance .P 2: Strictly conform to a older more strict version of the spec or reference software 1: Strictly conform to all the things in the spec no matter what consequences 0: Default -1: Allow inofficial extensions -2: Allow non standarized experimental things .P .BR ff_noise_reduction "= (0..2000, default: 0)" .P Noise reduction .P .BR ff_flag_gray "=[1|0] (default: 0)" .P Grayscale mode .P .BR ff_flag_bitexact "=[1|0] (default: 0)" .P Use only bitexact stuff .P Use only bitexact stuff (except (i)dct) .P .RE .BR default_timescale "= (default: 25)" .P Default timescale .P For formats, which support only constant framerates, set the default timescale here .P .BR default_frame_duration "= (default: 1)" .P Default frame duration .P For formats, which support only constant framerates, set the default frame duration here .P .RE .B Suboptions for video_encoder=b_ogg .P .RS 2 .BR server "= (Default: localhost)" .P Server .P .BR port "= (1..65535, default: 8000)" .P Port .P .BR mount "= (Default: /stream.ogg)" .P Mount .P .BR user "= (Default: source)" .P User .P .BR password "=" .P Password .P .BR name "= (Default: Test stream)" .P Name .P .BR description "= (Default: Brought to you by gmerlin)" .P Description .P .BR codec "=option[{suboptions}]" .P Supported options: vorbis speex .P Default: vorbis .P Codec .P .B Suboptions for codec=vorbis .P .RS 2 .BR bitrate_mode "=" .P Supported strings: vbr vbr_bitrate managed .P Default: VBR .P Bitrate mode .P Bitrate mode: VBR: You specify a quality and (optionally) a minimum and maximum bitrate VBR (bitrate): The specified nominal bitrate will be used for selecting the encoder mode. Managed: You specify a nominal bitrate and (optionally) a minimum and maximum bitrate VBR is recommended, managed bitrate might result in a worse quality .P .BR nominal_bitrate "= (0..1000, default: 128)" .P Nominal bitrate (kbps) .P Nominal bitrate (in kbps) for managed mode .P .BR quality "= (0.0..10.0, default: 3.0)" .P VBR Quality (10: best) .P Quality for VBR mode 10: best (largest output file) 0: worst (smallest output file) .P .BR min_bitrate "= (0..1000, default: 0)" .P Minimum bitrate (kbps) .P Optional minimum bitrate (in kbps) 0 = unspecified .P .BR max_bitrate "= (0..1000, default: 0)" .P Maximum bitrate (kbps) .P Optional maximum bitrate (in kbps) 0 = unspecified .P .RE .B Suboptions for codec=speex .P .RS 2 .BR mode "=" .P Supported strings: auto nb wb uwb .P Default: auto .P Speex mode .P Encoding mode. If you select Auto, the mode will be taken from the samplerate. .P .BR quality "= (0..10, default: 3)" .P Quality (10: best) .P .BR complexity "= (0..10, default: 3)" .P Encoding complexity .P .BR nframes "= (1..10, default: 1)" .P Frames per Ogg packet .P .BR bitrate "= (0..128, default: 8)" .P Bitrate (kbps) .P Bitrate (in kbps). Set to 0 for seleting the standard bitrates for the encoding mode. .P .BR vbr "=[1|0] (default: 0)" .P Variable bitrate .P .BR abr_bitrate "= (0..128, default: 0)" .P Average bitrate (kbps) .P Average bitrate (in kbps). Set to 0 for disabling ABR. .P .BR vad "=[1|0] (default: 0)" .P Use voice activity detection .P .BR dtx "=[1|0] (default: 0)" .P Enable file-based discontinuous transmission .P .RE .BR cbr "=[1|0] (default: 0)" .P Use constant bitrate .P For constant bitrate, choose a target bitrate. For variable bitrate, choose a nominal quality. .P .BR target_bitrate "= (45..2000, default: 250)" .P Target bitrate (kbps) .P .BR quality "= (0..63, default: 10)" .P Nominal quality .P Quality for VBR mode 63: best (largest output file) 0: worst (smallest output file) .P .BR max_keyframe_interval "= (1..1000, default: 64)" .P Maximum keyframe interval .P .BR drop_frames "=[1|0] (default: 1)" .P Enable frame dropping .P Drop frames to keep within bitrate buffer constraints. This can have a severe impact on quality, but is the only way to ensure that bitrate targets are met at low rates during sudden bursts of activity. .P .BR cap_overflow "=[1|0] (default: 1)" .P Don't bank excess bits for later use .P Ignore bitrate buffer overflows. If the encoder uses so few bits that the reservoir of available bits overflows, ignore the excess. The encoder will not try to use these extra bits in future frames. At high rates this may cause the result to be undersized, but allows a client to play the stream using a finite buffer; it should normally be enabled. .P .BR cap_underflow "=[1|0] (default: 0)" .P Don't try to make up shortfalls later .P Ignore bitrate buffer underflows. If the encoder uses so many bits that the reservoir of available bits underflows, ignore the deficit. The encoder will not try to make up these extra bits in future frames. At low rates this may cause the result to be oversized; it should normally be disabled. .P .BR speed "= (0.00..1.00, default: 0.00)" .P Encoding speed .P Higher speed levels favor quicker encoding over better quality per bit. Depending on the encoding mode, and the internal algorithms used, quality may actually improve, but in this case bitrate will also likely increase. In any case, overall rate/distortion performance will probably decrease. .P .BR default_timescale "= (default: 25)" .P Default timescale .P For formats, which support only constant framerates, set the default timescale here .P .BR default_frame_duration "= (default: 1)" .P Default frame duration .P For formats, which support only constant framerates, set the default frame duration here .P .RE .RE .B -o .I .RS 2 Set output options .RE .RS 2 .BR output_directory "= (Default: .)" .P Output directory .P .BR output_filename_mask "= (Default: %Y-%m-%d-%H-%M-%S)" .P Output filename mask .P Extension is appended by the plugin For the date and time formatting, consult the documentation of the strftime(3) function .P .BR snapshot_directory "= (Default: .)" .P Snapshot directory .P .BR snapshot_filename_mask "= (Default: shot_%5n)" .P Snapshot filename mask .P Extension is appended by the plugin %t Inserts time %d Inserts date %n Inserts Frame number with digits .P .RE .B -r .RS 2 Record to file .RE .B -syslog .I .RS 2 Set log messages to syslog .RE .SH GENERIC OPTIONS The following generic options are available for all gmerlin applications .B -help .RS 2 Print this help message and exit .RE .B -help-man .RS 2 Print this help message as a manual page and exit .RE .B -help-texi .RS 2 Print this help message in texinfo format and exit .RE .B -version .RS 2 Print version info and exit .RE .SH FILES .B ~/.gmerlin/plugins.xml .RS 2 Cache of the plugin registry (shared by all applicatons) .RE .P .B ~/.gmerlin/generic/config.xml .RS 2 Default plugin parameters are read from there. Use gmerlin_plugincfg to change them. .RE .P gmerlin-1.2.0~dfsg/apps/recorder/0000755000175000017500000000000011764363443016654 5ustar alessioalessiogmerlin-1.2.0~dfsg/apps/recorder/recorder_window.h0000644000175000017500000000243311764363402022216 0ustar alessioalessio/***************************************************************** * gmerlin - a general purpose multimedia framework and applications * * Copyright (c) 2001 - 2011 Members of the Gmerlin project * gmerlin-general@lists.sourceforge.net * http://gmerlin.sourceforge.net * * 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 of the License, 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 this program. If not, see . * *****************************************************************/ typedef struct bg_recorder_window_s bg_recorder_window_t; bg_recorder_window_t * bg_recorder_window_create(bg_cfg_registry_t * cfg_reg, bg_plugin_registry_t * plugin_reg); void bg_recorder_window_run(bg_recorder_window_t *); void bg_recorder_window_destroy(bg_recorder_window_t *); gmerlin-1.2.0~dfsg/apps/recorder/Makefile.am0000644000175000017500000000111611764363402020702 0ustar alessioalessioplugindir=$(pkglibdir)/plugins INCLUDES = -I$(top_srcdir)/include AM_CFLAGS = \ @XML2_CFLAGS@ \ @GTK_CFLAGS@ \ -DLOCALE_DIR=\"$(localedir)\" \ -DPLUGIN_DIR=\"$(plugindir)\" \ -DDOC_DIR=\"$(docdir)\" \ -DDATA_DIR=\"$(pkgdatadir)\" Desktopdir = $(datadir)/applications Desktop_DATA = gmerlin-recorder.desktop bin_PROGRAMS = gmerlin_recorder gmerlin_recorder_SOURCES = gmerlin_recorder.c recorder_window.c gmerlin_recorder_LDADD = \ $(top_builddir)/lib/gtk/libgmerlin_gtk.la \ $(top_builddir)/lib/libgmerlin.la noinst_HEADERS = recorder_window.h EXTRA_DIST = gmerlin-recorder.desktop gmerlin-1.2.0~dfsg/apps/recorder/gmerlin-recorder.desktop0000644000175000017500000000036211764363402023503 0ustar alessioalessio[Desktop Entry] Encoding=UTF-8 Name=Gmerlin recorder Name[de]=Gmerlin recorder Comment=Audio/video recorder Comment[de]=Audio/video recorder Exec=gmerlin_recorder Icon=gmerlin-recorder.png Type=Application Categories=Application;AudioVideo; gmerlin-1.2.0~dfsg/apps/recorder/Makefile.in0000644000175000017500000005245011764363423020725 0ustar alessioalessio# Makefile.in generated by automake 1.11.1 from Makefile.am. # @configure_input@ # Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, # 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation, # Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ VPATH = @srcdir@ pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ bin_PROGRAMS = gmerlin_recorder$(EXEEXT) subdir = apps/recorder DIST_COMMON = $(noinst_HEADERS) $(srcdir)/Makefile.am \ $(srcdir)/Makefile.in ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/m4/check_funcs.m4 \ $(top_srcdir)/m4/gavl_simd.m4 $(top_srcdir)/m4/gettext.m4 \ $(top_srcdir)/m4/iconv.m4 $(top_srcdir)/m4/lib-ld.m4 \ $(top_srcdir)/m4/lib-link.m4 $(top_srcdir)/m4/lib-prefix.m4 \ $(top_srcdir)/m4/lqt_opt_cflags.m4 $(top_srcdir)/m4/nls.m4 \ $(top_srcdir)/m4/po.m4 $(top_srcdir)/m4/progtest.m4 \ $(top_srcdir)/acinclude.m4 $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/include/config.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = am__installdirs = "$(DESTDIR)$(bindir)" "$(DESTDIR)$(Desktopdir)" PROGRAMS = $(bin_PROGRAMS) am_gmerlin_recorder_OBJECTS = gmerlin_recorder.$(OBJEXT) \ recorder_window.$(OBJEXT) gmerlin_recorder_OBJECTS = $(am_gmerlin_recorder_OBJECTS) gmerlin_recorder_DEPENDENCIES = \ $(top_builddir)/lib/gtk/libgmerlin_gtk.la \ $(top_builddir)/lib/libgmerlin.la DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)/include depcomp = $(SHELL) $(top_srcdir)/depcomp am__depfiles_maybe = depfiles am__mv = mv -f COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) LTCOMPILE = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \ --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) CCLD = $(CC) LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \ --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \ $(LDFLAGS) -o $@ SOURCES = $(gmerlin_recorder_SOURCES) DIST_SOURCES = $(gmerlin_recorder_SOURCES) am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; am__vpath_adj = case $$p in \ $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ *) f=$$p;; \ esac; am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; am__install_max = 40 am__nobase_strip_setup = \ srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` am__nobase_strip = \ for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" am__nobase_list = $(am__nobase_strip_setup); \ for p in $$list; do echo "$$p $$p"; done | \ sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ if (++n[$$2] == $(am__install_max)) \ { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ END { for (dir in files) print dir, files[dir] }' am__base_list = \ sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' DATA = $(Desktop_DATA) HEADERS = $(noinst_HEADERS) ETAGS = etags CTAGS = ctags DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ ALSA_CFLAGS = @ALSA_CFLAGS@ ALSA_LIBS = @ALSA_LIBS@ ALSA_REQUIRED = @ALSA_REQUIRED@ AMTAR = @AMTAR@ AR = @AR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ BG_VERSION = @BG_VERSION@ BG_VERSION_MAJOR = @BG_VERSION_MAJOR@ BG_VERSION_MICRO = @BG_VERSION_MICRO@ BG_VERSION_MINOR = @BG_VERSION_MINOR@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CDDB_CFLAGS = @CDDB_CFLAGS@ CDDB_LIBS = @CDDB_LIBS@ CDIO_CDDA_CFLAGS = @CDIO_CDDA_CFLAGS@ CDIO_CDDA_LIBS = @CDIO_CDDA_LIBS@ CDIO_CFLAGS = @CDIO_CFLAGS@ CDIO_LIBS = @CDIO_LIBS@ CDIO_PARANOIA_CFLAGS = @CDIO_PARANOIA_CFLAGS@ CDIO_PARANOIA_LIBS = @CDIO_PARANOIA_LIBS@ CDIO_REQUIRED = @CDIO_REQUIRED@ CFLAGS = @CFLAGS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CYGPATH_W = @CYGPATH_W@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DOXYGEN = @DOXYGEN@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ ESD_CFLAGS = @ESD_CFLAGS@ ESD_CONFIG = @ESD_CONFIG@ ESD_LIBS = @ESD_LIBS@ ESD_REQUIRED = @ESD_REQUIRED@ EXEEXT = @EXEEXT@ FGREP = @FGREP@ FONTCONFIG_CFLAGS = @FONTCONFIG_CFLAGS@ FONTCONFIG_LIBS = @FONTCONFIG_LIBS@ FREETYPE_CFLAGS = @FREETYPE_CFLAGS@ FREETYPE_LIBS = @FREETYPE_LIBS@ GAVL_CFLAGS = @GAVL_CFLAGS@ GAVL_LIBS = @GAVL_LIBS@ GAVL_REQUIRED = @GAVL_REQUIRED@ GLX_CFLAGS = @GLX_CFLAGS@ GLX_LIBS = @GLX_LIBS@ GL_CFLAGS = @GL_CFLAGS@ GL_LIBS = @GL_LIBS@ GMERLIN_DEP_LIBS = @GMERLIN_DEP_LIBS@ GMERLIN_PLUGIN_LDFLAGS = @GMERLIN_PLUGIN_LDFLAGS@ GMSGFMT = @GMSGFMT@ GMSGFMT_015 = @GMSGFMT_015@ GREP = @GREP@ GTK_CFLAGS = @GTK_CFLAGS@ GTK_LIBS = @GTK_LIBS@ GTK_REQUIRED = @GTK_REQUIRED@ ICONV_LIBS = @ICONV_LIBS@ INCLUDES = -I$(top_srcdir)/include INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ INTLLIBS = @INTLLIBS@ INTL_MACOSX_LIBS = @INTL_MACOSX_LIBS@ JACK_CFLAGS = @JACK_CFLAGS@ JACK_LIBS = @JACK_LIBS@ JACK_REQUIRED = @JACK_REQUIRED@ JPEG_CFLAGS = @JPEG_CFLAGS@ JPEG_LIBS = @JPEG_LIBS@ JPEG_REQUIRED = @JPEG_REQUIRED@ LD = @LD@ LDFLAGS = @LDFLAGS@ LIBCDDB_REQUIRED = @LIBCDDB_REQUIRED@ LIBEXIF_CFLAGS = @LIBEXIF_CFLAGS@ LIBEXIF_LIBS = @LIBEXIF_LIBS@ LIBICONV = @LIBICONV@ LIBINTL = @LIBINTL@ LIBM = @LIBM@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIPO = @LIPO@ LN_S = @LN_S@ LQT_CFLAGS = @LQT_CFLAGS@ LQT_LIBS = @LQT_LIBS@ LQT_REQUIRED = @LQT_REQUIRED@ LTLIBICONV = @LTLIBICONV@ LTLIBINTL = @LTLIBINTL@ LTLIBOBJS = @LTLIBOBJS@ LTVERSION_AGE = @LTVERSION_AGE@ LTVERSION_CURRENT = @LTVERSION_CURRENT@ LTVERSION_REVISION = @LTVERSION_REVISION@ LV_CFLAGS = @LV_CFLAGS@ LV_LIBS = @LV_LIBS@ LV_REQUIRED = @LV_REQUIRED@ MAKEINFO = @MAKEINFO@ MKDIR_P = @MKDIR_P@ MODULE_LIBADD = @MODULE_LIBADD@ MSGFMT = @MSGFMT@ MSGFMT_015 = @MSGFMT_015@ MSGMERGE = @MSGMERGE@ MUSICBRAINZ_CFLAGS = @MUSICBRAINZ_CFLAGS@ MUSICBRAINZ_LIBS = @MUSICBRAINZ_LIBS@ MUSICBRAINZ_REQUIRED = @MUSICBRAINZ_REQUIRED@ NM = @NM@ NMEDIT = @NMEDIT@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OTOOL = @OTOOL@ OTOOL64 = @OTOOL64@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PKG_CONFIG = @PKG_CONFIG@ PNG_CFLAGS = @PNG_CFLAGS@ PNG_LIBS = @PNG_LIBS@ PNG_REQUIRED = @PNG_REQUIRED@ POSUB = @POSUB@ PULSEAUDIO_CFLAGS = @PULSEAUDIO_CFLAGS@ PULSEAUDIO_LIBS = @PULSEAUDIO_LIBS@ PULSEAUDIO_REQUIRED = @PULSEAUDIO_REQUIRED@ RANLIB = @RANLIB@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ SQLITE3_LIBS = @SQLITE3_LIBS@ STRIP = @STRIP@ TEXINFO = @TEXINFO@ TIFF_CFLAGS = @TIFF_CFLAGS@ TIFF_LIBS = @TIFF_LIBS@ TIFF_REQUIRED = @TIFF_REQUIRED@ TOP_SRCDIR = @TOP_SRCDIR@ USE_NLS = @USE_NLS@ V4LCONVERT_CFLAGS = @V4LCONVERT_CFLAGS@ V4LCONVERT_LIBS = @V4LCONVERT_LIBS@ V4LCONVERT_REQUIRED = @V4LCONVERT_REQUIRED@ VERSION = @VERSION@ XDPMS_LIBS = @XDPMS_LIBS@ XFIXES_LIBS = @XFIXES_LIBS@ XGETTEXT = @XGETTEXT@ XGETTEXT_015 = @XGETTEXT_015@ XINERAMA_LIBS = @XINERAMA_LIBS@ XMKMF = @XMKMF@ XML2_CFLAGS = @XML2_CFLAGS@ XML2_LIBS = @XML2_LIBS@ XML2_REQUIRED = @XML2_REQUIRED@ XTEST_LIBS = @XTEST_LIBS@ XV_LIBS = @XV_LIBS@ X_CFLAGS = @X_CFLAGS@ X_LIBS = @X_LIBS@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_CC = @ac_ct_CC@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_vendor = @build_vendor@ builddir = @builddir@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ lt_ECHO = @lt_ECHO@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ plugindir = $(pkglibdir)/plugins AM_CFLAGS = \ @XML2_CFLAGS@ \ @GTK_CFLAGS@ \ -DLOCALE_DIR=\"$(localedir)\" \ -DPLUGIN_DIR=\"$(plugindir)\" \ -DDOC_DIR=\"$(docdir)\" \ -DDATA_DIR=\"$(pkgdatadir)\" Desktopdir = $(datadir)/applications Desktop_DATA = gmerlin-recorder.desktop gmerlin_recorder_SOURCES = gmerlin_recorder.c recorder_window.c gmerlin_recorder_LDADD = \ $(top_builddir)/lib/gtk/libgmerlin_gtk.la \ $(top_builddir)/lib/libgmerlin.la noinst_HEADERS = recorder_window.h EXTRA_DIST = gmerlin-recorder.desktop all: all-am .SUFFIXES: .SUFFIXES: .c .lo .o .obj $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ && { if test -f $@; then exit 0; else break; fi; }; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu apps/recorder/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --gnu apps/recorder/Makefile .PRECIOUS: Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): install-binPROGRAMS: $(bin_PROGRAMS) @$(NORMAL_INSTALL) test -z "$(bindir)" || $(MKDIR_P) "$(DESTDIR)$(bindir)" @list='$(bin_PROGRAMS)'; test -n "$(bindir)" || list=; \ for p in $$list; do echo "$$p $$p"; done | \ sed 's/$(EXEEXT)$$//' | \ while read p p1; do if test -f $$p || test -f $$p1; \ then echo "$$p"; echo "$$p"; else :; fi; \ done | \ sed -e 'p;s,.*/,,;n;h' -e 's|.*|.|' \ -e 'p;x;s,.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/' | \ sed 'N;N;N;s,\n, ,g' | \ $(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1 } \ { d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \ if ($$2 == $$4) files[d] = files[d] " " $$1; \ else { print "f", $$3 "/" $$4, $$1; } } \ END { for (d in files) print "f", d, files[d] }' | \ while read type dir files; do \ if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \ test -z "$$files" || { \ echo " $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files '$(DESTDIR)$(bindir)$$dir'"; \ $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files "$(DESTDIR)$(bindir)$$dir" || exit $$?; \ } \ ; done uninstall-binPROGRAMS: @$(NORMAL_UNINSTALL) @list='$(bin_PROGRAMS)'; test -n "$(bindir)" || list=; \ files=`for p in $$list; do echo "$$p"; done | \ sed -e 'h;s,^.*/,,;s/$(EXEEXT)$$//;$(transform)' \ -e 's/$$/$(EXEEXT)/' `; \ test -n "$$list" || exit 0; \ echo " ( cd '$(DESTDIR)$(bindir)' && rm -f" $$files ")"; \ cd "$(DESTDIR)$(bindir)" && rm -f $$files clean-binPROGRAMS: @list='$(bin_PROGRAMS)'; test -n "$$list" || exit 0; \ echo " rm -f" $$list; \ rm -f $$list || exit $$?; \ test -n "$(EXEEXT)" || exit 0; \ list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ echo " rm -f" $$list; \ rm -f $$list gmerlin_recorder$(EXEEXT): $(gmerlin_recorder_OBJECTS) $(gmerlin_recorder_DEPENDENCIES) @rm -f gmerlin_recorder$(EXEEXT) $(LINK) $(gmerlin_recorder_OBJECTS) $(gmerlin_recorder_LDADD) $(LIBS) mostlyclean-compile: -rm -f *.$(OBJEXT) distclean-compile: -rm -f *.tab.c @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gmerlin_recorder.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/recorder_window.Po@am__quote@ .c.o: @am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(COMPILE) -c $< .c.obj: @am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(COMPILE) -c `$(CYGPATH_W) '$<'` .c.lo: @am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(LTCOMPILE) -c -o $@ $< mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs install-DesktopDATA: $(Desktop_DATA) @$(NORMAL_INSTALL) test -z "$(Desktopdir)" || $(MKDIR_P) "$(DESTDIR)$(Desktopdir)" @list='$(Desktop_DATA)'; test -n "$(Desktopdir)" || list=; \ for p in $$list; do \ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ echo "$$d$$p"; \ done | $(am__base_list) | \ while read files; do \ echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(Desktopdir)'"; \ $(INSTALL_DATA) $$files "$(DESTDIR)$(Desktopdir)" || exit $$?; \ done uninstall-DesktopDATA: @$(NORMAL_UNINSTALL) @list='$(Desktop_DATA)'; test -n "$(Desktopdir)" || list=; \ files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ test -n "$$files" || exit 0; \ echo " ( cd '$(DESTDIR)$(Desktopdir)' && rm -f" $$files ")"; \ cd "$(DESTDIR)$(Desktopdir)" && rm -f $$files ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | \ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in files) print i; }; }'`; \ mkid -fID $$unique tags: TAGS TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ $(TAGS_FILES) $(LISP) set x; \ here=`pwd`; \ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | \ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in files) print i; }; }'`; \ shift; \ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ test -n "$$unique" || unique=$$empty_fix; \ if test $$# -gt 0; then \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ "$$@" $$unique; \ else \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ $$unique; \ fi; \ fi ctags: CTAGS CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ $(TAGS_FILES) $(LISP) list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | \ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in files) print i; }; }'`; \ test -z "$(CTAGS_ARGS)$$unique" \ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ $$unique GTAGS: here=`$(am__cd) $(top_builddir) && pwd` \ && $(am__cd) $(top_srcdir) \ && gtags -i $(GTAGS_ARGS) "$$here" distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags distdir: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done check-am: all-am check: check-am all-am: Makefile $(PROGRAMS) $(DATA) $(HEADERS) installdirs: for dir in "$(DESTDIR)$(bindir)" "$(DESTDIR)$(Desktopdir)"; do \ test -z "$$dir" || $(MKDIR_P) "$$dir"; \ done install: install-am install-exec: install-exec-am install-data: install-data-am uninstall: uninstall-am install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-am install-strip: $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ `test -z '$(STRIP)' || \ echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install mostlyclean-generic: clean-generic: distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." clean: clean-am clean-am: clean-binPROGRAMS clean-generic clean-libtool mostlyclean-am distclean: distclean-am -rm -rf ./$(DEPDIR) -rm -f Makefile distclean-am: clean-am distclean-compile distclean-generic \ distclean-tags dvi: dvi-am dvi-am: html: html-am html-am: info: info-am info-am: install-data-am: install-DesktopDATA install-dvi: install-dvi-am install-dvi-am: install-exec-am: install-binPROGRAMS install-html: install-html-am install-html-am: install-info: install-info-am install-info-am: install-man: install-pdf: install-pdf-am install-pdf-am: install-ps: install-ps-am install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-am -rm -rf ./$(DEPDIR) -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-compile mostlyclean-generic \ mostlyclean-libtool pdf: pdf-am pdf-am: ps: ps-am ps-am: uninstall-am: uninstall-DesktopDATA uninstall-binPROGRAMS .MAKE: install-am install-strip .PHONY: CTAGS GTAGS all all-am check check-am clean clean-binPROGRAMS \ clean-generic clean-libtool ctags distclean distclean-compile \ distclean-generic distclean-libtool distclean-tags distdir dvi \ dvi-am html html-am info info-am install install-DesktopDATA \ install-am install-binPROGRAMS install-data install-data-am \ install-dvi install-dvi-am install-exec install-exec-am \ install-html install-html-am install-info install-info-am \ install-man install-pdf install-pdf-am install-ps \ install-ps-am install-strip installcheck installcheck-am \ installdirs maintainer-clean maintainer-clean-generic \ mostlyclean mostlyclean-compile mostlyclean-generic \ mostlyclean-libtool pdf pdf-am ps ps-am tags uninstall \ uninstall-DesktopDATA uninstall-am uninstall-binPROGRAMS # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: gmerlin-1.2.0~dfsg/apps/recorder/recorder_window.c0000644000175000017500000006635511764363402022226 0ustar alessioalessio/***************************************************************** * gmerlin - a general purpose multimedia framework and applications * * Copyright (c) 2001 - 2011 Members of the Gmerlin project * gmerlin-general@lists.sourceforge.net * http://gmerlin.sourceforge.net * * 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 of the License, 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 this program. If not, see . * *****************************************************************/ #include #include #include #include #include #include #include #include #include #include #include #include #include #include "recorder_window.h" #define DELAY_TIME 100 #define PING_INTERVAL 10 /* This is missing in the gtk headers */ extern void gtk_decorated_window_move_resize_window(GtkWindow*, int, int, int, int); typedef struct { GtkWidget * win; GtkWidget * box; GtkWidget * socket; } window_t; struct bg_recorder_window_s { bg_recorder_t * rec; bg_gtk_vumeter_t * vumeter; GtkWidget * statusbar; GtkWidget * toolbar; window_t normal_window; window_t fullscreen_window; window_t * current_window; guint framerate_context; int framerate_shown; guint noinput_context; int noinput_shown; guint record_id; GtkWidget * about_button; GtkWidget * log_button; GtkWidget * config_button; GtkWidget * restart_button; GtkWidget * record_button; GtkWidget * snapshot_button; GtkWidget * fullscreen_button; GtkWidget * nofullscreen_button; GtkWidget * hide_button; bg_dialog_t * cfg_dialog; bg_gtk_log_window_t * logwindow; bg_cfg_section_t * general_section; bg_cfg_section_t * audio_filter_section; bg_cfg_section_t * video_filter_section; bg_cfg_section_t * video_monitor_section; bg_cfg_section_t * video_snapshot_section; bg_cfg_section_t * audio_section; bg_cfg_section_t * video_section; bg_cfg_section_t * encoder_section; bg_cfg_section_t * output_section; bg_cfg_section_t * metadata_section; bg_cfg_section_t * log_section; bg_cfg_section_t * gui_section; bg_msg_queue_t * msg_queue; bg_gtk_time_display_t * display; bg_plugin_registry_t * plugin_reg; gavl_rectangle_i_t win_rect; int toolbar_hidden; int timeout_counter; }; static const bg_parameter_info_t gui_parameters[] = { { .name = "x", .type = BG_PARAMETER_INT, .flags = BG_PARAMETER_HIDE_DIALOG, }, { .name = "y", .type = BG_PARAMETER_INT, .flags = BG_PARAMETER_HIDE_DIALOG, }, { .name = "width", .type = BG_PARAMETER_INT, .flags = BG_PARAMETER_HIDE_DIALOG, }, { .name = "height", .type = BG_PARAMETER_INT, .flags = BG_PARAMETER_HIDE_DIALOG, }, { /* End */ } }; static void set_parameter(void * data, const char * name, const bg_parameter_value_t * val) { bg_recorder_window_t * win = data; if(!name) return; else if(!strcmp(name, "x")) { win->win_rect.x = val->val_i; } else if(!strcmp(name, "y")) { win->win_rect.y = val->val_i; } else if(!strcmp(name, "width")) { win->win_rect.w = val->val_i; } else if(!strcmp(name, "height")) { win->win_rect.h = val->val_i; } } static int get_parameter(void * data, const char * name, bg_parameter_value_t * val) { bg_recorder_window_t * win = data; if(!name) return 1; else if(!strcmp(name, "x")) { val->val_i = win->win_rect.x; return 1; } else if(!strcmp(name, "y")) { val->val_i = win->win_rect.y; return 1; } else if(!strcmp(name, "width")) { val->val_i = win->win_rect.w; return 1; } else if(!strcmp(name, "height")) { val->val_i = win->win_rect.h; return 1; } return 0; } static void about_window_close_callback(bg_gtk_about_window_t * w, void * data) { bg_recorder_window_t * win; win = (bg_recorder_window_t *)data; gtk_widget_set_sensitive(win->about_button, 1); } static void log_window_close_callback(bg_gtk_log_window_t * w, void * data) { bg_recorder_window_t * win; win = (bg_recorder_window_t *)data; gtk_widget_set_sensitive(win->log_button, 1); } static void set_fullscreen(bg_recorder_window_t * v) { /* Reparent toolbar */ gtk_container_remove(GTK_CONTAINER(v->normal_window.box), v->toolbar); gtk_box_pack_start(GTK_BOX(v->fullscreen_window.box), v->toolbar, FALSE, FALSE, 0); /* Remember coordinates */ gdk_window_get_geometry(v->normal_window.win->window, NULL, NULL, &v->win_rect.w, &v->win_rect.h, NULL); gdk_window_get_root_origin(v->normal_window.win->window, &v->win_rect.x, &v->win_rect.y); bg_cfg_section_get(v->gui_section, gui_parameters, get_parameter, v); /* Hide normal window, show fullscreen window */ gtk_widget_show(v->fullscreen_window.win); gtk_widget_hide(v->normal_window.win); gtk_window_fullscreen(GTK_WINDOW(v->fullscreen_window.win)); /* Update toolbar */ gtk_widget_show(v->nofullscreen_button); gtk_widget_hide(v->fullscreen_button); gtk_widget_hide(v->config_button); gtk_widget_hide(v->log_button); gtk_widget_hide(v->about_button); v->current_window = &v->fullscreen_window; } static void set_nofullscreen(bg_recorder_window_t * v) { /* Reparent toolbar */ gtk_container_remove(GTK_CONTAINER(v->fullscreen_window.box), v->toolbar); gtk_box_pack_start(GTK_BOX(v->normal_window.box), v->toolbar, FALSE, FALSE, 0); /* Hide normal window, show fullscreen window */ gtk_widget_show(v->normal_window.win); gtk_widget_hide(v->fullscreen_window.win); gtk_decorated_window_move_resize_window(GTK_WINDOW(v->normal_window.win), v->win_rect.x, v->win_rect.y, v->win_rect.w, v->win_rect.h); /* Update toolbar */ gtk_widget_show(v->fullscreen_button); gtk_widget_hide(v->nofullscreen_button); gtk_widget_show(v->config_button); gtk_widget_show(v->config_button); gtk_widget_show(v->log_button); gtk_widget_show(v->about_button); v->current_window = &v->normal_window; } static void button_callback(GtkWidget * w, gpointer data) { bg_recorder_window_t * win; win = (bg_recorder_window_t *)data; if(w == win->log_button) { gtk_widget_set_sensitive(win->log_button, 0); bg_gtk_log_window_show(win->logwindow); } else if(w == win->config_button) { bg_dialog_show(win->cfg_dialog, win->current_window->win); } else if(w == win->restart_button) { bg_recorder_stop(win->rec); bg_recorder_run(win->rec); } else if(w == win->record_button) { int do_record = !!gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(win->record_button)); gtk_widget_set_sensitive(win->restart_button, !do_record); gtk_widget_set_sensitive(win->config_button, !do_record); bg_recorder_record(win->rec, do_record); } else if(w == win->snapshot_button) bg_recorder_snapshot(win->rec); else if(w == win->hide_button) { gtk_widget_hide(win->toolbar); win->toolbar_hidden = 1; } else if(w == win->about_button) { gtk_widget_set_sensitive(win->about_button, 0); bg_gtk_about_window_create("Gmerlin recorder", VERSION, "recorder_icon.png", about_window_close_callback, win); } else if(w == win->fullscreen_button) set_fullscreen(win); else if(w == win->nofullscreen_button) set_nofullscreen(win); } static void delete_callback(GtkWidget * w, GdkEvent * evt, gpointer data) { bg_recorder_window_t * win = (bg_recorder_window_t *)data; #if 1 if(win->current_window == &win->normal_window) /* Remember coordinates */ { gdk_window_get_geometry(win->normal_window.win->window, NULL, NULL, &win->win_rect.w, &win->win_rect.h, NULL); gdk_window_get_root_origin(win->normal_window.win->window, &win->win_rect.x, &win->win_rect.y); bg_cfg_section_get(win->gui_section, gui_parameters, get_parameter, win); } #endif // gtk_widget_hide(win->win); gtk_main_quit(); } static GtkWidget * create_pixmap_button(bg_recorder_window_t * w, const char * filename, const char * tooltip) { GtkWidget * button; GtkWidget * image; char * path; path = bg_search_file_read("icons", filename); if(path) { image = gtk_image_new_from_file(path); free(path); } else image = gtk_image_new(); gtk_widget_show(image); button = gtk_button_new(); gtk_container_add(GTK_CONTAINER(button), image); g_signal_connect(G_OBJECT(button), "clicked", G_CALLBACK(button_callback), w); gtk_widget_show(button); bg_gtk_tooltips_set_tip(button, tooltip, PACKAGE); return button; } static GtkWidget * create_pixmap_toggle_button(bg_recorder_window_t * w, const char * filename, const char * tooltip, guint * callback_id) { GtkWidget * button; GtkWidget * image; char * path; guint id; path = bg_search_file_read("icons", filename); if(path) { image = gtk_image_new_from_file(path); free(path); } else image = gtk_image_new(); gtk_widget_show(image); button = gtk_toggle_button_new(); gtk_container_add(GTK_CONTAINER(button), image); id= g_signal_connect(G_OBJECT(button), "toggled", G_CALLBACK(button_callback), w); if(callback_id) *callback_id = id; gtk_widget_show(button); bg_gtk_tooltips_set_tip(button, tooltip, PACKAGE); return button; } static gboolean timeout_func(void * data) { bg_msg_t * msg; bg_recorder_window_t * win = data; while((msg = bg_msg_queue_try_lock_read(win->msg_queue))) { switch(bg_msg_get_id(msg)) { case BG_RECORDER_MSG_FRAMERATE: { char * tmp_string; float framerate; framerate = bg_msg_get_arg_float(msg, 0); tmp_string = bg_sprintf(TR("Framerate: %.2f fps"), framerate); if(win->framerate_shown) gtk_statusbar_pop(GTK_STATUSBAR(win->statusbar), win->framerate_context); else win->framerate_shown = 1; gtk_statusbar_push(GTK_STATUSBAR(win->statusbar), win->framerate_context, tmp_string); free(tmp_string); } break; case BG_RECORDER_MSG_AUDIOLEVEL: { double l[2]; int samples; l[0] = bg_msg_get_arg_float(msg, 0); l[1] = bg_msg_get_arg_float(msg, 1); samples = bg_msg_get_arg_int(msg, 2); bg_gtk_vumeter_update_peak(win->vumeter, l, samples); } break; case BG_RECORDER_MSG_TIME: { gavl_time_t t = bg_msg_get_arg_time(msg, 0); bg_gtk_time_display_update(win->display, t, BG_GTK_DISPLAY_MODE_HMS); } break; case BG_RECORDER_MSG_RUNNING: { int do_audio, do_video; do_audio = bg_msg_get_arg_int(msg, 0); if(do_audio) gtk_widget_show(bg_gtk_vumeter_get_widget(win->vumeter)); else gtk_widget_hide(bg_gtk_vumeter_get_widget(win->vumeter)); do_video = bg_msg_get_arg_int(msg, 1); if(do_video) { gtk_widget_show(win->current_window->socket); gtk_widget_set_sensitive(win->snapshot_button, 1); gtk_widget_show(win->hide_button); } else { gtk_widget_hide(win->current_window->socket); gtk_widget_hide(win->hide_button); gtk_widget_set_sensitive(win->snapshot_button, 0); } if(!do_audio && !do_video) { gtk_statusbar_push(GTK_STATUSBAR(win->statusbar), win->noinput_context, TR("Error, check messages and settings")); win->noinput_shown = 1; g_signal_handler_block(G_OBJECT(win->record_button), win->record_id); gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(win->record_button), 0); g_signal_handler_unblock(G_OBJECT(win->record_button), win->record_id); gtk_widget_set_sensitive(win->config_button, 1); gtk_widget_set_sensitive(win->restart_button, 1); gtk_widget_set_sensitive(win->snapshot_button, 1); } else if(win->noinput_shown) { gtk_statusbar_pop(GTK_STATUSBAR(win->statusbar), win->noinput_context); } } case BG_RECORDER_MSG_BUTTON_PRESS: if(win->toolbar_hidden) { gtk_widget_show(win->toolbar); win->toolbar_hidden = 0; } break; case BG_RECORDER_MSG_BUTTON_RELEASE: break; case BG_RECORDER_MSG_MOTION: break; } bg_msg_queue_unlock_read(win->msg_queue); } if(!win->timeout_counter) { bg_recorder_ping(win->rec); } win->timeout_counter++; if(win->timeout_counter >= PING_INTERVAL) win->timeout_counter = 0; return TRUE; } static float display_fg[] = { 0.0, 1.0, 0.0 }; static float display_bg[] = { 0.0, 0.0, 0.0 }; static void window_init(bg_recorder_window_t * r, window_t * w, int fullscreen) { /* Window */ w->win = bg_gtk_window_new(GTK_WINDOW_TOPLEVEL); gtk_window_set_title(GTK_WINDOW(w->win), "Gmerlin-recorder-"VERSION); if(fullscreen) gtk_window_fullscreen(GTK_WINDOW(w->win)); /* Socket */ w->socket = gtk_socket_new(); gtk_widget_show(w->socket); w->box = gtk_vbox_new(0, 0); gtk_box_pack_start(GTK_BOX(w->box), w->socket, TRUE, TRUE, 0); gtk_widget_show(w->box); gtk_container_add(GTK_CONTAINER(w->win), w->box); g_signal_connect(G_OBJECT(w->win), "delete_event", G_CALLBACK(delete_callback), r); gtk_widget_realize(w->socket); } bg_recorder_window_t * bg_recorder_window_create(bg_cfg_registry_t * cfg_reg, bg_plugin_registry_t * plugin_reg) { void * parent; GdkDisplay * dpy; char * tmp_string; GtkWidget * box; GtkWidget * mainbox; bg_recorder_window_t * ret; ret = calloc(1, sizeof(*ret)); /* Create recorder */ ret->plugin_reg = plugin_reg; ret->rec = bg_recorder_create(plugin_reg); ret->msg_queue = bg_msg_queue_create(); bg_recorder_add_message_queue(ret->rec, ret->msg_queue); /* Create widgets */ ret->display = bg_gtk_time_display_create(BG_GTK_DISPLAY_SIZE_SMALL, 4, BG_GTK_DISPLAY_MODE_HMS); bg_gtk_time_display_update(ret->display, GAVL_TIME_UNDEFINED, BG_GTK_DISPLAY_MODE_HMS); bg_gtk_time_display_set_colors(ret->display, display_fg, display_bg ); ret->vumeter = bg_gtk_vumeter_create(2, 0); ret->about_button = create_pixmap_button(ret, "info_16.png", TRS("About")); ret->log_button = create_pixmap_button(ret, "log_16.png", TRS("Log messages")); ret->config_button = create_pixmap_button(ret, "config_16.png", TRS("Preferences")); ret->restart_button = create_pixmap_button(ret, "refresh_16.png", TRS("Reopen inputs")); ret->record_button = create_pixmap_toggle_button(ret, "record_16.png", TRS("Record"), &ret->record_id); ret->snapshot_button = create_pixmap_button(ret, "snapshot_16.png", TRS("Make snapshot")); ret->fullscreen_button = create_pixmap_button(ret, "fullscreen_16.png", TRS("Fullscreen mode")); ret->nofullscreen_button = create_pixmap_button(ret, "windowed_16.png", TRS("Leave fullscreen mode")); ret->hide_button = create_pixmap_button(ret, "close_16.png", TRS("Hide controls")); ret->statusbar = gtk_statusbar_new(); ret->framerate_context = gtk_statusbar_get_context_id(GTK_STATUSBAR(ret->statusbar), "framerate"); ret->noinput_context = gtk_statusbar_get_context_id(GTK_STATUSBAR(ret->statusbar), "noinput"); gtk_widget_show(ret->statusbar); /* Create other windows */ ret->logwindow = bg_gtk_log_window_create(log_window_close_callback, ret, "Recorder"); /* Pack everything */ mainbox = gtk_vbox_new(0, 0); ret->toolbar = gtk_vbox_new(0, 0); /* Display and buttons */ gtk_box_pack_start(GTK_BOX(ret->toolbar), bg_gtk_vumeter_get_widget(ret->vumeter), FALSE, FALSE, 0); box = gtk_hbox_new(0, 0); gtk_box_pack_start(GTK_BOX(box), ret->hide_button, FALSE, FALSE, 0); gtk_box_pack_start(GTK_BOX(box), ret->config_button, FALSE, FALSE, 0); gtk_box_pack_start(GTK_BOX(box), ret->about_button, FALSE, FALSE, 0); gtk_box_pack_start(GTK_BOX(box), ret->log_button, FALSE, FALSE, 0); gtk_box_pack_start(GTK_BOX(box), ret->restart_button, FALSE, FALSE, 0); gtk_box_pack_start(GTK_BOX(box), ret->record_button, FALSE, FALSE, 0); gtk_box_pack_start(GTK_BOX(box), ret->snapshot_button, FALSE, FALSE, 0); gtk_box_pack_start(GTK_BOX(box), ret->fullscreen_button, FALSE, FALSE, 0); gtk_box_pack_start(GTK_BOX(box), ret->nofullscreen_button, FALSE, FALSE, 0); gtk_box_pack_end(GTK_BOX(box), bg_gtk_time_display_get_widget(ret->display), FALSE, FALSE, 0); gtk_widget_show(box); gtk_box_pack_start(GTK_BOX(ret->toolbar), box, FALSE, FALSE, 0); /* Statusbar */ gtk_box_pack_start(GTK_BOX(ret->toolbar), ret->statusbar, FALSE, FALSE, 0); g_object_ref(ret->toolbar); gtk_widget_show(ret->toolbar); /* Config stuff */ ret->log_section = bg_cfg_registry_find_section(cfg_reg, "log"); ret->gui_section = bg_cfg_registry_find_section(cfg_reg, "gui"); ret->audio_section = bg_cfg_registry_find_section(cfg_reg, "audio"); ret->video_section = bg_cfg_registry_find_section(cfg_reg, "video"); ret->audio_filter_section = bg_cfg_registry_find_section(cfg_reg, "audiofilter"); ret->video_filter_section = bg_cfg_registry_find_section(cfg_reg, "videofilter"); ret->video_monitor_section = bg_cfg_registry_find_section(cfg_reg, "video_monitor"); ret->video_snapshot_section = bg_cfg_registry_find_section(cfg_reg, "video_snapshot"); ret->output_section = bg_cfg_registry_find_section(cfg_reg, "output"); ret->metadata_section = bg_cfg_registry_find_section(cfg_reg, "metadata"); /* Encoders */ ret->encoder_section = bg_encoder_section_get_from_registry(plugin_reg, bg_recorder_get_encoder_parameters(ret->rec), bg_recorder_stream_mask, bg_recorder_plugin_mask); bg_recorder_set_encoder_section(ret->rec, ret->encoder_section); ret->cfg_dialog = bg_dialog_create_multi(TR("Recorder configuration")); bg_dialog_set_plugin_registry(ret->cfg_dialog, plugin_reg); /* Audio */ parent = bg_dialog_add_parent(ret->cfg_dialog, NULL, TRS("Audio")); bg_dialog_add_child(ret->cfg_dialog, parent, TRS("General"), ret->audio_section, bg_recorder_set_audio_parameter, NULL, ret->rec, bg_recorder_get_audio_parameters(ret->rec)); bg_dialog_add_child(ret->cfg_dialog, parent, TRS("Filters"), ret->audio_filter_section, bg_recorder_set_audio_filter_parameter, NULL, ret->rec, bg_recorder_get_audio_filter_parameters(ret->rec)); /* Video */ parent = bg_dialog_add_parent(ret->cfg_dialog, NULL, TRS("Video")); bg_dialog_add_child(ret->cfg_dialog, parent, TRS("General"), ret->video_section, bg_recorder_set_video_parameter, NULL, ret->rec, bg_recorder_get_video_parameters(ret->rec)); bg_dialog_add_child(ret->cfg_dialog, parent, TRS("Filters"), ret->video_filter_section, bg_recorder_set_video_filter_parameter, NULL, ret->rec, bg_recorder_get_video_filter_parameters(ret->rec)); bg_dialog_add_child(ret->cfg_dialog, parent, TRS("Monitor"), ret->video_monitor_section, bg_recorder_set_video_monitor_parameter, NULL, ret->rec, bg_recorder_get_video_monitor_parameters(ret->rec)); bg_dialog_add_child(ret->cfg_dialog, parent, TRS("Snapshots"), ret->video_snapshot_section, bg_recorder_set_video_snapshot_parameter, NULL, ret->rec, bg_recorder_get_video_snapshot_parameters(ret->rec)); /* Other stuff */ bg_dialog_add(ret->cfg_dialog, TR("Encoders"), ret->encoder_section, NULL, NULL, NULL, bg_recorder_get_encoder_parameters(ret->rec)); /* Output */ bg_dialog_add(ret->cfg_dialog, TR("Output files"), ret->output_section, NULL, NULL, NULL, bg_recorder_get_output_parameters(ret->rec)); bg_dialog_add(ret->cfg_dialog, TR("Metadata"), ret->metadata_section, bg_recorder_set_metadata_parameter, NULL, ret->rec, bg_recorder_get_metadata_parameters(ret->rec)); bg_dialog_add(ret->cfg_dialog, TR("Log window"), ret->log_section, bg_gtk_log_window_set_parameter, NULL, (void*)(ret->logwindow), bg_gtk_log_window_get_parameters(ret->logwindow)); /* Apply config sections */ bg_cfg_section_apply(ret->log_section, bg_gtk_log_window_get_parameters(ret->logwindow), bg_gtk_log_window_set_parameter, ret->logwindow); bg_cfg_section_apply(ret->gui_section, gui_parameters, set_parameter, ret); bg_cfg_section_apply(ret->output_section, bg_recorder_get_output_parameters(ret->rec), bg_recorder_set_output_parameter, ret->rec); bg_cfg_section_apply(ret->metadata_section, bg_recorder_get_metadata_parameters(ret->rec), bg_recorder_set_metadata_parameter, ret->rec); /* Initialize windows */ dpy = gdk_display_get_default(); window_init(ret, &ret->normal_window, 0); window_init(ret, &ret->fullscreen_window, 1); tmp_string = bg_sprintf("%s:%08lx:%08lx", gdk_display_get_name(dpy), (long unsigned int)gtk_socket_get_id(GTK_SOCKET(ret->normal_window.socket)), (long unsigned int)gtk_socket_get_id(GTK_SOCKET(ret->fullscreen_window.socket))); bg_recorder_set_display_string(ret->rec, tmp_string); free(tmp_string); /* Now that we have the display string we can apply the config sections, which will load the plugins */ bg_cfg_section_apply(ret->audio_section, bg_recorder_get_audio_parameters(ret->rec), bg_recorder_set_audio_parameter, ret->rec); bg_cfg_section_apply(ret->audio_filter_section, bg_recorder_get_audio_filter_parameters(ret->rec), bg_recorder_set_audio_filter_parameter, ret->rec); bg_cfg_section_apply(ret->video_section, bg_recorder_get_video_parameters(ret->rec), bg_recorder_set_video_parameter, ret->rec); bg_cfg_section_apply(ret->video_filter_section, bg_recorder_get_video_filter_parameters(ret->rec), bg_recorder_set_video_filter_parameter, ret->rec); bg_cfg_section_apply(ret->video_monitor_section, bg_recorder_get_video_monitor_parameters(ret->rec), bg_recorder_set_video_monitor_parameter, ret->rec); bg_cfg_section_apply(ret->video_snapshot_section, bg_recorder_get_video_snapshot_parameters(ret->rec), bg_recorder_set_video_snapshot_parameter, ret->rec); /* Intialize windowed mode */ ret->current_window = &ret->normal_window; gtk_box_pack_start(GTK_BOX(ret->current_window->box), ret->toolbar, FALSE, FALSE, 0); gtk_widget_hide(ret->nofullscreen_button); /* Timeout */ g_timeout_add(DELAY_TIME, timeout_func, ret); return ret; } void bg_recorder_window_destroy(bg_recorder_window_t * win) { bg_encoder_section_store_in_registry(win->plugin_reg, win->encoder_section, bg_recorder_get_encoder_parameters(win->rec), bg_recorder_stream_mask, bg_recorder_plugin_mask); bg_recorder_destroy(win->rec); bg_cfg_section_destroy(win->encoder_section); free(win); } void bg_recorder_window_run(bg_recorder_window_t * win) { gtk_widget_show(win->current_window->win); if((win->win_rect.w > 0) && (win->win_rect.h > 0)) { gtk_decorated_window_move_resize_window(GTK_WINDOW(win->current_window->win), win->win_rect.x, win->win_rect.y, win->win_rect.w, win->win_rect.h); } else { gtk_window_set_default_size(GTK_WINDOW(win->current_window->win), 320, 300); } bg_recorder_run(win->rec); gtk_main(); } gmerlin-1.2.0~dfsg/apps/recorder/gmerlin_recorder.c0000644000175000017500000000456711764363402022351 0ustar alessioalessio/***************************************************************** * gmerlin - a general purpose multimedia framework and applications * * Copyright (c) 2001 - 2011 Members of the Gmerlin project * gmerlin-general@lists.sourceforge.net * http://gmerlin.sourceforge.net * * 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 of the License, 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 this program. If not, see . * *****************************************************************/ #include #include "recorder_window.h" #include #include #include #define WINDOW_ICON "recorder_icon.png" #define WINDOW_NAME "gmerlin-recorder" #define WINDOW_CLASS "gmerlin-recorder" int main(int argc, char ** argv) { bg_cfg_registry_t * cfg_reg; bg_plugin_registry_t * plugin_reg; char * tmp_path; bg_cfg_section_t * section; bg_recorder_window_t * win; /* We must initialize the random number generator if we want the Vorbis encoder to work */ srand(time(NULL)); /* Create config registry */ cfg_reg = bg_cfg_registry_create(); tmp_path = bg_search_file_read("recorder", "config.xml"); bg_cfg_registry_load(cfg_reg, tmp_path); if(tmp_path) free(tmp_path); /* Create plugin registry */ section = bg_cfg_registry_find_section(cfg_reg, "plugins"); plugin_reg = bg_plugin_registry_create(section); /* Initialize gtk */ bg_gtk_init(&argc, &argv, WINDOW_ICON, WINDOW_NAME, WINDOW_CLASS); win = bg_recorder_window_create(cfg_reg, plugin_reg); bg_recorder_window_run(win); bg_recorder_window_destroy(win); /* Save config */ tmp_path = bg_search_file_write("recorder", "config.xml"); if(tmp_path) { bg_cfg_registry_save(cfg_reg, tmp_path); free(tmp_path); } bg_plugin_registry_destroy(plugin_reg); bg_cfg_registry_destroy(cfg_reg); return 0; } gmerlin-1.2.0~dfsg/apps/transcoder/0000755000175000017500000000000011764363443017213 5ustar alessioalessiogmerlin-1.2.0~dfsg/apps/transcoder/Makefile.am0000644000175000017500000000164511764363402021250 0ustar alessioalessioplugindir=$(pkglibdir)/plugins INCLUDES = -I$(top_srcdir)/include AM_CFLAGS = \ @XML2_CFLAGS@ \ @GTK_CFLAGS@ \ -DLOCALE_DIR=\"$(localedir)\" \ -DPLUGIN_DIR=\"$(plugindir)\" \ -DDOC_DIR=\"$(docdir)\" \ -DDATA_DIR=\"$(pkgdatadir)\" Desktopdir = $(datadir)/applications Desktop_DATA = gmerlin-transcoder.desktop bin_PROGRAMS = gmerlin_transcoder gmerlin_transcoder_remote dist_man_MANS = gmerlin_transcoder.1 gmerlin_transcoder_remote.1 gmerlin_transcoder_SOURCES = \ ppwidget.c \ main.c \ transcoder_window.c \ trackdialog.c \ tracklist.c gmerlin_transcoder_remote_SOURCES = gmerlin_transcoder_remote.c gmerlin_transcoder_LDADD = \ $(top_builddir)/lib/gtk/libgmerlin_gtk.la \ $(top_builddir)/lib/libgmerlin.la gmerlin_transcoder_remote_LDADD = \ $(top_builddir)/lib/libgmerlin.la noinst_HEADERS = \ ppwidget.h \ transcoder_remote.h \ transcoder_window.h \ tracklist.h \ trackdialog.h EXTRA_DIST = gmerlin-transcoder.desktop gmerlin-1.2.0~dfsg/apps/transcoder/main.c0000644000175000017500000000527711764363402020311 0ustar alessioalessio/***************************************************************** * gmerlin - a general purpose multimedia framework and applications * * Copyright (c) 2001 - 2011 Members of the Gmerlin project * gmerlin-general@lists.sourceforge.net * http://gmerlin.sourceforge.net * * 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 of the License, 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 this program. If not, see . * *****************************************************************/ #include #include #include #include #include #include #include #include "transcoder_window.h" #include "transcoder_remote.h" static void opt_p(void * data, int * argc, char *** argv, int arg) { FILE * out = stderr; transcoder_window_t * win; win = (transcoder_window_t*)data; if(arg >= *argc) { fprintf(out, "Option -p requires an argument\n"); exit(-1); } transcoder_window_load_profile(win, (*argv)[arg]); bg_cmdline_remove_arg(argc, argv, arg); } bg_cmdline_arg_t args[] = { { .arg = "-p", .help_arg = "", .help_string = "Load a profile from the given file", .callback = opt_p, }, { /* End of args */ } }; const bg_cmdline_app_data_t app_data = { .package = PACKAGE, .version = VERSION, .name = "gmerlin_transcoder", .synopsis = TRS("[options]\n"), .help_before = TRS("GTK multimedia transcoder\n"), .args = (bg_cmdline_arg_array_t[]) { { TRS("Options"), args }, { } }, .env = (bg_cmdline_ext_doc_t[]) { { TRANSCODER_REMOTE_ENV, TRS("Default port for the remote control") }, { /* End */ } }, }; int main(int argc, char ** argv) { transcoder_window_t * win; bg_gtk_init(&argc, &argv, "transcoder_icon.png", NULL, NULL); /* We must initialize the random number generator if we want the Vorbis encoder to work */ srand(time(NULL)); win = transcoder_window_create(); bg_cmdline_init(&app_data); bg_cmdline_parse(args, &argc, &argv, win); transcoder_window_run(win); transcoder_window_destroy(win); return 0; } gmerlin-1.2.0~dfsg/apps/transcoder/transcoder_remote.h0000644000175000017500000000247511764363402023106 0ustar alessioalessio/***************************************************************** * gmerlin - a general purpose multimedia framework and applications * * Copyright (c) 2001 - 2011 Members of the Gmerlin project * gmerlin-general@lists.sourceforge.net * http://gmerlin.sourceforge.net * * 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 of the License, 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 this program. If not, see . * *****************************************************************/ #define TRANSCODER_REMOTE_PORT (BG_REMOTE_PORT_BASE+2) #define TRANSCODER_REMOTE_ID "gmerlin_transcoder" #define TRANSCODER_REMOTE_ENV "GMERLIN_TRANSCODER_REMOTE_PORT" /* Remote commands */ /* Add file (arg1) */ #define TRANSCODER_REMOTE_ADD_FILE 1 /* Add album (arg1 points to an xml encoded file) */ #define TRANSCODER_REMOTE_ADD_ALBUM 2 gmerlin-1.2.0~dfsg/apps/transcoder/trackdialog.h0000644000175000017500000000263411764363402021650 0ustar alessioalessio/***************************************************************** * gmerlin - a general purpose multimedia framework and applications * * Copyright (c) 2001 - 2011 Members of the Gmerlin project * gmerlin-general@lists.sourceforge.net * http://gmerlin.sourceforge.net * * 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 of the License, 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 this program. If not, see . * *****************************************************************/ typedef struct track_dialog_s track_dialog_t; track_dialog_t * track_dialog_create(bg_transcoder_track_t * t, void (*update_callback)(void * priv), void * update_priv, int show_tooltips, bg_plugin_registry_t * plugin_reg); void track_dialog_run(track_dialog_t *, GtkWidget * parent); void track_dialog_destroy(track_dialog_t *); gmerlin-1.2.0~dfsg/apps/transcoder/gmerlin_transcoder.10000644000175000017500000000131511764363402023151 0ustar alessioalessio.TH GMERLIN_TRANSCODER 1 "March 2012" Gmerlin "User Manuals" .SH NAME gmerlin_transcoder .SH SYNOPSIS .B gmerlin_transcoder .I [options] .SH DESCRIPTION GTK multimedia transcoder .SH OPTIONS .B -p .I .RS 2 Load a profile from the given file .RE .SH GENERIC OPTIONS The following generic options are available for all gmerlin applications .B -help .RS 2 Print this help message and exit .RE .B -help-man .RS 2 Print this help message as a manual page and exit .RE .B -help-texi .RS 2 Print this help message in texinfo format and exit .RE .B -version .RS 2 Print version info and exit .RE .SH ENVIRONMENT VARIABLES .B GMERLIN_TRANSCODER_REMOTE_PORT .RS 2 Default port for the remote control .RE gmerlin-1.2.0~dfsg/apps/transcoder/tracklist.c0000644000175000017500000015570511764363402021367 0ustar alessioalessio/***************************************************************** * gmerlin - a general purpose multimedia framework and applications * * Copyright (c) 2001 - 2011 Members of the Gmerlin project * gmerlin-general@lists.sourceforge.net * http://gmerlin.sourceforge.net * * 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 of the License, 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 this program. If not, see . * *****************************************************************/ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "tracklist.h" #include "trackdialog.h" #include "ppwidget.h" static void track_list_update(track_list_t * w); static GdkPixbuf * has_audio_pixbuf = NULL; static GdkPixbuf * has_video_pixbuf = NULL; #define cp_tracks_name "gmerlin_transcoder_tracks" /* 0 means unset */ #define DND_GMERLIN_TRACKS 1 #define DND_GMERLIN_TRACKS_R 2 #define DND_TEXT_URI_LIST 3 #define DND_TEXT_PLAIN 4 #define DND_TRANSCODER_TRACKS 5 static GtkTargetEntry dnd_dst_entries[] = { {bg_gtk_atom_entries_name, 0, DND_GMERLIN_TRACKS }, {bg_gtk_atom_entries_name_r, 0, DND_GMERLIN_TRACKS_R }, {"text/uri-list", 0, DND_TEXT_URI_LIST }, {"text/plain", 0, DND_TEXT_PLAIN }, }; static GtkTargetEntry copy_paste_entries[] = { { cp_tracks_name , 0, DND_TRANSCODER_TRACKS }, }; static int is_urilist(GtkSelectionData * data) { int ret; char * target_name; target_name = gdk_atom_name(data->target); if(!target_name) return 0; if(!strcmp(target_name, "text/uri-list") || !strcmp(target_name, "text/plain")) ret = 1; else ret = 0; g_free(target_name); return ret; } #if 0 static int is_tracks(GtkSelectionData * data) { int ret; char * target_name; target_name = gdk_atom_name(data->target); if(!target_name) return 0; if(!strcmp(target_name, cp_tracks_name)) ret = 1; else ret = 0; g_free(target_name); return ret; } #endif static int is_albumentries(GtkSelectionData * data) { int ret; char * target_name; target_name = gdk_atom_name(data->target); if(!target_name) return 0; if(!strcmp(target_name, bg_gtk_atom_entries_name) || !strcmp(target_name, bg_gtk_atom_entries_name_r)) ret = 1; else ret = 0; g_free(target_name); return ret; } static void load_pixmaps() { char * filename; if(has_audio_pixbuf) return; filename = bg_search_file_read("icons", "audio_16.png"); if(filename) { has_audio_pixbuf = gdk_pixbuf_new_from_file(filename, NULL); free(filename); } filename = bg_search_file_read("icons", "video_16.png"); if(filename) { has_video_pixbuf = gdk_pixbuf_new_from_file(filename, NULL); free(filename); } } typedef struct { GtkWidget * add_files_item; GtkWidget * add_urls_item; GtkWidget * add_drives_item; GtkWidget * menu; } add_menu_t; typedef struct { GtkWidget * move_up_item; GtkWidget * move_down_item; GtkWidget * remove_item; GtkWidget * configure_item; GtkWidget * encoder_item; GtkWidget * chapter_item; GtkWidget * mass_tag_item; GtkWidget * auto_number_item; GtkWidget * auto_rename_item; GtkWidget * menu; } selected_menu_t; typedef struct { GtkWidget * cut_item; GtkWidget * copy_item; GtkWidget * paste_item; GtkWidget * menu; } edit_menu_t; typedef struct { GtkWidget * add_item; add_menu_t add_menu; GtkWidget * selected_item; selected_menu_t selected_menu; GtkWidget * edit_item; edit_menu_t edit_menu; GtkWidget * pp_item; GtkWidget * menu; } menu_t; enum { COLUMN_INDEX, COLUMN_NAME, COLUMN_AUDIO, COLUMN_VIDEO, COLUMN_DURATION, NUM_COLUMNS }; struct track_list_s { GtkWidget * treeview; GtkWidget * widget; /* Buttons */ GtkWidget * add_file_button; GtkWidget * add_url_button; GtkWidget * add_removable_button; GtkWidget * delete_button; GtkWidget * config_button; GtkWidget * encoder_button; GtkWidget * chapter_button; GtkWidget * cut_button; GtkWidget * copy_button; GtkWidget * paste_button; bg_transcoder_track_t * tracks; bg_transcoder_track_global_t track_global; bg_plugin_registry_t * plugin_reg; GtkTreeViewColumn * col_name; bg_transcoder_track_t * selected_track; int num_selected; gulong select_handler_id; bg_cfg_section_t * track_defaults_section; bg_cfg_section_t * encoder_section; const bg_parameter_info_t * encoder_parameters; bg_gtk_time_display_t * time_total; int show_tooltips; menu_t menu; encoder_pp_window_t * encoder_pp_window; char * open_path; char * rename_mask; bg_gtk_filesel_t * filesel; char * clipboard; GtkAccelGroup * accel_group; }; /* Called when the selecection changed */ static void select_row_callback(GtkTreeSelection * sel, gpointer data) { GtkTreeIter iter; GtkTreeModel * model; GtkTreeSelection * selection; bg_transcoder_track_t * track; track_list_t * w = (track_list_t *)data; model = gtk_tree_view_get_model(GTK_TREE_VIEW(w->treeview)); selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(w->treeview)); w->num_selected = 0; track = w->tracks; if(!gtk_tree_model_get_iter_first(model, &iter) || !track) { gtk_widget_set_sensitive(w->config_button, 0); gtk_widget_set_sensitive(w->encoder_button, 0); w->selected_track = NULL; // gtk_widget_set_sensitive(w->up_button, 0); // gtk_widget_set_sensitive(w->down_button, 0); gtk_widget_set_sensitive(w->delete_button, 0); gtk_widget_set_sensitive(w->cut_button, 0); gtk_widget_set_sensitive(w->copy_button, 0); gtk_widget_set_sensitive(w->menu.selected_menu.move_up_item, 0); gtk_widget_set_sensitive(w->menu.selected_menu.move_down_item, 0); gtk_widget_set_sensitive(w->menu.selected_menu.configure_item, 0); gtk_widget_set_sensitive(w->menu.selected_menu.remove_item, 0); gtk_widget_set_sensitive(w->menu.selected_menu.encoder_item, 0); gtk_widget_set_sensitive(w->menu.edit_menu.cut_item, 0); gtk_widget_set_sensitive(w->menu.edit_menu.copy_item, 0); return; } while(1) { if(gtk_tree_selection_iter_is_selected(selection, &iter)) { track->selected = 1; w->selected_track = track; w->num_selected++; } else track->selected = 0; if(!gtk_tree_model_iter_next(model, &iter)) break; track = track->next; if(!track) break; } if(w->num_selected == 1) { gtk_widget_set_sensitive(w->config_button, 1); gtk_widget_set_sensitive(w->encoder_button, 1); // gtk_widget_set_sensitive(w->up_button, 1); // gtk_widget_set_sensitive(w->down_button, 1); gtk_widget_set_sensitive(w->delete_button, 1); gtk_widget_set_sensitive(w->chapter_button, 1); gtk_widget_set_sensitive(w->cut_button, 1); gtk_widget_set_sensitive(w->copy_button, 1); gtk_widget_set_sensitive(w->menu.selected_menu.move_up_item, 1); gtk_widget_set_sensitive(w->menu.selected_menu.move_down_item, 1); gtk_widget_set_sensitive(w->menu.selected_menu.configure_item, 1); gtk_widget_set_sensitive(w->menu.selected_menu.remove_item, 1); gtk_widget_set_sensitive(w->menu.selected_menu.encoder_item, 1); gtk_widget_set_sensitive(w->menu.selected_menu.chapter_item, 1); gtk_widget_set_sensitive(w->menu.selected_menu.mass_tag_item, 1); gtk_widget_set_sensitive(w->menu.selected_menu.auto_number_item, 1); gtk_widget_set_sensitive(w->menu.selected_menu.auto_rename_item, 1); gtk_widget_set_sensitive(w->menu.edit_menu.cut_item, 1); gtk_widget_set_sensitive(w->menu.edit_menu.copy_item, 1); } else if(w->num_selected == 0) { gtk_widget_set_sensitive(w->config_button, 0); gtk_widget_set_sensitive(w->encoder_button, 0); w->selected_track = NULL; // gtk_widget_set_sensitive(w->up_button, 0); // gtk_widget_set_sensitive(w->down_button, 0); gtk_widget_set_sensitive(w->delete_button, 0); gtk_widget_set_sensitive(w->chapter_button, 0); gtk_widget_set_sensitive(w->cut_button, 0); gtk_widget_set_sensitive(w->copy_button, 0); gtk_widget_set_sensitive(w->menu.selected_menu.move_up_item, 0); gtk_widget_set_sensitive(w->menu.selected_menu.move_down_item, 0); gtk_widget_set_sensitive(w->menu.selected_menu.configure_item, 0); gtk_widget_set_sensitive(w->menu.selected_menu.remove_item, 0); gtk_widget_set_sensitive(w->menu.selected_menu.encoder_item, 0); gtk_widget_set_sensitive(w->menu.selected_menu.chapter_item, 0); gtk_widget_set_sensitive(w->menu.selected_menu.mass_tag_item, 0); gtk_widget_set_sensitive(w->menu.selected_menu.auto_number_item, 0); gtk_widget_set_sensitive(w->menu.selected_menu.auto_rename_item, 0); gtk_widget_set_sensitive(w->menu.edit_menu.cut_item, 0); gtk_widget_set_sensitive(w->menu.edit_menu.copy_item, 0); } else { gtk_widget_set_sensitive(w->config_button, 0); w->selected_track = NULL; gtk_widget_set_sensitive(w->encoder_button, 1); // gtk_widget_set_sensitive(w->up_button, 1); // gtk_widget_set_sensitive(w->down_button, 1); gtk_widget_set_sensitive(w->delete_button, 1); gtk_widget_set_sensitive(w->chapter_button, 0); gtk_widget_set_sensitive(w->cut_button, 1); gtk_widget_set_sensitive(w->copy_button, 1); gtk_widget_set_sensitive(w->menu.selected_menu.move_up_item, 1); gtk_widget_set_sensitive(w->menu.selected_menu.move_down_item, 1); gtk_widget_set_sensitive(w->menu.selected_menu.configure_item, 0); gtk_widget_set_sensitive(w->menu.selected_menu.remove_item, 1); gtk_widget_set_sensitive(w->menu.selected_menu.encoder_item, 1); gtk_widget_set_sensitive(w->menu.selected_menu.chapter_item, 0); gtk_widget_set_sensitive(w->menu.selected_menu.mass_tag_item, 1); gtk_widget_set_sensitive(w->menu.selected_menu.auto_number_item, 1); gtk_widget_set_sensitive(w->menu.selected_menu.auto_rename_item, 1); gtk_widget_set_sensitive(w->menu.edit_menu.cut_item, 1); gtk_widget_set_sensitive(w->menu.edit_menu.copy_item, 1); } } /* Update the entire list */ static void track_list_update(track_list_t * w) { int i; GtkTreeModel * model; GtkTreeIter iter; bg_transcoder_track_t * track; gavl_time_t track_duration; gavl_time_t track_duration_total; gavl_time_t duration_total; char * name; char string_buffer[GAVL_TIME_STRING_LEN + 32]; char string_buffer1[GAVL_TIME_STRING_LEN + 32]; char * buf; GtkTreeSelection * selection; selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(w->treeview)); model = gtk_tree_view_get_model(GTK_TREE_VIEW(w->treeview)); g_signal_handler_block(G_OBJECT(selection), w->select_handler_id); gtk_list_store_clear(GTK_LIST_STORE(model)); track = w->tracks; i = 0; duration_total = 0; while(track) { gtk_list_store_append(GTK_LIST_STORE(model), &iter); name = bg_transcoder_track_get_name(track); /* Set index */ sprintf(string_buffer, "%d.", i+1); gtk_list_store_set(GTK_LIST_STORE(model), &iter, COLUMN_INDEX, string_buffer, -1); /* Set name */ gtk_list_store_set(GTK_LIST_STORE(model), &iter, COLUMN_NAME, name, -1); /* Audio */ if(track->num_audio_streams) gtk_list_store_set(GTK_LIST_STORE(model), &iter, COLUMN_AUDIO, has_audio_pixbuf, -1); else gtk_list_store_set(GTK_LIST_STORE(model), &iter, COLUMN_AUDIO, NULL, -1); /* Video */ if(track->num_video_streams) gtk_list_store_set(GTK_LIST_STORE(model), &iter, COLUMN_VIDEO, has_video_pixbuf, -1); else gtk_list_store_set(GTK_LIST_STORE(model), &iter, COLUMN_VIDEO, NULL, -1); /* Set time */ bg_transcoder_track_get_duration(track, &track_duration, &track_duration_total); if(duration_total != GAVL_TIME_UNDEFINED) { if(track_duration == GAVL_TIME_UNDEFINED) duration_total = GAVL_TIME_UNDEFINED; else duration_total += track_duration; } if(track_duration == track_duration_total) { gavl_time_prettyprint(track_duration, string_buffer); gtk_list_store_set(GTK_LIST_STORE(model), &iter, COLUMN_DURATION, string_buffer, -1); } else { gavl_time_prettyprint(track_duration, string_buffer); gavl_time_prettyprint(track_duration_total, string_buffer1); buf = bg_sprintf("%s/%s", string_buffer, string_buffer1); gtk_list_store_set(GTK_LIST_STORE(model), &iter, COLUMN_DURATION, buf, -1); free(buf); } /* Select track */ if(track->selected) { gtk_tree_selection_select_iter(selection, &iter); } free(name); i++; track = track->next; } g_signal_handler_unblock(G_OBJECT(selection), w->select_handler_id); bg_gtk_time_display_update(w->time_total, duration_total, BG_GTK_DISPLAY_MODE_HMS); /* Flush events */ // while(gdk_events_pending() || gtk_events_pending()) // gtk_main_iteration(); select_row_callback(NULL, w); } /* Append a track to the list */ static void add_track(track_list_t * l, bg_transcoder_track_t * new_track) { bg_transcoder_track_t * track; if(!l->tracks) { l->tracks = new_track; return; } track = l->tracks; while(track->next) { track = track->next; } track->next = new_track; } static void delete_selected(track_list_t * l) { l->tracks = bg_transcoder_tracks_delete_selected(l->tracks); track_list_update(l); } /* Callback functions for the clipboard */ static void clipboard_get_func(GtkClipboard *clipboard, GtkSelectionData *selection_data, guint info, gpointer data) { GdkAtom type_atom; track_list_t * w = (track_list_t*)data; type_atom = gdk_atom_intern("STRING", FALSE); if(!type_atom) return; gtk_selection_data_set(selection_data, type_atom, 8, (uint8_t*)w->clipboard, strlen(w->clipboard)+1); } static void clipboard_clear_func(GtkClipboard *clipboard, gpointer data) { track_list_t * w = (track_list_t*)data; if(w->clipboard) { free(w->clipboard); w->clipboard = NULL; } } static void clipboard_received_func_tracks(GtkClipboard *clipboard, GtkSelectionData *selection_data, gpointer data) { bg_transcoder_track_t * new_tracks; track_list_t * w = (track_list_t*)data; if(selection_data->length <= 0) return; new_tracks = bg_transcoder_tracks_from_xml((char*)selection_data->data, w->plugin_reg); w->tracks = bg_transcoder_tracks_append(w->tracks, new_tracks); track_list_update(w); } static void clipboard_received_func_albumentries(GtkClipboard *clipboard, GtkSelectionData *selection_data, gpointer data) { track_list_t * w = (track_list_t*)data; if(selection_data->length <= 0) return; track_list_add_albumentries_xml(w, (char*)(selection_data->data)); } static void do_copy(track_list_t * w) { GtkClipboard *clipboard; GdkAtom clipboard_atom; // clipboard_atom = gdk_atom_intern ("PRIMARY", FALSE); clipboard_atom = gdk_atom_intern ("CLIPBOARD", FALSE); clipboard = gtk_clipboard_get(clipboard_atom); gtk_clipboard_set_with_data(clipboard, copy_paste_entries, sizeof(copy_paste_entries)/ sizeof(copy_paste_entries[0]), clipboard_get_func, clipboard_clear_func, (gpointer)w); if(w->clipboard) free(w->clipboard); w->clipboard = bg_transcoder_tracks_selected_to_xml(w->tracks); } static void do_cut(track_list_t * l) { do_copy(l); delete_selected(l); } static void target_received_func(GtkClipboard *clipboard, GdkAtom *atoms, gint n_atoms, gpointer data) { track_list_t * l; int i = 0; char * atom_name; l = (track_list_t *)(data); for(i = 0; i < n_atoms; i++) { atom_name = gdk_atom_name(atoms[i]); if(!atom_name) return; else if(!strcmp(atom_name, cp_tracks_name)) { gtk_clipboard_request_contents(clipboard, atoms[i], clipboard_received_func_tracks, l); g_free(atom_name); return; } else if(!strcmp(atom_name, bg_gtk_atom_entries_name) || !strcmp(atom_name, bg_gtk_atom_entries_name_r)) { fprintf(stderr, "Paste albumentries\n"); gtk_clipboard_request_contents(clipboard, atoms[i], clipboard_received_func_albumentries, l); return; } } } static void do_paste(track_list_t * l) { GtkClipboard *clipboard; GdkAtom clipboard_atom; GdkAtom target; // clipboard_atom = gdk_atom_intern ("PRIMARY", FALSE); clipboard_atom = gdk_atom_intern ("CLIPBOARD", FALSE); clipboard = gtk_clipboard_get(clipboard_atom); target = gdk_atom_intern(cp_tracks_name, FALSE); gtk_clipboard_request_targets(clipboard, target_received_func, l); } static void move_up(track_list_t * l) { l->tracks = bg_transcoder_tracks_move_selected_up(l->tracks); track_list_update(l); } static void move_down(track_list_t * l) { l->tracks = bg_transcoder_tracks_move_selected_down(l->tracks); track_list_update(l); } static void add_file_callback(char ** files, const char * plugin, int prefer_edl, void * data) { const bg_plugin_info_t * plugin_info; bg_transcoder_track_t * new_track; track_list_t * l; int i = 0; l = (track_list_t *)(data); if(plugin) plugin_info = bg_plugin_find_by_name(l->plugin_reg, plugin); else plugin_info = NULL; while(files[i]) { new_track = bg_transcoder_track_create(files[i], plugin_info, prefer_edl, -1, l->plugin_reg, l->track_defaults_section, l->encoder_section, NULL); add_track(l, new_track); track_list_update(l); i++; } /* Remember open path */ if(l->filesel) l->open_path = bg_strdup(l->open_path, bg_gtk_filesel_get_directory(l->filesel)); } static void filesel_close_callback(bg_gtk_filesel_t * f , void * data) { track_list_t * t; t = (track_list_t*)data; gtk_widget_set_sensitive(t->add_file_button, 1); t->filesel = NULL; } static void urlsel_close_callback(bg_gtk_urlsel_t * f , void * data) { track_list_t * t; t = (track_list_t*)data; gtk_widget_set_sensitive(t->add_url_button, 1); gtk_widget_set_sensitive(t->menu.add_menu.add_urls_item, 1); } static void drivesel_close_callback(bg_gtk_drivesel_t * f , void * data) { track_list_t * t; t = (track_list_t*)data; gtk_widget_set_sensitive(t->add_removable_button, 1); } /* Set track name */ static void update_track(void * data) { track_list_t * l = (track_list_t *)data; track_list_update(l); } typedef struct { int changed; } encoder_parameter_data; static void set_encoder_parameter(void * data, const char * name, const bg_parameter_value_t * val) { encoder_parameter_data * d = data; d->changed = 1; } static void configure_encoders(track_list_t * l) { bg_cfg_section_t * s; bg_dialog_t * dlg; bg_transcoder_track_t * first_selected; encoder_parameter_data d; d.changed = 0; first_selected = l->tracks; while(first_selected && !first_selected->selected) first_selected = first_selected->next; if(!first_selected) return; s = bg_cfg_section_create("Encoders"); /* All settings, which are not in the track, are taken from the current encoder settings */ bg_cfg_section_transfer(l->encoder_section, s); bg_transcoder_track_get_encoders(first_selected, l->plugin_reg, s); dlg = bg_dialog_create(s, set_encoder_parameter, NULL, &d, l->encoder_parameters, TR("Encoder configuration")); bg_dialog_show(dlg, l->widget); if(d.changed) { while(first_selected) { if(first_selected->selected) { bg_transcoder_track_set_encoders(first_selected, l->plugin_reg, s); } first_selected = first_selected->next; } } bg_dialog_destroy(dlg); bg_cfg_section_destroy(s); } static void mass_tag(track_list_t * l) { bg_dialog_t * dlg; bg_transcoder_track_t * first_selected; bg_parameter_info_t * params; bg_cfg_section_t * s; encoder_parameter_data d; int i; bg_parameter_value_t val; d.changed = 0; first_selected = l->tracks; while(first_selected && !first_selected->selected) first_selected = first_selected->next; if(!first_selected) return; params = bg_metadata_get_parameters_common(NULL); s = bg_cfg_section_create_from_parameters("Mass tag", params); /* Copy parameters from the first selected track. Also set the help string. */ i = 0; while(params[i].name) { memset(&val, 0, sizeof(val)); bg_cfg_section_get_parameter(first_selected->metadata_section, ¶ms[i], &val); bg_cfg_section_set_parameter(s, ¶ms[i], &val); bg_parameter_value_free(&val, params[i].type); params[i].help_string = bg_strdup(params[i].help_string, TRS("Use \"-\" to clear this field for all tracks. Empty string means to leave it unchanged for all tracks")); i++; } /* Create and show dialog */ dlg = bg_dialog_create(s, set_encoder_parameter, NULL, &d, params, TR("Mass tag")); bg_dialog_show(dlg, l->widget); /* Apply values */ if(d.changed) { while(first_selected) { if(first_selected->selected) { i = 0; while(params[i].name) { memset(&val, 0, sizeof(val)); bg_cfg_section_get_parameter(s, ¶ms[i], &val); if(params[i].type == BG_PARAMETER_STRING) { if(val.val_str && !strcmp(val.val_str, "-")) { bg_parameter_value_t val1; val1.val_str = NULL; bg_cfg_section_set_parameter(first_selected->metadata_section, ¶ms[i], &val1); } else if(val.val_str && (val.val_str[0] != '\0')) bg_cfg_section_set_parameter(first_selected->metadata_section, ¶ms[i], &val); } bg_parameter_value_free(&val, params[i].type); i++; } } first_selected = first_selected->next; } } bg_dialog_destroy(dlg); bg_cfg_section_destroy(s); bg_parameter_info_destroy_array(params); } static const bg_parameter_info_t auto_rename_parameters[] = { { .name = "rename_mask", .long_name = TRS("Format for track names"), .type = BG_PARAMETER_STRING, .help_string = TRS("Format specifier for tracknames from\n\ metadata\n\ %p: Artist\n\ %a: Album\n\ %g: Genre\n\ %t: Track name\n\ %n: Track number with digits\n\ %y: Year\n\ %c: Comment"), }, { /* End */ }, }; typedef struct { char * rename_mask; } auto_rename_parameter_data; static void set_auto_rename_parameter(void * data, const char * name, const bg_parameter_value_t * val) { auto_rename_parameter_data * d = data; if(!name) return; if(!strcmp(name, "rename_mask")) d->rename_mask = bg_strdup(d->rename_mask, val->val_str); } static void auto_rename(track_list_t * l) { bg_parameter_info_t * metadata_params; bg_parameter_info_t * auto_rename_params; auto_rename_parameter_data d; bg_dialog_t * dlg; metadata_params = bg_metadata_get_parameters(NULL); auto_rename_params = bg_parameter_info_copy_array(auto_rename_parameters); auto_rename_params[0].val_default.val_str = bg_strdup(NULL, l->rename_mask); memset(&d, 0, sizeof(d)); /* Create dialog */ dlg = bg_dialog_create(NULL, set_auto_rename_parameter, NULL, &d, auto_rename_params, TR("Auto rename")); bg_dialog_show(dlg, l->widget); bg_dialog_destroy(dlg); if(d.rename_mask) { bg_transcoder_track_t * t = l->tracks; while(t) { if(t->selected) { char * new_name; gavl_metadata_t m; gavl_metadata_init(&m); bg_cfg_section_apply(t->metadata_section, metadata_params, bg_metadata_set_parameter, &m); new_name = bg_create_track_name(&m, d.rename_mask); bg_cfg_section_set_parameter_string(t->general_section, "name", new_name); free(new_name); gavl_metadata_free(&m); } t = t->next; } /* Save for later use */ l->rename_mask = bg_strdup(l->rename_mask, d.rename_mask); free(d.rename_mask); track_list_update(l); } bg_parameter_info_destroy_array(metadata_params); bg_parameter_info_destroy_array(auto_rename_params); } static void auto_number(track_list_t * l) { bg_transcoder_track_t * t; int num = 1; t = l->tracks; while(t) { if(t->selected) { bg_cfg_section_set_parameter_int(t->metadata_section, "track", num); num++; } t = t->next; } } static void button_callback(GtkWidget * w, gpointer data) { track_list_t * t; bg_gtk_urlsel_t * urlsel; bg_gtk_drivesel_t * drivesel; track_dialog_t * track_dialog; gavl_time_t track_duration; gavl_time_t track_duration_total; t = (track_list_t*)data; if((w == t->add_file_button) || (w == t->menu.add_menu.add_files_item)) { t->filesel = bg_gtk_filesel_create("Add URLs", add_file_callback, filesel_close_callback, t, NULL /* parent */, t->plugin_reg, BG_PLUGIN_INPUT, BG_PLUGIN_FILE); bg_gtk_filesel_set_directory(t->filesel, t->open_path); gtk_widget_set_sensitive(t->add_file_button, 0); bg_gtk_filesel_run(t->filesel, 0); // bg_gtk_filesel_destroy(filesel); } else if((w == t->add_url_button) || (w == t->menu.add_menu.add_urls_item)) { urlsel = bg_gtk_urlsel_create(TR("Add files"), add_file_callback, urlsel_close_callback, t, NULL /* parent */, t->plugin_reg, BG_PLUGIN_INPUT, BG_PLUGIN_URL); gtk_widget_set_sensitive(t->add_url_button, 0); gtk_widget_set_sensitive(t->menu.add_menu.add_urls_item, 0); bg_gtk_urlsel_run(urlsel, 0, t->add_url_button); // bg_gtk_urlsel_destroy(urlsel); } else if((w == t->add_removable_button) || (w == t->menu.add_menu.add_drives_item)) { drivesel = bg_gtk_drivesel_create("Add drive", add_file_callback, drivesel_close_callback, t, NULL /* parent */, t->plugin_reg, BG_PLUGIN_INPUT, BG_PLUGIN_REMOVABLE); gtk_widget_set_sensitive(t->add_removable_button, 0); bg_gtk_drivesel_run(drivesel, 0, t->add_removable_button); } else if((w == t->delete_button) || (w == t->menu.selected_menu.remove_item)) { delete_selected(t); } else if(w == t->menu.selected_menu.move_up_item) { move_up(t); } else if(w == t->menu.selected_menu.move_down_item) { move_down(t); } else if((w == t->config_button) || (w == t->menu.selected_menu.configure_item)) { track_dialog = track_dialog_create(t->selected_track, update_track, t, t->show_tooltips, t->plugin_reg); track_dialog_run(track_dialog, t->treeview); track_dialog_destroy(track_dialog); } else if((w == t->menu.edit_menu.cut_item) || (w == t->cut_button)) { do_cut(t); } else if((w == t->menu.edit_menu.copy_item) || (w == t->copy_button)) { do_copy(t); } else if((w == t->menu.edit_menu.paste_item) || (w == t->paste_button)) { do_paste(t); } else if((w == t->chapter_button) || (w == t->menu.selected_menu.chapter_item)) { bg_transcoder_track_get_duration(t->selected_track, &track_duration, &track_duration_total); bg_gtk_chapter_dialog_show(&t->selected_track->chapter_list, track_duration, t->treeview); } else if(w == t->menu.selected_menu.mass_tag_item) { mass_tag(t); } else if(w == t->menu.selected_menu.auto_number_item) { auto_number(t); } else if(w == t->menu.selected_menu.auto_rename_item) { auto_rename(t); } else if((w == t->encoder_button) || (w == t->menu.selected_menu.encoder_item)) { configure_encoders(t); } else if(w == t->menu.pp_item) { encoder_pp_window_run(t->encoder_pp_window, &t->track_global); } } /* Menu stuff */ static GtkWidget * create_item(track_list_t * w, GtkWidget * parent, const char * label, const char * pixmap) { GtkWidget * ret, *image; char * path; if(pixmap) { path = bg_search_file_read("icons", pixmap); if(path) { image = gtk_image_new_from_file(path); free(path); } else image = gtk_image_new(); gtk_widget_show(image); ret = gtk_image_menu_item_new_with_label(label); gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(ret), image); } else { ret = gtk_menu_item_new_with_label(label); } g_signal_connect(G_OBJECT(ret), "activate", G_CALLBACK(button_callback), (gpointer)w); gtk_widget_show(ret); gtk_menu_shell_append(GTK_MENU_SHELL(parent), ret); return ret; } static void init_menu(track_list_t * t) { /* Add */ t->menu.add_menu.menu = gtk_menu_new(); t->menu.add_menu.add_files_item = create_item(t, t->menu.add_menu.menu, TR("Files..."), "folder_open_16.png"); t->menu.add_menu.add_urls_item = create_item(t, t->menu.add_menu.menu, TR("Urls..."), "earth_16.png"); t->menu.add_menu.add_drives_item = create_item(t, t->menu.add_menu.menu, TR("Drives..."), "drive_running_16.png"); gtk_widget_show(t->menu.add_menu.menu); /* Selected */ t->menu.selected_menu.menu = gtk_menu_new(); t->menu.selected_menu.move_up_item = create_item(t, t->menu.selected_menu.menu, TR("Move Up"), "top_16.png"); t->menu.selected_menu.move_down_item = create_item(t, t->menu.selected_menu.menu, TR("Move Down"), "bottom_16.png"); t->menu.selected_menu.remove_item = create_item(t, t->menu.selected_menu.menu, TR("Remove"), "trash_16.png"); t->menu.selected_menu.configure_item = create_item(t, t->menu.selected_menu.menu, TR("Configure..."), "config_16.png"); t->menu.selected_menu.chapter_item = create_item(t, t->menu.selected_menu.menu, TR("Edit chapters..."), "chapter_16.png"); t->menu.selected_menu.mass_tag_item = create_item(t, t->menu.selected_menu.menu, TR("Mass tag..."), NULL); t->menu.selected_menu.auto_number_item = create_item(t, t->menu.selected_menu.menu, TR("Auto numbering"), NULL); t->menu.selected_menu.auto_rename_item = create_item(t, t->menu.selected_menu.menu, TR("Auto rename..."), NULL); t->menu.selected_menu.encoder_item = create_item(t, t->menu.selected_menu.menu, TR("Change encoders..."), "plugin_16.png"); /* Edit */ t->menu.edit_menu.menu = gtk_menu_new(); t->menu.edit_menu.cut_item = create_item(t, t->menu.edit_menu.menu, TR("Cut"), "cut_16.png"); gtk_widget_add_accelerator(t->menu.edit_menu.cut_item, "activate", t->accel_group, GDK_x, GDK_CONTROL_MASK, GTK_ACCEL_VISIBLE); t->menu.edit_menu.copy_item = create_item(t, t->menu.edit_menu.menu, TR("Copy"), "copy_16.png"); gtk_widget_add_accelerator(t->menu.edit_menu.copy_item, "activate", t->accel_group, GDK_c, GDK_CONTROL_MASK, GTK_ACCEL_VISIBLE); t->menu.edit_menu.paste_item = create_item(t, t->menu.edit_menu.menu, TR("Paste"), "paste_16.png"); gtk_widget_add_accelerator(t->menu.edit_menu.paste_item, "activate", t->accel_group, GDK_v, GDK_CONTROL_MASK, GTK_ACCEL_VISIBLE); gtk_widget_show(t->menu.add_menu.menu); /* Root menu */ t->menu.menu = gtk_menu_new(); t->menu.add_item = create_item(t, t->menu.menu, TR("Add..."), NULL); gtk_menu_item_set_submenu(GTK_MENU_ITEM(t->menu.add_item), t->menu.add_menu.menu); t->menu.selected_item = create_item(t, t->menu.menu, TR("Selected..."), NULL); gtk_menu_item_set_submenu(GTK_MENU_ITEM(t->menu.selected_item), t->menu.selected_menu.menu); t->menu.edit_item = create_item(t, t->menu.menu, TR("Edit..."), NULL); gtk_menu_item_set_submenu(GTK_MENU_ITEM(t->menu.edit_item), t->menu.edit_menu.menu); t->menu.pp_item = create_item(t, t->menu.menu, TR("Postprocess..."), NULL); gtk_widget_set_sensitive(t->menu.selected_menu.move_up_item, 0); gtk_widget_set_sensitive(t->menu.selected_menu.move_down_item, 0); gtk_widget_set_sensitive(t->menu.selected_menu.configure_item, 0); gtk_widget_set_sensitive(t->menu.selected_menu.remove_item, 0); gtk_widget_set_sensitive(t->menu.selected_menu.encoder_item, 0); gtk_widget_set_sensitive(t->menu.selected_menu.chapter_item, 0); gtk_widget_set_sensitive(t->menu.selected_menu.mass_tag_item, 0); gtk_widget_set_sensitive(t->menu.selected_menu.auto_number_item, 0); gtk_widget_set_sensitive(t->menu.selected_menu.auto_rename_item, 0); gtk_widget_set_sensitive(t->menu.edit_menu.cut_item, 0); gtk_widget_set_sensitive(t->menu.edit_menu.copy_item, 0); } GtkWidget * track_list_get_menu(track_list_t * t) { return t->menu.menu; } static gboolean button_press_callback(GtkWidget * w, GdkEventButton * evt, gpointer data) { track_list_t * t = (track_list_t*)data; if(evt->button == 3) { gtk_menu_popup(GTK_MENU(t->menu.menu), NULL, NULL, NULL, NULL, 3, evt->time); return TRUE; } return FALSE; } /* */ static void column_resize_callback(GtkTreeViewColumn * col, gint * width_val, gpointer data) { int width_needed; int name_width; int width; track_list_t * w = (track_list_t *)data; width = col->width; gtk_tree_view_column_cell_get_size(col, NULL, NULL, NULL, &width_needed, NULL); name_width = gtk_tree_view_column_get_fixed_width (w->col_name); if(width > width_needed) { name_width += width - width_needed; gtk_tree_view_column_set_fixed_width (w->col_name, name_width); } else if(width < width_needed) { name_width -= width_needed - width; gtk_tree_view_column_set_fixed_width (w->col_name, name_width); } } void track_list_add_albumentries_xml(track_list_t * l, char * xml_string) { bg_transcoder_track_t * new_tracks; new_tracks = bg_transcoder_track_create_from_albumentries(xml_string, l->plugin_reg, l->track_defaults_section, l->encoder_section); add_track(l, new_tracks); track_list_update(l); } void track_list_add_url(track_list_t * l, char * url) { bg_transcoder_track_t * new_tracks; new_tracks = bg_transcoder_track_create(url, NULL, 0, -1, l->plugin_reg, l->track_defaults_section, l->encoder_section, NULL); add_track(l, new_tracks); track_list_update(l); } #if 0 static gboolean drag_drop_callback(GtkWidget *widget, GdkDragContext *drag_context, gint x, gint y, guint time, gpointer user_data) { GdkAtom target; track_list_t * l = (track_list_t *)user_data; target = gtk_drag_dest_find_target(widget, drag_context, gtk_drag_dest_get_target_list(widget)); // fprintf(stderr, "Drag drop %d (%s)\n", target, gtk_atom_get); if(target != GDK_NONE) gtk_drag_get_data(widget, drag_context, target, time); return TRUE; } #endif static void drag_received_callback(GtkWidget *widget, GdkDragContext *drag_context, gint x, gint y, GtkSelectionData *data, guint info, guint time, gpointer d) { bg_transcoder_track_t * new_tracks; track_list_t * l = (track_list_t *)d; if(is_urilist(data)) { new_tracks = bg_transcoder_track_create_from_urilist((char*)(data->data), data->length, l->plugin_reg, l->track_defaults_section, l->encoder_section); add_track(l, new_tracks); track_list_update(l); } else if(is_albumentries(data)) { track_list_add_albumentries_xml(l, (char*)(data->data)); } gtk_drag_finish(drag_context, TRUE, /* Success */ 0, /* Delete */ time); } /* Buttons */ static GtkWidget * create_pixmap_button(track_list_t * l, const char * filename, const char * tooltip) { GtkWidget * button; GtkWidget * image; char * path; path = bg_search_file_read("icons", filename); if(path) { image = gtk_image_new_from_file(path); free(path); } else image = gtk_image_new(); gtk_widget_show(image); button = gtk_button_new(); gtk_container_add(GTK_CONTAINER(button), image); bg_gtk_tooltips_set_tip(button, tooltip, PACKAGE); g_signal_connect(G_OBJECT(button), "clicked", G_CALLBACK(button_callback), l); gtk_widget_show(button); return button; } track_list_t * track_list_create(bg_plugin_registry_t * plugin_reg, bg_cfg_section_t * track_defaults_section, const bg_parameter_info_t * encoder_parameters, bg_cfg_section_t * encoder_section) { GtkWidget * scrolled; GtkWidget * box; track_list_t * ret; GtkTreeViewColumn * col; GtkListStore *store; GtkCellRenderer *renderer; GtkTreeSelection * selection; char * tmp_path; load_pixmaps(); ret = calloc(1, sizeof(*ret)); ret->track_defaults_section = track_defaults_section; ret->encoder_section = encoder_section; ret->encoder_parameters = encoder_parameters; ret->time_total = bg_gtk_time_display_create(BG_GTK_DISPLAY_SIZE_SMALL, 4, BG_GTK_DISPLAY_MODE_HMS); ret->encoder_pp_window = encoder_pp_window_create(plugin_reg); ret->accel_group = gtk_accel_group_new(); bg_gtk_tooltips_set_tip(bg_gtk_time_display_get_widget(ret->time_total), TRS("Total playback time"), PACKAGE); ret->plugin_reg = plugin_reg; /* Create buttons */ ret->add_file_button = create_pixmap_button(ret, "folder_open_16.png", TRS("Append files to the task list")); ret->add_url_button = create_pixmap_button(ret, "earth_16.png", TRS("Append URLs to the task list")); ret->add_removable_button = create_pixmap_button(ret, "drive_running_16.png", TRS("Append removable media to the task list")); ret->delete_button = create_pixmap_button(ret, "trash_16.png", TRS("Delete selected tracks")); ret->config_button = create_pixmap_button(ret, "config_16.png", TRS("Configure selected track")); ret->chapter_button = create_pixmap_button(ret, "chapter_16.png", TRS("Edit chapters")); ret->encoder_button = create_pixmap_button(ret, "plugin_16.png", TRS("Change encoder plugins for selected tracks")); ret->copy_button = create_pixmap_button(ret, "copy_16.png", TRS("Copy selected tracks to clipboard")); ret->cut_button = create_pixmap_button(ret, "cut_16.png", TRS("Cut selected tracks to clipboard")); ret->paste_button = create_pixmap_button(ret, "paste_16.png", TRS("Paste tracks from clipboard")); gtk_widget_set_sensitive(ret->delete_button, 0); gtk_widget_set_sensitive(ret->encoder_button, 0); gtk_widget_set_sensitive(ret->config_button, 0); gtk_widget_set_sensitive(ret->chapter_button, 0); // gtk_widget_set_sensitive(ret->up_button, 0); // gtk_widget_set_sensitive(ret->down_button, 0); gtk_widget_set_sensitive(ret->cut_button, 0); gtk_widget_set_sensitive(ret->copy_button, 0); /* Create list view */ store = gtk_list_store_new(NUM_COLUMNS, G_TYPE_STRING, // Index G_TYPE_STRING, // Name GDK_TYPE_PIXBUF, // Audio GDK_TYPE_PIXBUF, // Video G_TYPE_STRING); // Duration ret->treeview = gtk_tree_view_new_with_model(GTK_TREE_MODEL(store)); gtk_widget_set_size_request(ret->treeview, 200, 100); selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(ret->treeview)); gtk_tree_selection_set_mode(selection, GTK_SELECTION_MULTIPLE); ret->select_handler_id = g_signal_connect(G_OBJECT(selection), "changed", G_CALLBACK(select_row_callback), (gpointer)ret); gtk_tree_view_set_headers_visible(GTK_TREE_VIEW(ret->treeview), 0); gtk_drag_dest_set(ret->treeview, GTK_DEST_DEFAULT_ALL, /* GTK_DEST_DEFAULT_HIGHLIGHT | GTK_DEST_DEFAULT_DROP | GTK_DEST_DEFAULT_MOTION, */ dnd_dst_entries, sizeof(dnd_dst_entries)/sizeof(dnd_dst_entries[0]), GDK_ACTION_COPY | GDK_ACTION_MOVE); g_signal_connect(G_OBJECT(ret->treeview), "drag-data-received", G_CALLBACK(drag_received_callback), (gpointer)ret); #if 0 g_signal_connect(G_OBJECT(ret->treeview), "drag-drop", G_CALLBACK(drag_drop_callback), (gpointer)ret); #endif g_signal_connect(G_OBJECT(ret->treeview), "button-press-event", G_CALLBACK(button_press_callback), (gpointer)ret); /* Create columns */ /* Index */ renderer = gtk_cell_renderer_text_new(); g_object_set(G_OBJECT(renderer), "xalign", 1.0, NULL); col = gtk_tree_view_column_new (); gtk_tree_view_column_set_title(col, "I"); gtk_tree_view_column_pack_start(col, renderer, FALSE); gtk_tree_view_column_add_attribute(col, renderer, "text", COLUMN_INDEX); gtk_tree_view_column_set_sizing(col, GTK_TREE_VIEW_COLUMN_GROW_ONLY); gtk_tree_view_append_column (GTK_TREE_VIEW(ret->treeview), col); /* Name */ renderer = gtk_cell_renderer_text_new(); g_object_set(G_OBJECT(renderer), "xalign", 0.0, NULL); col = gtk_tree_view_column_new (); ret->col_name = col; gtk_tree_view_column_pack_start(col, renderer, TRUE); gtk_tree_view_column_add_attribute(col, renderer, "text", COLUMN_NAME); gtk_tree_view_column_set_sizing(col, GTK_TREE_VIEW_COLUMN_FIXED); gtk_tree_view_append_column (GTK_TREE_VIEW(ret->treeview), col); /* Audio */ renderer = gtk_cell_renderer_pixbuf_new(); col = gtk_tree_view_column_new (); gtk_tree_view_column_set_title(col, "A"); gtk_tree_view_column_pack_start(col, renderer, FALSE); gtk_tree_view_column_add_attribute(col, renderer, "pixbuf", COLUMN_AUDIO); gtk_tree_view_column_set_sizing(col, GTK_TREE_VIEW_COLUMN_GROW_ONLY); gtk_tree_view_append_column (GTK_TREE_VIEW(ret->treeview), col); /* Video */ renderer = gtk_cell_renderer_pixbuf_new(); col = gtk_tree_view_column_new (); gtk_tree_view_column_set_title(col, "V"); gtk_tree_view_column_pack_start(col, renderer, FALSE); gtk_tree_view_column_add_attribute(col, renderer, "pixbuf", COLUMN_VIDEO); gtk_tree_view_column_set_sizing(col, GTK_TREE_VIEW_COLUMN_GROW_ONLY); gtk_tree_view_append_column (GTK_TREE_VIEW(ret->treeview), col); /* Duration */ renderer = gtk_cell_renderer_text_new(); g_object_set(G_OBJECT(renderer), "xalign", 1.0, NULL); col = gtk_tree_view_column_new (); g_signal_connect(G_OBJECT(col), "notify::width", G_CALLBACK(column_resize_callback), (gpointer)ret); gtk_tree_view_column_set_title(col, "T"); gtk_tree_view_column_pack_start(col, renderer, FALSE); gtk_tree_view_column_add_attribute(col, renderer, "text", COLUMN_DURATION); gtk_tree_view_column_set_sizing(col, GTK_TREE_VIEW_COLUMN_FIXED); gtk_tree_view_append_column (GTK_TREE_VIEW(ret->treeview), col); /* Done with columns */ gtk_widget_show(ret->treeview); /* Pack */ scrolled = gtk_scrolled_window_new(gtk_tree_view_get_hadjustment(GTK_TREE_VIEW(ret->treeview)), gtk_tree_view_get_vadjustment(GTK_TREE_VIEW(ret->treeview))); gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled), GTK_POLICY_NEVER, GTK_POLICY_ALWAYS); gtk_container_add(GTK_CONTAINER(scrolled), ret->treeview); gtk_widget_show(scrolled); ret->widget = gtk_table_new(2, 1, 0); gtk_table_attach_defaults(GTK_TABLE(ret->widget), scrolled, 0, 1, 0, 1); box = gtk_hbox_new(0, 0); gtk_box_pack_start(GTK_BOX(box), ret->add_file_button, FALSE, FALSE, 0); gtk_box_pack_start(GTK_BOX(box), ret->add_url_button, FALSE, FALSE, 0); gtk_box_pack_start(GTK_BOX(box), ret->add_removable_button, FALSE, FALSE, 0); gtk_box_pack_start(GTK_BOX(box), ret->delete_button, FALSE, FALSE, 0); gtk_box_pack_start(GTK_BOX(box), ret->encoder_button, FALSE, FALSE, 0); gtk_box_pack_start(GTK_BOX(box), ret->config_button, FALSE, FALSE, 0); gtk_box_pack_start(GTK_BOX(box), ret->chapter_button, FALSE, FALSE, 0); // gtk_box_pack_start(GTK_BOX(box), ret->up_button, FALSE, FALSE, 0); // gtk_box_pack_start(GTK_BOX(box), ret->down_button, FALSE, FALSE, 0); gtk_box_pack_start(GTK_BOX(box), ret->cut_button, FALSE, FALSE, 0); gtk_box_pack_start(GTK_BOX(box), ret->copy_button, FALSE, FALSE, 0); gtk_box_pack_start(GTK_BOX(box), ret->paste_button, FALSE, FALSE, 0); gtk_box_pack_end(GTK_BOX(box), bg_gtk_time_display_get_widget(ret->time_total), FALSE, FALSE, 0); gtk_widget_show(box); gtk_table_attach(GTK_TABLE(ret->widget), box, 0, 1, 1, 2, GTK_FILL, GTK_FILL, 0, 0); gtk_widget_show(ret->widget); init_menu(ret); /* Load tracks */ tmp_path = bg_search_file_read("transcoder", "tracks.xml"); if(tmp_path) { ret->tracks = bg_transcoder_tracks_load(tmp_path, &ret->track_global, ret->plugin_reg); free(tmp_path); track_list_update(ret); } return ret; } void track_list_destroy(track_list_t * t) { char * tmp_path; bg_transcoder_track_t * tmp_track; bg_transcoder_track_global_free(&t->track_global); tmp_path = bg_search_file_write("transcoder", "tracks.xml"); if(tmp_path) { bg_transcoder_tracks_save(t->tracks, &t->track_global, tmp_path); free(tmp_path); } tmp_track = t->tracks; while(t->tracks) { tmp_track = t->tracks->next; bg_transcoder_track_destroy(t->tracks); t->tracks = tmp_track; } g_object_unref(t->accel_group); if(t->open_path) free(t->open_path); if(t->rename_mask) free(t->rename_mask); if(t->clipboard) free(t->clipboard); bg_gtk_time_display_destroy(t->time_total); free(t); } GtkWidget * track_list_get_widget(track_list_t * t) { return t->widget; } GtkAccelGroup * track_list_get_accel_group(track_list_t * t) { return t->accel_group; } bg_plugin_handle_t * track_list_get_pp_plugin(track_list_t * t) { const bg_plugin_info_t * info; info = encoder_pp_window_get_plugin(t->encoder_pp_window); return bg_plugin_load(t->plugin_reg, info); } bg_transcoder_track_t * track_list_get_track(track_list_t * t) { bg_transcoder_track_t * ret; if(!t->tracks) return NULL; ret = t->tracks; t->tracks = t->tracks->next; track_list_update(t); return ret; } void track_list_prepend_track(track_list_t * t, bg_transcoder_track_t * track) { track->next = t->tracks; t->tracks = track; track_list_update(t); } void track_list_load(track_list_t * t, const char * filename) { bg_transcoder_track_t * end_track; bg_transcoder_track_t * new_tracks; new_tracks = bg_transcoder_tracks_load(filename, &t->track_global, t->plugin_reg); if(!t->tracks) { t->tracks = new_tracks; } else { end_track = t->tracks; while(end_track->next) end_track = end_track->next; end_track->next = new_tracks; } track_list_update(t); } void track_list_save(track_list_t * t, const char * filename) { bg_transcoder_tracks_save(t->tracks, &t->track_global, filename); } void track_list_set_display_colors(track_list_t * t, float * fg, float * bg) { bg_gtk_time_display_set_colors(t->time_total, fg, bg); } bg_parameter_info_t parameters[] = { { .name = "open_path", .long_name = "Open Path", .type = BG_PARAMETER_DIRECTORY, .flags = BG_PARAMETER_HIDE_DIALOG, .val_default = { .val_str = "." }, }, { .name = "rename_mask", .long_name = "rename mask", .type = BG_PARAMETER_STRING, .flags = BG_PARAMETER_HIDE_DIALOG, .val_default = { .val_str = "%p - %t" }, }, { /* End of parameters */ } }; bg_parameter_info_t * track_list_get_parameters(track_list_t * t) { return parameters; } void track_list_set_parameter(void * data, const char * name, const bg_parameter_value_t * val) { track_list_t * t; if(!name) return; t = (track_list_t *)data; if(!strcmp(name, "open_path")) t->open_path = bg_strdup(t->open_path, val->val_str); if(!strcmp(name, "rename_mask")) t->rename_mask = bg_strdup(t->rename_mask, val->val_str); } int track_list_get_parameter(void * data, const char * name, bg_parameter_value_t * val) { track_list_t * t; if(!name) return 0; t = (track_list_t *)data; if(!strcmp(name, "open_path")) { val->val_str = bg_strdup(val->val_str, t->open_path); return 1; } else if(!strcmp(name, "rename_mask")) { val->val_str = bg_strdup(val->val_str, t->rename_mask); return 1; } return 0; } gmerlin-1.2.0~dfsg/apps/transcoder/gmerlin_transcoder_remote.10000644000175000017500000000203311764363402024522 0ustar alessioalessio.TH GMERLIN_TRANSCODER_REMOTE 1 "March 2012" Gmerlin "User Manuals" .SH NAME gmerlin_transcoder_remote .SH SYNOPSIS .B gmerlin_transcoder_remote .I [options] .I command .SH DESCRIPTION Remote control command for the Gmerlin GUI transcoder .SH GLOBAL OPTIONS .B -host .I .RS 2 Host to connect to, default is localhost .RE .B -port .I .RS 2 Port to connect to .RE .B -launch .RS 2 Launch new transcoder if necessary .RE .SH COMMANDS .B -addalbum .I .RS 2 Add album to track list .RE .B -add .I .RS 2 Add to the track list .RE .SH GENERIC OPTIONS The following generic options are available for all gmerlin applications .B -help .RS 2 Print this help message and exit .RE .B -help-man .RS 2 Print this help message as a manual page and exit .RE .B -help-texi .RS 2 Print this help message in texinfo format and exit .RE .B -version .RS 2 Print version info and exit .RE .SH ENVIRONMENT VARIABLES .B GMERLIN_TRANSCODER_REMOTE_PORT .RS 2 Default port for the remote control .RE gmerlin-1.2.0~dfsg/apps/transcoder/gmerlin_transcoder_remote.c0000644000175000017500000001342611764363402024614 0ustar alessioalessio/***************************************************************** * gmerlin - a general purpose multimedia framework and applications * * Copyright (c) 2001 - 2011 Members of the Gmerlin project * gmerlin-general@lists.sourceforge.net * http://gmerlin.sourceforge.net * * 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 of the License, 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 this program. If not, see . * *****************************************************************/ #include #include #include #include #include #include #include #define LOG_DOMAIN "gmerlin_transcoder_remote" #include "transcoder_remote.h" static void cmd_addalbum(void * data, int * argc, char *** _argv, int arg) { FILE * out = stderr; char * xml_string; bg_msg_t * msg; bg_remote_client_t * remote; char ** argv = *_argv; remote = (bg_remote_client_t *)data; if(arg >= *argc) { fprintf(out, "Option -addalbum requires an argument\n"); exit(-1); } /* Load the entire xml file into a string */ xml_string = bg_read_file(argv[arg], NULL); if(!xml_string) return; msg = bg_remote_client_get_msg_write(remote); bg_msg_set_id(msg, TRANSCODER_REMOTE_ADD_ALBUM); bg_msg_set_arg_string(msg, 0, xml_string); bg_cmdline_remove_arg(argc, _argv, arg); bg_remote_client_done_msg_write(remote); free(xml_string); } static void cmd_add(void * data, int * argc, char *** _argv, int arg) { FILE * out = stderr; bg_msg_t * msg; bg_remote_client_t * remote; remote = (bg_remote_client_t *)data; if(arg >= *argc) { fprintf(out, "Option -add requires an argument\n"); exit(-1); } msg = bg_remote_client_get_msg_write(remote); bg_msg_set_id(msg, TRANSCODER_REMOTE_ADD_FILE); bg_msg_set_arg_string(msg, 0, (*_argv)[arg]); bg_cmdline_remove_arg(argc, _argv, arg); bg_remote_client_done_msg_write(remote); } bg_cmdline_arg_t commands[] = { { .arg = "-addalbum", .help_arg = "", .help_string = "Add album to track list", .callback = cmd_addalbum, }, { .arg = "-add", .help_arg = "", .help_string = "Add to the track list", .callback = cmd_add, }, { /* End of options */ } }; char * host = NULL; int port = TRANSCODER_REMOTE_PORT; int launch = 0; static void opt_host(void * data, int * argc, char *** argv, int arg) { FILE * out = stderr; if(arg >= *argc) { fprintf(out, "Option -host requires an argument\n"); exit(-1); } host = bg_strdup(host, (*argv)[arg]); bg_cmdline_remove_arg(argc, argv, arg); } static void opt_port(void * data, int * argc, char *** argv, int arg) { FILE * out = stderr; if(arg >= *argc) { fprintf(out, "Option -port requires an argument\n"); exit(-1); } port = atoi((*argv)[arg]); bg_cmdline_remove_arg(argc, argv, arg); } static void opt_launch(void * data, int * argc, char *** argv, int arg) { launch = 1; } static bg_cmdline_arg_t global_options[] = { { .arg = "-host", .help_arg = "", .help_string = "Host to connect to, default is localhost", .callback = opt_host, }, { .arg = "-port", .help_arg = "", .help_string = "Port to connect to", .callback = opt_port, }, { .arg = "-launch", .help_string = "Launch new transcoder if necessary", .callback = opt_launch, }, { /* End of options */ } }; const bg_cmdline_app_data_t app_data = { .package = PACKAGE, .version = VERSION, .name = "gmerlin_transcoder_remote", .synopsis = TRS("[options] command\n"), .help_before = TRS("Remote control command for the Gmerlin GUI transcoder\n"), .args = (bg_cmdline_arg_array_t[]) { { TRS("Global options"), global_options }, { TRS("Commands"), commands }, { } }, .env = (bg_cmdline_ext_doc_t[]) { { TRANSCODER_REMOTE_ENV, TRS("Default port for the remote control") }, { /* End */ } }, }; int main(int argc, char ** argv) { int i; gavl_time_t delay_time = GAVL_TIME_SCALE / 50; bg_remote_client_t * remote; char * env; bg_cmdline_init(&app_data); if(argc < 2) bg_cmdline_print_help(argv[0], 0); port = TRANSCODER_REMOTE_PORT; env = getenv(TRANSCODER_REMOTE_ENV); if(env) port = atoi(env); bg_cmdline_parse(global_options, &argc, &argv, NULL); remote = bg_remote_client_create(TRANSCODER_REMOTE_ID, 0); if(!host) host = bg_strdup(host, "localhost"); if(!bg_remote_client_init(remote, host, port, 1000)) { if(launch) { if(system("gmerlin_transcoder &")) { bg_log(BG_LOG_ERROR, LOG_DOMAIN, "Cannot launch transcoder process"); return -1; } for(i = 0; i < 500; i++) { if(bg_remote_client_init(remote, host, port, 1000)) break; gavl_time_delay(&delay_time); } } else return -1; } bg_cmdline_parse(commands, &argc, &argv, remote); bg_remote_client_destroy(remote); return 0; } gmerlin-1.2.0~dfsg/apps/transcoder/ppwidget.c0000644000175000017500000001737311764363402021210 0ustar alessioalessio/***************************************************************** * gmerlin - a general purpose multimedia framework and applications * * Copyright (c) 2001 - 2011 Members of the Gmerlin project * gmerlin-general@lists.sourceforge.net * http://gmerlin.sourceforge.net * * 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 of the License, 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 this program. If not, see . * *****************************************************************/ #include #include #include #include #include #include #include #include #include "ppwidget.h" typedef struct { bg_gtk_plugin_widget_single_t * plugins; GtkWidget * pp; GtkWidget * widget; bg_plugin_registry_t * plugin_reg; } encoder_pp_widget_t; static void button_callback(GtkWidget * w, gpointer data) { encoder_pp_widget_t * wid = (encoder_pp_widget_t *)data; if(w == wid->pp) { if(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(wid->pp))) { bg_gtk_plugin_widget_single_set_sensitive(wid->plugins, 1); bg_plugin_registry_set_encode_pp(wid->plugin_reg, 1); } else { bg_gtk_plugin_widget_single_set_sensitive(wid->plugins, 0); bg_plugin_registry_set_encode_pp(wid->plugin_reg, 0); } } } static void encoder_pp_widget_init(encoder_pp_widget_t * ret, bg_plugin_registry_t * plugin_reg) { int row, num_columns; ret->plugin_reg = plugin_reg; ret->plugins = bg_gtk_plugin_widget_single_create("Postprocessing plugin", plugin_reg, BG_PLUGIN_ENCODER_PP, BG_PLUGIN_PP); bg_gtk_plugin_widget_single_set_sensitive(ret->plugins, 0); ret->pp = gtk_check_button_new_with_label(TR("Enable postprocessing")); g_signal_connect(G_OBJECT(ret->pp), "toggled", G_CALLBACK(button_callback), ret); gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(ret->pp), bg_plugin_registry_get_encode_pp(plugin_reg)); gtk_widget_show(ret->pp); ret->widget = gtk_table_new(1, 1, 0); gtk_table_set_row_spacings(GTK_TABLE(ret->widget), 5); gtk_table_set_col_spacings(GTK_TABLE(ret->widget), 5); gtk_container_set_border_width(GTK_CONTAINER(ret->widget), 5); row = 0; num_columns = 4; gtk_table_resize(GTK_TABLE(ret->widget), row+1, num_columns); gtk_table_attach(GTK_TABLE(ret->widget), ret->pp, 0, num_columns, row, row+1, GTK_FILL | GTK_EXPAND, GTK_SHRINK, 0, 0); row++; bg_gtk_plugin_widget_single_attach(ret->plugins, ret->widget, &row, &num_columns); gtk_widget_show(ret->widget); } static void encoder_pp_widget_destroy(encoder_pp_widget_t * wid) { bg_gtk_plugin_widget_single_destroy(wid->plugins); } /* Encoder window */ struct encoder_pp_window_s { encoder_pp_widget_t encoder_pp_widget; GtkWidget * window; GtkWidget * ok_button; GtkWidget * apply_button; GtkWidget * close_button; bg_transcoder_track_global_t * global; }; const bg_plugin_info_t * encoder_pp_window_get_plugin(encoder_pp_window_t * win) { if(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(win->encoder_pp_widget.pp))) return bg_gtk_plugin_widget_single_get_plugin(win->encoder_pp_widget.plugins); else return NULL; } static void encoder_pp_window_get(encoder_pp_window_t * win) { const bg_plugin_info_t * plugin_info; if(!win->global->pp_plugin) { gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(win->encoder_pp_widget.pp), 0); } else { gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(win->encoder_pp_widget.pp), 1); plugin_info = bg_plugin_find_by_name(win->encoder_pp_widget.plugin_reg, win->global->pp_plugin); bg_gtk_plugin_widget_single_set_plugin(win->encoder_pp_widget.plugins, plugin_info); } bg_transcoder_track_global_to_reg(win->global, win->encoder_pp_widget.plugin_reg); } static void encoder_pp_window_apply(encoder_pp_window_t * win) { bg_transcoder_track_global_from_reg(win->global, win->encoder_pp_widget.plugin_reg); } static void window_button_callback(GtkWidget * w, gpointer data) { encoder_pp_window_t * win = (encoder_pp_window_t *)data; if((w == win->close_button) || (w == win->window)) { gtk_widget_hide(win->window); gtk_main_quit(); } if(w == win->apply_button) { encoder_pp_window_apply(win); } if(w == win->ok_button) { encoder_pp_window_apply(win); gtk_widget_hide(win->window); gtk_main_quit(); } } static gboolean delete_callback(GtkWidget * w, GdkEvent * evt, gpointer data) { window_button_callback(w, data); return TRUE; } encoder_pp_window_t * encoder_pp_window_create(bg_plugin_registry_t * plugin_reg) { GtkWidget * mainbox; GtkWidget * buttonbox; encoder_pp_window_t * ret; ret = calloc(1, sizeof(*ret)); ret->window = bg_gtk_window_new(GTK_WINDOW_TOPLEVEL); gtk_window_set_position(GTK_WINDOW(ret->window), GTK_WIN_POS_CENTER); g_signal_connect(G_OBJECT(ret->window), "delete_event", G_CALLBACK(delete_callback), ret); gtk_window_set_title(GTK_WINDOW(ret->window), TR("Postprocessing")); gtk_window_set_modal(GTK_WINDOW(ret->window), 1); ret->apply_button = gtk_button_new_from_stock(GTK_STOCK_APPLY); ret->close_button = gtk_button_new_from_stock(GTK_STOCK_CLOSE); ret->ok_button = gtk_button_new_from_stock(GTK_STOCK_OK); g_signal_connect(G_OBJECT(ret->close_button), "clicked", G_CALLBACK(window_button_callback), ret); g_signal_connect(G_OBJECT(ret->apply_button), "clicked", G_CALLBACK(window_button_callback), ret); g_signal_connect(G_OBJECT(ret->ok_button), "clicked", G_CALLBACK(window_button_callback), ret); /* Show */ gtk_widget_show(ret->close_button); gtk_widget_show(ret->apply_button); gtk_widget_show(ret->ok_button); encoder_pp_widget_init(&ret->encoder_pp_widget, plugin_reg); /* Pack */ buttonbox = gtk_hbutton_box_new(); gtk_container_add(GTK_CONTAINER(buttonbox), ret->ok_button); gtk_container_add(GTK_CONTAINER(buttonbox), ret->apply_button); gtk_container_add(GTK_CONTAINER(buttonbox), ret->close_button); gtk_widget_show(buttonbox); mainbox = gtk_vbox_new(0, 5); bg_gtk_box_pack_start_defaults(GTK_BOX(mainbox), ret->encoder_pp_widget.widget); bg_gtk_box_pack_start_defaults(GTK_BOX(mainbox), buttonbox); gtk_widget_show(mainbox); gtk_container_add(GTK_CONTAINER(ret->window), mainbox); return ret; } void encoder_pp_window_run(encoder_pp_window_t * win, bg_transcoder_track_global_t * global) { win->global = global; encoder_pp_window_get(win); gtk_widget_show(win->window); gtk_main(); } void encoder_pp_window_destroy(encoder_pp_window_t * win) { encoder_pp_widget_destroy(&win->encoder_pp_widget); free(win); } gmerlin-1.2.0~dfsg/apps/transcoder/trackdialog.c0000644000175000017500000003456311764363402021651 0ustar alessioalessio/***************************************************************** * gmerlin - a general purpose multimedia framework and applications * * Copyright (c) 2001 - 2011 Members of the Gmerlin project * gmerlin-general@lists.sourceforge.net * http://gmerlin.sourceforge.net * * 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 of the License, 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 this program. If not, see . * *****************************************************************/ #include #include #include #include #include #include #include #include #include #include "trackdialog.h" #include struct track_dialog_s { /* Config dialog */ bg_dialog_t * cfg_dialog; void (*update_callback)(void * priv); void * update_priv; }; static void set_parameter_general(void * priv, const char * name, const bg_parameter_value_t * val) { track_dialog_t * d; d = (track_dialog_t *)priv; if(!name) { if(d->update_callback) d->update_callback(d->update_priv); } } track_dialog_t * track_dialog_create(bg_transcoder_track_t * t, void (*update_callback)(void * priv), void * update_priv, int show_tooltips, bg_plugin_registry_t * plugin_reg) { int i; char * label; track_dialog_t * ret; void * parent, * child; const char * plugin_name; const bg_plugin_info_t * plugin_info; const char * plugin_name1; const bg_plugin_info_t * plugin_info1; ret = calloc(1, sizeof(*ret)); ret->update_callback = update_callback; ret->update_priv = update_priv; ret->cfg_dialog = bg_dialog_create_multi(TR("Track options")); /* General */ bg_dialog_add(ret->cfg_dialog, TR("General"), t->general_section, set_parameter_general, NULL, ret, t->general_parameters); /* Metadata */ bg_dialog_add(ret->cfg_dialog, TR("Metadata"), t->metadata_section, NULL, NULL, NULL, t->metadata_parameters); /* Audio encoder */ if(t->num_audio_streams && t->audio_encoder_section) { plugin_name = bg_transcoder_track_get_audio_encoder(t); plugin_info = bg_plugin_find_by_name(plugin_reg, plugin_name); if(plugin_info->parameters) { label = TRD(plugin_info->long_name, plugin_info->gettext_domain); bg_dialog_add(ret->cfg_dialog, label, t->audio_encoder_section, NULL, NULL, NULL, plugin_info->parameters); } } /* Video encoder */ if((!t->audio_encoder_section && t->num_audio_streams ) || t->num_video_streams) { plugin_name = bg_transcoder_track_get_video_encoder(t); plugin_info = bg_plugin_find_by_name(plugin_reg, plugin_name); if(plugin_info->parameters) { label = TRD(plugin_info->long_name, plugin_info->gettext_domain); bg_dialog_add(ret->cfg_dialog, label, t->video_encoder_section, NULL, NULL, NULL, plugin_info->parameters); } } /* Subtitle text encoder */ if(t->subtitle_text_encoder_section && t->num_subtitle_text_streams) { plugin_name = bg_transcoder_track_get_subtitle_text_encoder(t); if(plugin_name) { plugin_info = bg_plugin_find_by_name(plugin_reg, plugin_name); if(plugin_info->parameters) { label = TRD(plugin_info->long_name, plugin_info->gettext_domain); bg_dialog_add(ret->cfg_dialog, label, t->subtitle_text_encoder_section, NULL, NULL, NULL, plugin_info->parameters); } } } /* Subtitle overlay encoder */ if(t->subtitle_overlay_encoder_section && (t->num_subtitle_text_streams || t->num_subtitle_overlay_streams)) { plugin_name = bg_transcoder_track_get_subtitle_overlay_encoder(t); if(plugin_name) { plugin_info = bg_plugin_find_by_name(plugin_reg, plugin_name); if(plugin_info->parameters) { label = TRD(plugin_info->long_name, plugin_info->gettext_domain); bg_dialog_add(ret->cfg_dialog, label, t->subtitle_overlay_encoder_section, NULL, NULL, NULL, plugin_info->parameters); } } } /* Audio streams */ plugin_name = bg_transcoder_track_get_audio_encoder(t); if(!plugin_name) plugin_name = bg_transcoder_track_get_video_encoder(t); if(plugin_name) plugin_info = bg_plugin_find_by_name(plugin_reg, plugin_name); else plugin_info = NULL; for(i = 0; i < t->num_audio_streams; i++) { if(t->num_audio_streams > 1) { if(t->audio_streams[i].label) label = bg_sprintf(TR("Audio #%d: %s"), i+1, t->audio_streams[i].label); else label = bg_sprintf(TR("Audio #%d"), i+1); } else { if(t->audio_streams[i].label) label = bg_sprintf(TR("Audio: %s"), t->audio_streams[i].label); else label = bg_sprintf(TR("Audio")); } parent = bg_dialog_add_parent(ret->cfg_dialog, NULL, label); free(label); bg_dialog_add_child(ret->cfg_dialog, parent, TR("General"), t->audio_streams[i].general_section, NULL, NULL, NULL, bg_transcoder_track_audio_get_general_parameters()); bg_dialog_add_child(ret->cfg_dialog, parent, TR("Filters"), t->audio_streams[i].filter_section, NULL, NULL, NULL, t->audio_streams[i].filter_parameters); if(plugin_info && plugin_info->audio_parameters) { label = TR("Encode options"); if(plugin_info->audio_parameters[0].type != BG_PARAMETER_SECTION) { bg_dialog_add_child(ret->cfg_dialog, parent, label, t->audio_streams[i].encoder_section, NULL, NULL, NULL, plugin_info->audio_parameters); } else { child = bg_dialog_add_parent(ret->cfg_dialog, parent, label); bg_dialog_add_child(ret->cfg_dialog, child, NULL, t->audio_streams[i].encoder_section, NULL, NULL, NULL, plugin_info->audio_parameters); } } } /* Video streams */ plugin_name = bg_transcoder_track_get_video_encoder(t); plugin_info = bg_plugin_find_by_name(plugin_reg, plugin_name); for(i = 0; i < t->num_video_streams; i++) { if(t->num_video_streams > 1) { if(t->video_streams[i].label) label = bg_sprintf(TR("Video #%d: %s"), i+1, t->video_streams[i].label); else label = bg_sprintf(TR("Video #%d"), i+1); } else { if(t->video_streams[i].label) label = bg_sprintf(TR("Video: %s"), t->video_streams[i].label); else label = bg_sprintf(TR("Video")); } parent = bg_dialog_add_parent(ret->cfg_dialog, NULL, label); free(label); bg_dialog_add_child(ret->cfg_dialog, parent, TR("General"), t->video_streams[i].general_section, NULL, NULL, NULL, bg_transcoder_track_video_get_general_parameters()); bg_dialog_add_child(ret->cfg_dialog, parent, TR("Filters"), t->video_streams[i].filter_section, NULL, NULL, NULL, t->video_streams[i].filter_parameters); if(plugin_info && plugin_info->video_parameters) { label = TR("Encode options"); if(plugin_info->video_parameters[0].type != BG_PARAMETER_SECTION) { bg_dialog_add_child(ret->cfg_dialog, parent, label, t->video_streams[i].encoder_section, NULL, NULL, NULL, plugin_info->video_parameters); } else { child = bg_dialog_add_parent(ret->cfg_dialog, parent, label); bg_dialog_add_child(ret->cfg_dialog, child, NULL, t->video_streams[i].encoder_section, NULL, NULL, NULL, plugin_info->video_parameters); } } } /* Subtitle streams */ plugin_name = bg_transcoder_track_get_subtitle_text_encoder(t); if(!plugin_name) plugin_name = bg_transcoder_track_get_video_encoder(t); if(plugin_name) plugin_info = bg_plugin_find_by_name(plugin_reg, plugin_name); else plugin_info = NULL; plugin_name1 = bg_transcoder_track_get_subtitle_overlay_encoder(t); if(!plugin_name1) plugin_name1 = bg_transcoder_track_get_video_encoder(t); if(plugin_name1) plugin_info1 = bg_plugin_find_by_name(plugin_reg, plugin_name1); else plugin_info1 = NULL; for(i = 0; i < t->num_subtitle_text_streams; i++) { if(t->num_subtitle_text_streams > 1) { if(t->subtitle_text_streams[i].label) label = bg_sprintf(TR("Subtitles #%d: %s"), i+1, t->subtitle_text_streams[i].label); else label = bg_sprintf(TR("Subtitles #%d"), i+1); } else { if(t->subtitle_text_streams[i].label) label = bg_sprintf(TR("Subtitles: %s"), t->subtitle_text_streams[i].label); else label = bg_sprintf(TR("Subtitles")); } parent = bg_dialog_add_parent(ret->cfg_dialog, NULL, label); free(label); bg_dialog_add_child(ret->cfg_dialog, parent, TR("General"), t->subtitle_text_streams[i].general_section, NULL, NULL, NULL, t->subtitle_text_streams[i].general_parameters); bg_dialog_add_child(ret->cfg_dialog, parent, TR("Textrenderer"), t->subtitle_text_streams[i].textrenderer_section, NULL, NULL, NULL, bg_text_renderer_get_parameters()); if(plugin_info->subtitle_text_parameters) { label = TR("Encode options (text)"); bg_dialog_add_child(ret->cfg_dialog, parent, label, t->subtitle_text_streams[i].encoder_section_text, NULL, NULL, NULL, plugin_info->subtitle_text_parameters); } if(plugin_info1->subtitle_overlay_parameters) { label = TR("Encode options (overlay)"); bg_dialog_add_child(ret->cfg_dialog, parent, label, t->subtitle_text_streams[i].encoder_section_overlay, NULL, NULL, NULL, plugin_info1->subtitle_overlay_parameters); } } for(i = 0; i < t->num_subtitle_overlay_streams; i++) { if(t->num_subtitle_overlay_streams > 1) { if(t->subtitle_overlay_streams[i].label) label = bg_sprintf(TR("Subtitles #%d: %s"), i+1+t->num_subtitle_text_streams, t->subtitle_overlay_streams[i].label); else label = bg_sprintf(TR("Subtitles #%d"), i+1+t->num_subtitle_text_streams); } else { if(t->subtitle_overlay_streams[i].label) label = bg_sprintf(TR("Subtitles: %s"), t->subtitle_overlay_streams[i].label); else label = bg_sprintf(TR("Subtitles")); } parent = bg_dialog_add_parent(ret->cfg_dialog, NULL, label); free(label); bg_dialog_add_child(ret->cfg_dialog, parent, TR("General"), t->subtitle_overlay_streams[i].general_section, NULL, NULL, NULL, t->subtitle_overlay_streams[i].general_parameters); if(plugin_info1->subtitle_overlay_parameters) { label = TR("Encode options"); bg_dialog_add_child(ret->cfg_dialog, parent, label, t->subtitle_overlay_streams[i].encoder_section, NULL, NULL, NULL, plugin_info1->subtitle_overlay_parameters); } } return ret; } void track_dialog_run(track_dialog_t * d, GtkWidget * parent) { bg_dialog_show(d->cfg_dialog, parent); } void track_dialog_destroy(track_dialog_t * d) { bg_dialog_destroy(d->cfg_dialog); free(d); } gmerlin-1.2.0~dfsg/apps/transcoder/transcoder_window.c0000644000175000017500000012604411764363402023114 0ustar alessioalessio/***************************************************************** * gmerlin - a general purpose multimedia framework and applications * * Copyright (c) 2001 - 2011 Members of the Gmerlin project * gmerlin-general@lists.sourceforge.net * http://gmerlin.sourceforge.net * * 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 of the License, 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 this program. If not, see . * *****************************************************************/ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "transcoder_window.h" #include "transcoder_remote.h" #include "tracklist.h" static const uint32_t stream_flags = BG_STREAM_AUDIO | BG_STREAM_VIDEO | BG_STREAM_SUBTITLE_TEXT | BG_STREAM_SUBTITLE_OVERLAY; static const uint32_t plugin_flags = BG_PLUGIN_FILE; struct transcoder_window_s { GtkWidget * win; bg_plugin_registry_t * plugin_reg; bg_cfg_registry_t * cfg_reg; track_list_t * tracklist; GtkWidget * run_button; GtkWidget * stop_button; GtkWidget * properties_button; GtkWidget * quit_button; GtkWidget * load_button; GtkWidget * save_button; bg_gtk_log_window_t * logwindow; int show_logwindow; GtkWidget * progress_bar; bg_gtk_time_display_t * time_remaining; bg_gtk_scrolltext_t * scrolltext; /* Configuration stuff */ char * output_directory; int delete_incomplete; bg_cfg_section_t * track_defaults_section; bg_parameter_info_t * encoder_parameters; bg_cfg_section_t * encoder_section; /* The actual transcoder */ bg_transcoder_t * transcoder; bg_transcoder_track_t * transcoder_track; /* Postprocessor */ bg_transcoder_pp_t * pp; bg_plugin_handle_t * pp_plugin; float fg_color[3]; float fg_color_e[3]; /* Foreground color for error messages */ float bg_color[3]; /* Load/Save stuff */ char * task_path; char * profile_path; GtkWidget * filesel; char * filesel_file; char * filesel_path; bg_remote_server_t * remote; GtkWidget * menubar; struct { GtkWidget * load_item; GtkWidget * save_item; GtkWidget * quit_item; GtkWidget * menu; } file_menu; struct { GtkWidget * config_item; GtkWidget * load_item; GtkWidget * save_item; GtkWidget * menu; } options_menu; struct { GtkWidget * run_item; GtkWidget * stop_item; GtkWidget * menu; } actions_menu; struct { GtkWidget * log_item; GtkWidget * menu; } windows_menu; struct { GtkWidget * about_item; GtkWidget * help_item; GtkWidget * menu; } help_menu; bg_msg_queue_t * msg_queue; }; static int start_transcode(transcoder_window_t * win); static const bg_parameter_info_t transcoder_window_parameters[] = { { .name = "display", .long_name = TRS("Display"), .type = BG_PARAMETER_SECTION, }, { .name = "display_foreground", .long_name = TRS("Foreground"), .type = BG_PARAMETER_COLOR_RGB, .val_default = { .val_color = { 1.0, 1.0, 0.0, 1.0 } } }, { .name = "display_foreground_error", .long_name = TRS("Error foreground"), .type = BG_PARAMETER_COLOR_RGB, .val_default = { .val_color = { 1.0, 0.0, 0.0, 1.0 } } }, { .name = "display_background", .long_name = TRS("Background"), .type = BG_PARAMETER_COLOR_RGB, .val_default = { .val_color = { 0.0, 0.0, 0.0, 1.0 } } }, { .name = "display_font", .long_name = TRS("Font"), .type = BG_PARAMETER_FONT, .val_default = { .val_str = "Sans Bold 10" } }, { .name = "task_path", .long_name = "Task path", .type = BG_PARAMETER_DIRECTORY, .flags = BG_PARAMETER_HIDE_DIALOG, .val_default = { .val_str = "." }, }, { .name = "profile_path", .long_name = "Profile path", .type = BG_PARAMETER_DIRECTORY, .flags = BG_PARAMETER_HIDE_DIALOG, .val_default = { .val_str = "." }, }, { .name = "show_logwindow", .long_name = "Show log window", .type = BG_PARAMETER_CHECKBUTTON, .flags = BG_PARAMETER_HIDE_DIALOG, .val_default = { .val_i = 0 }, }, { .name = "gui", .long_name = TRS("GUI"), .type = BG_PARAMETER_SECTION, }, { .name = "show_tooltips", .long_name = TRS("Show Tooltips"), .type = BG_PARAMETER_CHECKBUTTON, .val_default = { .val_i = 1 }, }, { /* End of parameters */ } }; static void set_transcoder_window_parameter(void * data, const char * name, const bg_parameter_value_t * val) { transcoder_window_t * win = (transcoder_window_t *)data; if(!name) { bg_gtk_scrolltext_set_colors(win->scrolltext, win->fg_color, win->bg_color); bg_gtk_time_display_set_colors(win->time_remaining, win->fg_color, win->bg_color); track_list_set_display_colors(win->tracklist, win->fg_color, win->bg_color); return; } if(!strcmp(name, "task_path")) { win->task_path = bg_strdup(win->task_path, val->val_str); } else if(!strcmp(name, "profile_path")) { win->profile_path = bg_strdup(win->profile_path, val->val_str); } else if(!strcmp(name, "display_foreground")) { memcpy(win->fg_color, val->val_color, 3 * sizeof(float)); } else if(!strcmp(name, "display_foreground_error")) { memcpy(win->fg_color_e, val->val_color, 3 * sizeof(float)); } else if(!strcmp(name, "display_background")) { memcpy(win->bg_color, val->val_color, 3 * sizeof(float)); } else if(!strcmp(name, "display_font")) { bg_gtk_scrolltext_set_font(win->scrolltext, val->val_str); } else if(!strcmp(name, "show_logwindow")) { win->show_logwindow = val->val_i; } else if(!strcmp(name, "show_tooltips")) { bg_gtk_set_tooltips(val->val_i); } } static int get_transcoder_window_parameter(void * data, const char * name, bg_parameter_value_t * val) { transcoder_window_t * win = (transcoder_window_t *)data; if(!name) return 1; if(!strcmp(name, "task_path")) { val->val_str = bg_strdup(val->val_str, win->task_path); return 1; } else if(!strcmp(name, "profile_path")) { val->val_str = bg_strdup(val->val_str, win->profile_path); return 1; } else if(!strcmp(name, "show_logwindow")) { val->val_i = win->show_logwindow; return 1; } return 0; } static void transcoder_window_preferences(transcoder_window_t * win); static void finish_transcoding(transcoder_window_t * win) { if(win->transcoder) { bg_transcoder_finish(win->transcoder); bg_transcoder_destroy(win->transcoder); win->transcoder = NULL; if(win->transcoder_track) { bg_transcoder_track_destroy(win->transcoder_track); win->transcoder_track = NULL; } if(win->pp) bg_transcoder_pp_update(win->pp); } else if(win->pp) { bg_transcoder_pp_finish(win->pp); bg_transcoder_pp_destroy(win->pp); win->pp = NULL; } /* Flush message queue */ while(bg_msg_queue_try_lock_read(win->msg_queue)) bg_msg_queue_unlock_read(win->msg_queue); } static gboolean idle_callback(gpointer data) { bg_msg_t * msg; float percentage_done; gavl_time_t remaining_time; char * arg_str; transcoder_window_t * win; win = (transcoder_window_t*)data; /* If the transcoder isn't there, it means that we were interrupted */ while((msg = bg_msg_queue_try_lock_read(win->msg_queue))) { switch(bg_msg_get_id(msg)) { case BG_TRANSCODER_MSG_START: arg_str = bg_msg_get_arg_string(msg, 0); bg_gtk_scrolltext_set_text(win->scrolltext, arg_str, win->fg_color, win->bg_color); free(arg_str); break; case BG_TRANSCODER_MSG_NUM_AUDIO_STREAMS: break; case BG_TRANSCODER_MSG_AUDIO_FORMAT: break; case BG_TRANSCODER_MSG_NUM_VIDEO_STREAMS: break; case BG_TRANSCODER_MSG_VIDEO_FORMAT: break; case BG_TRANSCODER_MSG_PROGRESS: percentage_done = bg_msg_get_arg_float(msg, 0); remaining_time = bg_msg_get_arg_time(msg, 1); bg_gtk_time_display_update(win->time_remaining, remaining_time, BG_GTK_DISPLAY_MODE_HMS); gtk_progress_bar_set_fraction(GTK_PROGRESS_BAR(win->progress_bar), percentage_done); break; case BG_TRANSCODER_MSG_FINISHED: finish_transcoding(win); bg_gtk_time_display_update(win->time_remaining, GAVL_TIME_UNDEFINED, BG_GTK_DISPLAY_MODE_HMS); gtk_progress_bar_set_fraction(GTK_PROGRESS_BAR(win->progress_bar), 0.0); if(!start_transcode(win)) { gtk_widget_set_sensitive(win->run_button, 1); gtk_widget_set_sensitive(win->actions_menu.run_item, 1); gtk_widget_set_sensitive(win->stop_button, 0); gtk_widget_set_sensitive(win->actions_menu.stop_item, 0); bg_msg_queue_unlock_read(win->msg_queue); return TRUE; } else { bg_msg_queue_unlock_read(win->msg_queue); return TRUE; } break; case BG_TRANSCODER_MSG_ERROR: arg_str = bg_msg_get_arg_string(msg, 0); bg_gtk_scrolltext_set_text(win->scrolltext, bg_gtk_log_window_last_error(win->logwindow), win->fg_color_e, win->bg_color); if(win->transcoder_track) { track_list_prepend_track(win->tracklist, win->transcoder_track); win->transcoder_track = NULL; } finish_transcoding(win); bg_gtk_time_display_update(win->time_remaining, GAVL_TIME_UNDEFINED, BG_GTK_DISPLAY_MODE_HMS); gtk_progress_bar_set_fraction(GTK_PROGRESS_BAR(win->progress_bar), 0.0); win->transcoder = NULL; gtk_widget_set_sensitive(win->run_button, 1); gtk_widget_set_sensitive(win->actions_menu.run_item, 1); gtk_widget_set_sensitive(win->stop_button, 0); gtk_widget_set_sensitive(win->actions_menu.stop_item, 0); free(arg_str); bg_msg_queue_unlock_read(win->msg_queue); return TRUE; } bg_msg_queue_unlock_read(win->msg_queue); } return TRUE; } static int start_transcode(transcoder_window_t * win) { bg_cfg_section_t * cfg_section; cfg_section = bg_cfg_registry_find_section(win->cfg_reg, "output"); win->transcoder_track = track_list_get_track(win->tracklist); if(!win->transcoder_track) { /* Check whether to postprocess */ if(win->pp) { bg_transcoder_pp_add_message_queue(win->pp, win->msg_queue); bg_transcoder_pp_run(win->pp); return 1; } else { bg_gtk_scrolltext_set_text(win->scrolltext, "Gmerlin transcoder version "VERSION, win->fg_color, win->bg_color); return 0; } } win->transcoder = bg_transcoder_create(); bg_cfg_section_apply(cfg_section, bg_transcoder_get_parameters(), bg_transcoder_set_parameter, win->transcoder); bg_transcoder_add_message_queue(win->transcoder, win->msg_queue); if(win->pp) { bg_transcoder_pp_connect(win->pp, win->transcoder); } if(!bg_transcoder_init(win->transcoder, win->plugin_reg, win->transcoder_track)) { bg_gtk_log_window_flush(win->logwindow); bg_gtk_scrolltext_set_text(win->scrolltext, bg_gtk_log_window_last_error(win->logwindow), win->fg_color_e, win->bg_color); if(win->transcoder_track) track_list_prepend_track(win->tracklist, win->transcoder_track); win->transcoder_track = NULL; bg_transcoder_destroy(win->transcoder); win->transcoder = NULL; return 0; } gtk_widget_set_sensitive(win->run_button, 0); gtk_widget_set_sensitive(win->actions_menu.run_item, 0); gtk_widget_set_sensitive(win->stop_button, 1); gtk_widget_set_sensitive(win->actions_menu.stop_item, 1); bg_transcoder_run(win->transcoder); return 1; } #if 0 static void filesel_button_callback(GtkWidget * w, gpointer * data) { const char * end_pos; GtkFileSelection * filesel; transcoder_window_t * win = (transcoder_window_t *)data; filesel = GTK_FILE_SELECTION(win->filesel); if(w == filesel->ok_button) { win->filesel_file = bg_strdup(NULL, gtk_file_selection_get_filename(filesel)); gtk_widget_hide(win->filesel); end_pos = strrchr(win->filesel_file, '/'); if(end_pos) { end_pos++; win->filesel_path = bg_strndup(win->filesel_path, win->filesel_file, end_pos); } gtk_main_quit(); } else if((w == win->filesel) || (w == filesel->cancel_button)) { gtk_widget_hide(win->filesel); gtk_main_quit(); } } static gboolean filesel_delete_callback(GtkWidget * w, GdkEventAny * event, gpointer * data) { filesel_button_callback(w, data); return TRUE; } static GtkWidget * create_filesel(transcoder_window_t * win) { GtkWidget * ret; ret = gtk_file_selection_new(""); gtk_window_set_modal(GTK_WINDOW(ret), 1); g_signal_connect(G_OBJECT(ret), "delete-event", G_CALLBACK(filesel_delete_callback), win); g_signal_connect(G_OBJECT(GTK_FILE_SELECTION(ret)->ok_button), "clicked", G_CALLBACK(filesel_button_callback), win); g_signal_connect(G_OBJECT(GTK_FILE_SELECTION(ret)->cancel_button), "clicked", G_CALLBACK(filesel_button_callback), win); return ret; } static void filesel_set_path(GtkWidget * filesel, char * path) { if(path) gtk_file_selection_set_filename(GTK_FILE_SELECTION(filesel), path); } #endif static void about_window_close_callback(bg_gtk_about_window_t * w, void * data) { transcoder_window_t * win = (transcoder_window_t *)data; gtk_widget_set_sensitive(win->help_menu.about_item, 1); } void transcoder_window_load_profile(transcoder_window_t * win, const char * file) { bg_cfg_section_t * s; bg_cfg_registry_load(win->cfg_reg, file); s = bg_encoder_section_get_from_registry(win->plugin_reg, win->encoder_parameters, stream_flags, plugin_flags); bg_cfg_section_transfer(s, win->encoder_section); bg_cfg_section_destroy(s); } static void transcoder_window_save_profile(transcoder_window_t * win, const char * file) { bg_encoder_section_store_in_registry(win->plugin_reg, win->encoder_section, win->encoder_parameters, stream_flags, plugin_flags); bg_cfg_registry_save(win->cfg_reg, file); } static void button_callback(GtkWidget * w, gpointer data) { bg_cfg_section_t * cfg_section; transcoder_window_t * win = (transcoder_window_t *)data; char * tmp_string; if((w == win->run_button) || (w == win->actions_menu.run_item)) { win->pp_plugin = track_list_get_pp_plugin(win->tracklist); if(win->pp_plugin) { win->pp = bg_transcoder_pp_create(); cfg_section = bg_cfg_registry_find_section(win->cfg_reg, "output"); bg_cfg_section_apply(cfg_section, bg_transcoder_get_parameters(), bg_transcoder_pp_set_parameter, win->pp); if(!bg_transcoder_pp_init(win->pp, win->pp_plugin)) { bg_transcoder_pp_destroy(win->pp); win->pp = NULL; } } start_transcode(win); } else if((w == win->stop_button) || (w == win->actions_menu.stop_item)) { if(win->transcoder_track) track_list_prepend_track(win->tracklist, win->transcoder_track); win->transcoder_track = NULL; if(win->transcoder) bg_transcoder_stop(win->transcoder); else if(win->pp) bg_transcoder_pp_stop(win->pp); finish_transcoding(win); gtk_widget_set_sensitive(win->run_button, 1); gtk_widget_set_sensitive(win->actions_menu.run_item, 1); gtk_widget_set_sensitive(win->stop_button, 0); gtk_widget_set_sensitive(win->actions_menu.stop_item, 0); bg_gtk_time_display_update(win->time_remaining, GAVL_TIME_UNDEFINED, BG_GTK_DISPLAY_MODE_HMS); gtk_progress_bar_set_fraction(GTK_PROGRESS_BAR(win->progress_bar), 0.0); bg_gtk_scrolltext_set_text(win->scrolltext, "Gmerlin transcoder version "VERSION, win->fg_color, win->bg_color); } else if((w == win->load_button) || (w == win->file_menu.load_item)) { tmp_string = bg_gtk_get_filename_read(TR("Load task list"), &win->task_path, win->load_button); if(tmp_string) { track_list_load(win->tracklist, tmp_string); free(tmp_string); } } else if((w == win->save_button) || (w == win->file_menu.save_item)) { tmp_string = bg_gtk_get_filename_write(TR("Save task list"), &win->task_path, 1, win->save_button); if(tmp_string) { track_list_save(win->tracklist, tmp_string); free(tmp_string); } } else if(w == win->options_menu.load_item) { tmp_string = bg_gtk_get_filename_read(TR("Load profile"), &win->profile_path, win->win); if(tmp_string) { transcoder_window_load_profile(win, tmp_string); free(tmp_string); } } else if(w == win->options_menu.save_item) { tmp_string = bg_gtk_get_filename_write(TR("Save profile"), &win->profile_path, 1, win->win); if(tmp_string) { transcoder_window_save_profile(win, tmp_string); free(tmp_string); } } else if((w == win->quit_button) || (w == win->file_menu.quit_item)) { gtk_widget_hide(win->win); gtk_main_quit(); } else if((w == win->properties_button) || (w == win->options_menu.config_item)) { transcoder_window_preferences(win); } else if(w == win->windows_menu.log_item) { if(gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(w))) { bg_gtk_log_window_show(win->logwindow); win->show_logwindow = 1; } else { bg_gtk_log_window_hide(win->logwindow); win->show_logwindow = 0; } } else if(w == win->help_menu.about_item) { bg_gtk_about_window_create("Gmerlin transcoder", VERSION, "transcoder_icon.png", about_window_close_callback, win); gtk_widget_set_sensitive(win->help_menu.about_item, 0); } else if(w == win->help_menu.help_item) { bg_display_html_help("userguide/GUI-Transcoder.html"); } } static GtkWidget * create_pixmap_button(transcoder_window_t * win, const char * pixmap, const char * tooltip) { GtkWidget * ret; GtkWidget * image; char * path; path = bg_search_file_read("icons", pixmap); if(path) { image = gtk_image_new_from_file(path); free(path); } else image = gtk_image_new(); ret = gtk_button_new(); gtk_widget_show(image); gtk_container_add(GTK_CONTAINER(ret), image); g_signal_connect(G_OBJECT(ret), "clicked", G_CALLBACK(button_callback), win); gtk_widget_show(ret); bg_gtk_tooltips_set_tip(ret, tooltip, PACKAGE); return ret; } static gboolean delete_callback(GtkWidget * w, GdkEvent * evt, gpointer data) { transcoder_window_t * win = (transcoder_window_t *)data; gtk_widget_hide(win->win); gtk_main_quit(); return TRUE; } static GtkWidget * create_item(transcoder_window_t * w, GtkWidget * parent, const char * label, const char * pixmap) { GtkWidget * ret, *image; char * path; if(pixmap) { path = bg_search_file_read("icons", pixmap); if(path) { image = gtk_image_new_from_file(path); free(path); } else image = gtk_image_new(); gtk_widget_show(image); ret = gtk_image_menu_item_new_with_label(label); gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(ret), image); } else { ret = gtk_menu_item_new_with_label(label); } g_signal_connect(G_OBJECT(ret), "activate", G_CALLBACK(button_callback), (gpointer)w); gtk_widget_show(ret); gtk_menu_shell_append(GTK_MENU_SHELL(parent), ret); return ret; } static GtkWidget * create_toggle_item(transcoder_window_t * w, GtkWidget * parent, const char * label) { GtkWidget * ret; ret = gtk_check_menu_item_new_with_label(label); g_signal_connect(G_OBJECT(ret), "toggled", G_CALLBACK(button_callback), (gpointer)w); gtk_widget_show(ret); gtk_menu_shell_append(GTK_MENU_SHELL(parent), ret); return ret; } #if 0 struct { GtkWidget * load_item; GtkWidget * save_item; GtkWidget * quit_item; GtkWidget * menu; } file_menu; struct { GtkWidget * config_item; GtkWidget * load_item; GtkWidget * save_item; } options_menu; #endif static void init_menus(transcoder_window_t * w) { w->file_menu.menu = gtk_menu_new(); w->file_menu.load_item = create_item(w, w->file_menu.menu, TR("Load tasklist..."), "folder_open_16.png"); w->file_menu.save_item = create_item(w, w->file_menu.menu, TR("Save tasklist..."), "save_16.png"); w->file_menu.quit_item = create_item(w, w->file_menu.menu, TR("Quit"), "quit_16.png"); gtk_widget_show(w->file_menu.menu); w->options_menu.menu = gtk_menu_new(); w->options_menu.config_item = create_item(w, w->options_menu.menu, TR("Preferences..."), "config_16.png"); w->options_menu.load_item = create_item(w, w->options_menu.menu, TR("Load profile..."), "folder_open_16.png"); w->options_menu.save_item = create_item(w, w->options_menu.menu, TR("Save profile..."), "save_16.png"); gtk_widget_show(w->options_menu.menu); w->actions_menu.menu = gtk_menu_new(); w->actions_menu.run_item = create_item(w, w->actions_menu.menu, TR("Start transcoding"), "run_16.png"); w->actions_menu.stop_item = create_item(w, w->actions_menu.menu, TR("Stop transcoding"), "stop_16.png"); gtk_widget_set_sensitive(w->actions_menu.stop_item, 0); w->windows_menu.menu = gtk_menu_new(); w->windows_menu.log_item = create_toggle_item(w, w->windows_menu.menu, TR("Log messages")); gtk_widget_show(w->windows_menu.menu); w->help_menu.menu = gtk_menu_new(); w->help_menu.about_item = create_item(w, w->help_menu.menu, TR("About..."), "about_16.png"); w->help_menu.help_item = create_item(w, w->help_menu.menu, TR("Userguide"), "help_16.png"); gtk_widget_show(w->help_menu.menu); } static void logwindow_close_callback(bg_gtk_log_window_t*w, void*data) { transcoder_window_t * win = (transcoder_window_t*)data; gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(win->windows_menu.log_item), 0); win->show_logwindow = 0; } transcoder_window_t * transcoder_window_create() { int port; char * env; GtkWidget * menuitem; GtkWidget * main_table; GtkWidget * frame; GtkWidget * box; char * tmp_path; transcoder_window_t * ret; bg_cfg_section_t * cfg_section; ret = calloc(1, sizeof(*ret)); ret->msg_queue = bg_msg_queue_create(); g_timeout_add(200, idle_callback, ret); /* Create window */ ret->win = bg_gtk_window_new(GTK_WINDOW_TOPLEVEL); gtk_window_set_position(GTK_WINDOW(ret->win), GTK_WIN_POS_CENTER); gtk_window_set_title(GTK_WINDOW(ret->win), "Gmerlin transcoder "VERSION); g_signal_connect(G_OBJECT(ret->win), "delete_event", G_CALLBACK(delete_callback), ret); /* Create config registry */ ret->cfg_reg = bg_cfg_registry_create(); tmp_path = bg_search_file_read("transcoder", "config.xml"); bg_cfg_registry_load(ret->cfg_reg, tmp_path); if(tmp_path) free(tmp_path); /* Create plugin registry */ cfg_section = bg_cfg_registry_find_section(ret->cfg_reg, "plugins"); ret->plugin_reg = bg_plugin_registry_create(cfg_section); /* Create encoding parameters */ ret->encoder_parameters = bg_plugin_registry_create_encoder_parameters(ret->plugin_reg, stream_flags, plugin_flags); // bg_parameters_dump(ret->encoder_parameters, "encoder_params.xml"); ret->encoder_section = bg_encoder_section_get_from_registry(ret->plugin_reg, ret->encoder_parameters, stream_flags, plugin_flags); // bg_cfg_section_dump(ret->encoder_section, "encoders.xml"); /* Create track list */ ret->track_defaults_section = bg_cfg_registry_find_section(ret->cfg_reg, "track_defaults"); ret->tracklist = track_list_create(ret->plugin_reg, ret->track_defaults_section, ret->encoder_parameters, ret->encoder_section); gtk_window_add_accel_group(GTK_WINDOW(ret->win), track_list_get_accel_group(ret->tracklist)); cfg_section = bg_cfg_registry_find_section(ret->cfg_reg, "track_list"); bg_cfg_section_apply(cfg_section, track_list_get_parameters(ret->tracklist), track_list_set_parameter, ret->tracklist); /* Create log window */ ret->logwindow = bg_gtk_log_window_create(logwindow_close_callback, ret, TR("Gmerlin transcoder")); cfg_section = bg_cfg_registry_find_section(ret->cfg_reg, "logwindow"); bg_cfg_section_apply(cfg_section, bg_gtk_log_window_get_parameters(ret->logwindow), bg_gtk_log_window_set_parameter, ret->logwindow); /* Create buttons */ ret->run_button = create_pixmap_button(ret, "run_16.png", TRS("Start transcoding")); ret->stop_button = create_pixmap_button(ret, "stop_16.png", TRS("Stop transcoding")); ret->properties_button = create_pixmap_button(ret, "config_16.png", TRS("Set global options and track defaults")); ret->quit_button = create_pixmap_button(ret, "quit_16.png", TRS("Quit program")); ret->load_button = create_pixmap_button(ret, "folder_open_16.png", TRS("Load task list")); ret->save_button = create_pixmap_button(ret, "save_16.png", TRS("Save task list")); gtk_widget_set_sensitive(ret->stop_button, 0); /* Progress bar */ ret->progress_bar = gtk_progress_bar_new(); gtk_widget_show(ret->progress_bar); /* Time display */ ret->time_remaining = bg_gtk_time_display_create(BG_GTK_DISPLAY_SIZE_SMALL, 4, BG_GTK_DISPLAY_MODE_HMS); bg_gtk_tooltips_set_tip(bg_gtk_time_display_get_widget(ret->time_remaining), "Estimated remaining transcoding time", PACKAGE); bg_gtk_time_display_update(ret->time_remaining, GAVL_TIME_UNDEFINED, BG_GTK_DISPLAY_MODE_HMS); /* Scrolltext */ ret->scrolltext = bg_gtk_scrolltext_create(100, 24); /* Menubar */ init_menus(ret); ret->menubar = gtk_menu_bar_new(); menuitem = gtk_menu_item_new_with_label(TR("File")); gtk_menu_item_set_submenu(GTK_MENU_ITEM(menuitem), ret->file_menu.menu); gtk_widget_show(menuitem); gtk_menu_shell_append(GTK_MENU_SHELL(ret->menubar), menuitem); menuitem = gtk_menu_item_new_with_label(TR("Options")); gtk_menu_item_set_submenu(GTK_MENU_ITEM(menuitem), ret->options_menu.menu); gtk_widget_show(menuitem); gtk_menu_shell_append(GTK_MENU_SHELL(ret->menubar), menuitem); menuitem = gtk_menu_item_new_with_label(TR("Actions")); gtk_menu_item_set_submenu(GTK_MENU_ITEM(menuitem), ret->actions_menu.menu); gtk_widget_show(menuitem); gtk_menu_shell_append(GTK_MENU_SHELL(ret->menubar), menuitem); menuitem = gtk_menu_item_new_with_label(TR("Tasklist")); gtk_menu_item_set_submenu(GTK_MENU_ITEM(menuitem), track_list_get_menu(ret->tracklist)); gtk_widget_show(menuitem); gtk_menu_shell_append(GTK_MENU_SHELL(ret->menubar), menuitem); menuitem = gtk_menu_item_new_with_label(TR("Windows")); gtk_menu_item_set_submenu(GTK_MENU_ITEM(menuitem), ret->windows_menu.menu); gtk_widget_show(menuitem); gtk_menu_shell_append(GTK_MENU_SHELL(ret->menubar), menuitem); menuitem = gtk_menu_item_new_with_label(TR("Help")); gtk_menu_item_set_submenu(GTK_MENU_ITEM(menuitem), ret->help_menu.menu); gtk_widget_show(menuitem); gtk_menu_shell_append(GTK_MENU_SHELL(ret->menubar), menuitem); gtk_widget_show(ret->menubar); /* Pack everything */ main_table = gtk_table_new(5, 1, 0); gtk_container_set_border_width(GTK_CONTAINER(main_table), 5); gtk_table_set_row_spacings(GTK_TABLE(main_table), 5); gtk_table_set_col_spacings(GTK_TABLE(main_table), 5); gtk_table_attach(GTK_TABLE(main_table), ret->menubar, 0, 1, 0, 1, GTK_FILL, GTK_FILL, 0, 0); box = gtk_hbox_new(0, 0); gtk_box_pack_start(GTK_BOX(box), ret->load_button, FALSE, FALSE, 0); gtk_box_pack_start(GTK_BOX(box), ret->save_button, FALSE, FALSE, 0); gtk_box_pack_start(GTK_BOX(box), ret->run_button, FALSE, FALSE, 0); gtk_box_pack_start(GTK_BOX(box), ret->stop_button, FALSE, FALSE, 0); gtk_box_pack_start(GTK_BOX(box), ret->properties_button, FALSE, FALSE, 0); gtk_box_pack_start(GTK_BOX(box), ret->quit_button, FALSE, FALSE, 0); gtk_widget_show(box); gtk_table_attach(GTK_TABLE(main_table), box, 0, 1, 1, 2, GTK_FILL, GTK_FILL, 0, 0); box = gtk_hbox_new(0, 0); gtk_box_pack_end(GTK_BOX(box), bg_gtk_time_display_get_widget(ret->time_remaining), FALSE, FALSE, 0); bg_gtk_box_pack_start_defaults(GTK_BOX(box), bg_gtk_scrolltext_get_widget(ret->scrolltext)); gtk_widget_show(box); gtk_table_attach(GTK_TABLE(main_table), box, 0, 1, 2, 3, GTK_FILL, GTK_FILL, 0, 0); gtk_table_attach(GTK_TABLE(main_table), ret->progress_bar, 0, 1, 3, 4, GTK_FILL, GTK_FILL, 0, 0); frame = gtk_frame_new(TR("Tasklist")); gtk_container_add(GTK_CONTAINER(frame), track_list_get_widget(ret->tracklist)); gtk_widget_show(frame); gtk_table_attach_defaults(GTK_TABLE(main_table), frame, 0, 1, 4, 5); gtk_widget_show(main_table); gtk_container_add(GTK_CONTAINER(ret->win), main_table); bg_gtk_scrolltext_set_text(ret->scrolltext, "Gmerlin transcoder version "VERSION, ret->fg_color, ret->bg_color); /* Apply config stuff */ cfg_section = bg_cfg_registry_find_section(ret->cfg_reg, "transcoder_window"); bg_cfg_section_apply(cfg_section, transcoder_window_parameters, set_transcoder_window_parameter, ret); port = TRANSCODER_REMOTE_PORT; env = getenv(TRANSCODER_REMOTE_ENV); if(env) port = atoi(env); ret->remote = bg_remote_server_create(port, TRANSCODER_REMOTE_ID); cfg_section = bg_cfg_registry_find_section(ret->cfg_reg, "remote"); bg_cfg_section_apply(cfg_section, bg_remote_server_get_parameters(ret->remote), bg_remote_server_set_parameter, ret->remote); return ret; } void transcoder_window_destroy(transcoder_window_t* w) { char * tmp_path; bg_cfg_section_t * cfg_section; bg_encoder_section_store_in_registry(w->plugin_reg, w->encoder_section, w->encoder_parameters, stream_flags, plugin_flags); bg_cfg_section_destroy(w->encoder_section); bg_parameter_info_destroy_array(w->encoder_parameters); cfg_section = bg_cfg_registry_find_section(w->cfg_reg, "transcoder_window"); bg_cfg_section_get(cfg_section, transcoder_window_parameters, get_transcoder_window_parameter, w); cfg_section = bg_cfg_registry_find_section(w->cfg_reg, "track_list"); bg_cfg_section_get(cfg_section, track_list_get_parameters(w->tracklist), track_list_get_parameter, w->tracklist); track_list_destroy(w->tracklist); cfg_section = bg_cfg_registry_find_section(w->cfg_reg, "logwindow"); bg_cfg_section_get(cfg_section, bg_gtk_log_window_get_parameters(w->logwindow), bg_gtk_log_window_get_parameter, w->logwindow); bg_gtk_log_window_destroy(w->logwindow); tmp_path = bg_search_file_write("transcoder", "config.xml"); bg_cfg_registry_save(w->cfg_reg, tmp_path); if(tmp_path) free(tmp_path); bg_plugin_registry_destroy(w->plugin_reg); bg_cfg_registry_destroy(w->cfg_reg); if(w->task_path) free(w->task_path); if(w->profile_path) free(w->profile_path); bg_msg_queue_destroy(w->msg_queue); bg_remote_server_destroy(w->remote); bg_gtk_time_display_destroy(w->time_remaining); bg_gtk_scrolltext_destroy(w->scrolltext); // g_object_unref(w->win); free(w); } static gboolean remote_callback(gpointer data) { int id; char * arg_str; bg_msg_t * msg; transcoder_window_t * win; win = (transcoder_window_t*)data; while((msg = bg_remote_server_get_msg(win->remote))) { id = bg_msg_get_id(msg); switch(id) { case TRANSCODER_REMOTE_ADD_ALBUM: arg_str = bg_msg_get_arg_string(msg, 0); track_list_add_albumentries_xml(win->tracklist, arg_str); free(arg_str); break; case TRANSCODER_REMOTE_ADD_FILE: arg_str = bg_msg_get_arg_string(msg, 0); track_list_add_url(win->tracklist, arg_str); free(arg_str); break; } } return TRUE; } void transcoder_window_run(transcoder_window_t * w) { gtk_widget_show(w->win); if(w->show_logwindow) { gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(w->windows_menu.log_item), 1); } // bg_gtk_log_window_show(w->logwindow); remote_callback(w); g_timeout_add(50, remote_callback, w); gtk_main(); } static const bg_parameter_info_t input_plugin_parameters[] = { { .name = "input_plugins", .long_name = "Input plugins", .flags = BG_PARAMETER_PLUGIN, }, { /* */ }, }; static const bg_parameter_info_t image_reader_parameters[] = { { .name = "image_readers", .long_name = "Image readers", .flags = BG_PARAMETER_PLUGIN, }, { /* */ }, }; /* Configuration stuff */ static void transcoder_window_preferences(transcoder_window_t * w) { bg_dialog_t * dlg; bg_cfg_section_t * cfg_section; void * parent; bg_audio_filter_chain_t * ac; bg_video_filter_chain_t * vc; bg_gavl_audio_options_t ao; bg_gavl_video_options_t vo; bg_parameter_info_t * params_i; bg_parameter_info_t * params_ir; params_i = bg_parameter_info_copy_array(input_plugin_parameters); params_ir = bg_parameter_info_copy_array(image_reader_parameters); bg_plugin_registry_set_parameter_info_input(w->plugin_reg, BG_PLUGIN_INPUT, BG_PLUGIN_FILE| BG_PLUGIN_URL| BG_PLUGIN_REMOVABLE| BG_PLUGIN_TUNER, params_i); bg_plugin_registry_set_parameter_info_input(w->plugin_reg, BG_PLUGIN_IMAGE_READER, BG_PLUGIN_FILE, params_ir); memset(&ao, 0, sizeof(ao)); memset(&vo, 0, sizeof(vo)); bg_gavl_audio_options_init(&ao); bg_gavl_video_options_init(&vo); ac = bg_audio_filter_chain_create(&ao, w->plugin_reg); vc = bg_video_filter_chain_create(&vo, w->plugin_reg); dlg = bg_dialog_create_multi(TR("Transcoder configuration")); cfg_section = bg_cfg_registry_find_section(w->cfg_reg, "output"); bg_dialog_add(dlg, TR("Output options"), cfg_section, NULL, NULL, NULL, bg_transcoder_get_parameters()); cfg_section = bg_cfg_section_find_subsection(w->track_defaults_section, "general"); bg_dialog_add(dlg, TR("Track defaults"), cfg_section, NULL, NULL, NULL, bg_transcoder_track_get_general_parameters()); parent = bg_dialog_add_parent(dlg, NULL, TR("Audio defaults")); cfg_section = bg_cfg_section_find_subsection(w->track_defaults_section, "audio"); bg_dialog_add_child(dlg, parent, TR("General"), cfg_section, NULL, NULL, NULL, bg_transcoder_track_audio_get_general_parameters()); cfg_section = bg_cfg_section_find_subsection(w->track_defaults_section, "audiofilters"); bg_dialog_add_child(dlg, parent, TR("Filters"), cfg_section, NULL, NULL, NULL, bg_audio_filter_chain_get_parameters(ac)); cfg_section = bg_cfg_section_find_subsection(w->track_defaults_section, "video"); parent = bg_dialog_add_parent(dlg, NULL, TR("Video defaults")); bg_dialog_add_child(dlg, parent, TR("General"), cfg_section, NULL, NULL, NULL, bg_transcoder_track_video_get_general_parameters()); cfg_section = bg_cfg_section_find_subsection(w->track_defaults_section, "videofilters"); bg_dialog_add_child(dlg, parent, TR("Filters"), cfg_section, NULL, NULL, NULL, bg_video_filter_chain_get_parameters(vc)); parent = bg_dialog_add_parent(dlg, NULL, TR("Text subtitle defaults")); cfg_section = bg_cfg_section_find_subsection(w->track_defaults_section, "subtitle_text"); bg_dialog_add_child(dlg, parent, TR("General"), cfg_section, NULL, NULL, NULL, bg_transcoder_track_subtitle_text_get_general_parameters()); cfg_section = bg_cfg_section_find_subsection(w->track_defaults_section, "textrenderer"); bg_dialog_add_child(dlg, parent, TR("Textrenderer"), cfg_section, NULL, NULL, NULL, bg_text_renderer_get_parameters()); cfg_section = bg_cfg_section_find_subsection(w->track_defaults_section, "subtitle_overlay"); bg_dialog_add(dlg, TR("Overlay subtitle defaults"), cfg_section, NULL, NULL, NULL, bg_transcoder_track_subtitle_overlay_get_general_parameters()); bg_dialog_add(dlg, TR("Encoders"), w->encoder_section, NULL, NULL, NULL, w->encoder_parameters); bg_dialog_add(dlg, TR("Input plugins"), NULL, bg_plugin_registry_set_parameter_input, bg_plugin_registry_get_parameter_input, w->plugin_reg, params_i); bg_dialog_add(dlg, TR("Image readers"), NULL, bg_plugin_registry_set_parameter_input, bg_plugin_registry_get_parameter_input, w->plugin_reg, params_ir); cfg_section = bg_cfg_registry_find_section(w->cfg_reg, "transcoder_window"); bg_dialog_add(dlg, TR("Window"), cfg_section, set_transcoder_window_parameter, NULL, w, transcoder_window_parameters); cfg_section = bg_cfg_registry_find_section(w->cfg_reg, "remote"); bg_dialog_add(dlg, TR("Remote"), cfg_section, bg_remote_server_set_parameter, NULL, w->remote, bg_remote_server_get_parameters(w->remote)); cfg_section = bg_cfg_registry_find_section(w->cfg_reg, "logwindow"); bg_dialog_add(dlg, TR("Log window"), cfg_section, bg_gtk_log_window_set_parameter, NULL, w->logwindow, bg_gtk_log_window_get_parameters(w->logwindow)); bg_dialog_show(dlg, w->win); bg_dialog_destroy(dlg); bg_audio_filter_chain_destroy(ac); bg_video_filter_chain_destroy(vc); bg_gavl_audio_options_free(&ao); bg_gavl_video_options_free(&vo); } gmerlin-1.2.0~dfsg/apps/transcoder/gmerlin-transcoder.desktop0000644000175000017500000000041411764363402024377 0ustar alessioalessio[Desktop Entry] Encoding=UTF-8 Name=Gmerlin transcoder Name[de]=Gmerlin transcoder Comment=Gmerlin multimedia transcoder Comment[de]=Gmerlin multimedia transcoder Exec=gmerlin_transcoder Icon=gmerlin-transcoder.png Type=Application Categories=Application;AudioVideo; gmerlin-1.2.0~dfsg/apps/transcoder/ppwidget.h0000644000175000017500000000256211764363402021207 0ustar alessioalessio/***************************************************************** * gmerlin - a general purpose multimedia framework and applications * * Copyright (c) 2001 - 2011 Members of the Gmerlin project * gmerlin-general@lists.sourceforge.net * http://gmerlin.sourceforge.net * * 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 of the License, 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 this program. If not, see . * *****************************************************************/ /* Encoder window */ typedef struct encoder_pp_window_s encoder_pp_window_t; encoder_pp_window_t * encoder_pp_window_create(bg_plugin_registry_t * plugin_reg); void encoder_pp_window_run(encoder_pp_window_t * win, bg_transcoder_track_global_t * global); void encoder_pp_window_destroy(encoder_pp_window_t * win); const bg_plugin_info_t * encoder_pp_window_get_plugin(encoder_pp_window_t * win); gmerlin-1.2.0~dfsg/apps/transcoder/tracklist.h0000644000175000017500000000443411764363402021364 0ustar alessioalessio/***************************************************************** * gmerlin - a general purpose multimedia framework and applications * * Copyright (c) 2001 - 2011 Members of the Gmerlin project * gmerlin-general@lists.sourceforge.net * http://gmerlin.sourceforge.net * * 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 of the License, 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 this program. If not, see . * *****************************************************************/ typedef struct track_list_s track_list_t; track_list_t * track_list_create(bg_plugin_registry_t * plugin_reg, bg_cfg_section_t * track_defaults_section, const bg_parameter_info_t * encoder_parameters, bg_cfg_section_t * encoder_section); void track_list_destroy(track_list_t *); GtkWidget * track_list_get_widget(track_list_t *); GtkWidget * track_list_get_menu(track_list_t *); bg_transcoder_track_t * track_list_get_track(track_list_t *); void track_list_prepend_track(track_list_t *, bg_transcoder_track_t *); void track_list_load(track_list_t * t, const char * filename); void track_list_save(track_list_t * t, const char * filename); void track_list_set_display_colors(track_list_t * t, float * fg, float * bg); void track_list_add_url(track_list_t * t, char * url); void track_list_add_albumentries_xml(track_list_t * t, char * xml_string); bg_parameter_info_t * track_list_get_parameters(track_list_t * t); void track_list_set_parameter(void * data, const char * name, const bg_parameter_value_t * val); int track_list_get_parameter(void * data, const char * name, bg_parameter_value_t * val); bg_plugin_handle_t * track_list_get_pp_plugin(track_list_t * t); GtkAccelGroup * track_list_get_accel_group(track_list_t * t); gmerlin-1.2.0~dfsg/apps/transcoder/Makefile.in0000644000175000017500000006205211764363423021263 0ustar alessioalessio# Makefile.in generated by automake 1.11.1 from Makefile.am. # @configure_input@ # Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, # 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation, # Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ VPATH = @srcdir@ pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ bin_PROGRAMS = gmerlin_transcoder$(EXEEXT) \ gmerlin_transcoder_remote$(EXEEXT) subdir = apps/transcoder DIST_COMMON = $(dist_man_MANS) $(noinst_HEADERS) $(srcdir)/Makefile.am \ $(srcdir)/Makefile.in ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/m4/check_funcs.m4 \ $(top_srcdir)/m4/gavl_simd.m4 $(top_srcdir)/m4/gettext.m4 \ $(top_srcdir)/m4/iconv.m4 $(top_srcdir)/m4/lib-ld.m4 \ $(top_srcdir)/m4/lib-link.m4 $(top_srcdir)/m4/lib-prefix.m4 \ $(top_srcdir)/m4/lqt_opt_cflags.m4 $(top_srcdir)/m4/nls.m4 \ $(top_srcdir)/m4/po.m4 $(top_srcdir)/m4/progtest.m4 \ $(top_srcdir)/acinclude.m4 $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/include/config.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = am__installdirs = "$(DESTDIR)$(bindir)" "$(DESTDIR)$(man1dir)" \ "$(DESTDIR)$(Desktopdir)" PROGRAMS = $(bin_PROGRAMS) am_gmerlin_transcoder_OBJECTS = ppwidget.$(OBJEXT) main.$(OBJEXT) \ transcoder_window.$(OBJEXT) trackdialog.$(OBJEXT) \ tracklist.$(OBJEXT) gmerlin_transcoder_OBJECTS = $(am_gmerlin_transcoder_OBJECTS) gmerlin_transcoder_DEPENDENCIES = \ $(top_builddir)/lib/gtk/libgmerlin_gtk.la \ $(top_builddir)/lib/libgmerlin.la am_gmerlin_transcoder_remote_OBJECTS = \ gmerlin_transcoder_remote.$(OBJEXT) gmerlin_transcoder_remote_OBJECTS = \ $(am_gmerlin_transcoder_remote_OBJECTS) gmerlin_transcoder_remote_DEPENDENCIES = \ $(top_builddir)/lib/libgmerlin.la DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)/include depcomp = $(SHELL) $(top_srcdir)/depcomp am__depfiles_maybe = depfiles am__mv = mv -f COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) LTCOMPILE = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \ --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) CCLD = $(CC) LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \ --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \ $(LDFLAGS) -o $@ SOURCES = $(gmerlin_transcoder_SOURCES) \ $(gmerlin_transcoder_remote_SOURCES) DIST_SOURCES = $(gmerlin_transcoder_SOURCES) \ $(gmerlin_transcoder_remote_SOURCES) am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; am__vpath_adj = case $$p in \ $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ *) f=$$p;; \ esac; am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; am__install_max = 40 am__nobase_strip_setup = \ srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` am__nobase_strip = \ for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" am__nobase_list = $(am__nobase_strip_setup); \ for p in $$list; do echo "$$p $$p"; done | \ sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ if (++n[$$2] == $(am__install_max)) \ { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ END { for (dir in files) print dir, files[dir] }' am__base_list = \ sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' man1dir = $(mandir)/man1 NROFF = nroff MANS = $(dist_man_MANS) DATA = $(Desktop_DATA) HEADERS = $(noinst_HEADERS) ETAGS = etags CTAGS = ctags DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ ALSA_CFLAGS = @ALSA_CFLAGS@ ALSA_LIBS = @ALSA_LIBS@ ALSA_REQUIRED = @ALSA_REQUIRED@ AMTAR = @AMTAR@ AR = @AR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ BG_VERSION = @BG_VERSION@ BG_VERSION_MAJOR = @BG_VERSION_MAJOR@ BG_VERSION_MICRO = @BG_VERSION_MICRO@ BG_VERSION_MINOR = @BG_VERSION_MINOR@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CDDB_CFLAGS = @CDDB_CFLAGS@ CDDB_LIBS = @CDDB_LIBS@ CDIO_CDDA_CFLAGS = @CDIO_CDDA_CFLAGS@ CDIO_CDDA_LIBS = @CDIO_CDDA_LIBS@ CDIO_CFLAGS = @CDIO_CFLAGS@ CDIO_LIBS = @CDIO_LIBS@ CDIO_PARANOIA_CFLAGS = @CDIO_PARANOIA_CFLAGS@ CDIO_PARANOIA_LIBS = @CDIO_PARANOIA_LIBS@ CDIO_REQUIRED = @CDIO_REQUIRED@ CFLAGS = @CFLAGS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CYGPATH_W = @CYGPATH_W@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DOXYGEN = @DOXYGEN@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ ESD_CFLAGS = @ESD_CFLAGS@ ESD_CONFIG = @ESD_CONFIG@ ESD_LIBS = @ESD_LIBS@ ESD_REQUIRED = @ESD_REQUIRED@ EXEEXT = @EXEEXT@ FGREP = @FGREP@ FONTCONFIG_CFLAGS = @FONTCONFIG_CFLAGS@ FONTCONFIG_LIBS = @FONTCONFIG_LIBS@ FREETYPE_CFLAGS = @FREETYPE_CFLAGS@ FREETYPE_LIBS = @FREETYPE_LIBS@ GAVL_CFLAGS = @GAVL_CFLAGS@ GAVL_LIBS = @GAVL_LIBS@ GAVL_REQUIRED = @GAVL_REQUIRED@ GLX_CFLAGS = @GLX_CFLAGS@ GLX_LIBS = @GLX_LIBS@ GL_CFLAGS = @GL_CFLAGS@ GL_LIBS = @GL_LIBS@ GMERLIN_DEP_LIBS = @GMERLIN_DEP_LIBS@ GMERLIN_PLUGIN_LDFLAGS = @GMERLIN_PLUGIN_LDFLAGS@ GMSGFMT = @GMSGFMT@ GMSGFMT_015 = @GMSGFMT_015@ GREP = @GREP@ GTK_CFLAGS = @GTK_CFLAGS@ GTK_LIBS = @GTK_LIBS@ GTK_REQUIRED = @GTK_REQUIRED@ ICONV_LIBS = @ICONV_LIBS@ INCLUDES = -I$(top_srcdir)/include INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ INTLLIBS = @INTLLIBS@ INTL_MACOSX_LIBS = @INTL_MACOSX_LIBS@ JACK_CFLAGS = @JACK_CFLAGS@ JACK_LIBS = @JACK_LIBS@ JACK_REQUIRED = @JACK_REQUIRED@ JPEG_CFLAGS = @JPEG_CFLAGS@ JPEG_LIBS = @JPEG_LIBS@ JPEG_REQUIRED = @JPEG_REQUIRED@ LD = @LD@ LDFLAGS = @LDFLAGS@ LIBCDDB_REQUIRED = @LIBCDDB_REQUIRED@ LIBEXIF_CFLAGS = @LIBEXIF_CFLAGS@ LIBEXIF_LIBS = @LIBEXIF_LIBS@ LIBICONV = @LIBICONV@ LIBINTL = @LIBINTL@ LIBM = @LIBM@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIPO = @LIPO@ LN_S = @LN_S@ LQT_CFLAGS = @LQT_CFLAGS@ LQT_LIBS = @LQT_LIBS@ LQT_REQUIRED = @LQT_REQUIRED@ LTLIBICONV = @LTLIBICONV@ LTLIBINTL = @LTLIBINTL@ LTLIBOBJS = @LTLIBOBJS@ LTVERSION_AGE = @LTVERSION_AGE@ LTVERSION_CURRENT = @LTVERSION_CURRENT@ LTVERSION_REVISION = @LTVERSION_REVISION@ LV_CFLAGS = @LV_CFLAGS@ LV_LIBS = @LV_LIBS@ LV_REQUIRED = @LV_REQUIRED@ MAKEINFO = @MAKEINFO@ MKDIR_P = @MKDIR_P@ MODULE_LIBADD = @MODULE_LIBADD@ MSGFMT = @MSGFMT@ MSGFMT_015 = @MSGFMT_015@ MSGMERGE = @MSGMERGE@ MUSICBRAINZ_CFLAGS = @MUSICBRAINZ_CFLAGS@ MUSICBRAINZ_LIBS = @MUSICBRAINZ_LIBS@ MUSICBRAINZ_REQUIRED = @MUSICBRAINZ_REQUIRED@ NM = @NM@ NMEDIT = @NMEDIT@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OTOOL = @OTOOL@ OTOOL64 = @OTOOL64@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PKG_CONFIG = @PKG_CONFIG@ PNG_CFLAGS = @PNG_CFLAGS@ PNG_LIBS = @PNG_LIBS@ PNG_REQUIRED = @PNG_REQUIRED@ POSUB = @POSUB@ PULSEAUDIO_CFLAGS = @PULSEAUDIO_CFLAGS@ PULSEAUDIO_LIBS = @PULSEAUDIO_LIBS@ PULSEAUDIO_REQUIRED = @PULSEAUDIO_REQUIRED@ RANLIB = @RANLIB@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ SQLITE3_LIBS = @SQLITE3_LIBS@ STRIP = @STRIP@ TEXINFO = @TEXINFO@ TIFF_CFLAGS = @TIFF_CFLAGS@ TIFF_LIBS = @TIFF_LIBS@ TIFF_REQUIRED = @TIFF_REQUIRED@ TOP_SRCDIR = @TOP_SRCDIR@ USE_NLS = @USE_NLS@ V4LCONVERT_CFLAGS = @V4LCONVERT_CFLAGS@ V4LCONVERT_LIBS = @V4LCONVERT_LIBS@ V4LCONVERT_REQUIRED = @V4LCONVERT_REQUIRED@ VERSION = @VERSION@ XDPMS_LIBS = @XDPMS_LIBS@ XFIXES_LIBS = @XFIXES_LIBS@ XGETTEXT = @XGETTEXT@ XGETTEXT_015 = @XGETTEXT_015@ XINERAMA_LIBS = @XINERAMA_LIBS@ XMKMF = @XMKMF@ XML2_CFLAGS = @XML2_CFLAGS@ XML2_LIBS = @XML2_LIBS@ XML2_REQUIRED = @XML2_REQUIRED@ XTEST_LIBS = @XTEST_LIBS@ XV_LIBS = @XV_LIBS@ X_CFLAGS = @X_CFLAGS@ X_LIBS = @X_LIBS@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_CC = @ac_ct_CC@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_vendor = @build_vendor@ builddir = @builddir@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ lt_ECHO = @lt_ECHO@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ plugindir = $(pkglibdir)/plugins AM_CFLAGS = \ @XML2_CFLAGS@ \ @GTK_CFLAGS@ \ -DLOCALE_DIR=\"$(localedir)\" \ -DPLUGIN_DIR=\"$(plugindir)\" \ -DDOC_DIR=\"$(docdir)\" \ -DDATA_DIR=\"$(pkgdatadir)\" Desktopdir = $(datadir)/applications Desktop_DATA = gmerlin-transcoder.desktop dist_man_MANS = gmerlin_transcoder.1 gmerlin_transcoder_remote.1 gmerlin_transcoder_SOURCES = \ ppwidget.c \ main.c \ transcoder_window.c \ trackdialog.c \ tracklist.c gmerlin_transcoder_remote_SOURCES = gmerlin_transcoder_remote.c gmerlin_transcoder_LDADD = \ $(top_builddir)/lib/gtk/libgmerlin_gtk.la \ $(top_builddir)/lib/libgmerlin.la gmerlin_transcoder_remote_LDADD = \ $(top_builddir)/lib/libgmerlin.la noinst_HEADERS = \ ppwidget.h \ transcoder_remote.h \ transcoder_window.h \ tracklist.h \ trackdialog.h EXTRA_DIST = gmerlin-transcoder.desktop all: all-am .SUFFIXES: .SUFFIXES: .c .lo .o .obj $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ && { if test -f $@; then exit 0; else break; fi; }; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu apps/transcoder/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --gnu apps/transcoder/Makefile .PRECIOUS: Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): install-binPROGRAMS: $(bin_PROGRAMS) @$(NORMAL_INSTALL) test -z "$(bindir)" || $(MKDIR_P) "$(DESTDIR)$(bindir)" @list='$(bin_PROGRAMS)'; test -n "$(bindir)" || list=; \ for p in $$list; do echo "$$p $$p"; done | \ sed 's/$(EXEEXT)$$//' | \ while read p p1; do if test -f $$p || test -f $$p1; \ then echo "$$p"; echo "$$p"; else :; fi; \ done | \ sed -e 'p;s,.*/,,;n;h' -e 's|.*|.|' \ -e 'p;x;s,.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/' | \ sed 'N;N;N;s,\n, ,g' | \ $(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1 } \ { d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \ if ($$2 == $$4) files[d] = files[d] " " $$1; \ else { print "f", $$3 "/" $$4, $$1; } } \ END { for (d in files) print "f", d, files[d] }' | \ while read type dir files; do \ if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \ test -z "$$files" || { \ echo " $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files '$(DESTDIR)$(bindir)$$dir'"; \ $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files "$(DESTDIR)$(bindir)$$dir" || exit $$?; \ } \ ; done uninstall-binPROGRAMS: @$(NORMAL_UNINSTALL) @list='$(bin_PROGRAMS)'; test -n "$(bindir)" || list=; \ files=`for p in $$list; do echo "$$p"; done | \ sed -e 'h;s,^.*/,,;s/$(EXEEXT)$$//;$(transform)' \ -e 's/$$/$(EXEEXT)/' `; \ test -n "$$list" || exit 0; \ echo " ( cd '$(DESTDIR)$(bindir)' && rm -f" $$files ")"; \ cd "$(DESTDIR)$(bindir)" && rm -f $$files clean-binPROGRAMS: @list='$(bin_PROGRAMS)'; test -n "$$list" || exit 0; \ echo " rm -f" $$list; \ rm -f $$list || exit $$?; \ test -n "$(EXEEXT)" || exit 0; \ list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ echo " rm -f" $$list; \ rm -f $$list gmerlin_transcoder$(EXEEXT): $(gmerlin_transcoder_OBJECTS) $(gmerlin_transcoder_DEPENDENCIES) @rm -f gmerlin_transcoder$(EXEEXT) $(LINK) $(gmerlin_transcoder_OBJECTS) $(gmerlin_transcoder_LDADD) $(LIBS) gmerlin_transcoder_remote$(EXEEXT): $(gmerlin_transcoder_remote_OBJECTS) $(gmerlin_transcoder_remote_DEPENDENCIES) @rm -f gmerlin_transcoder_remote$(EXEEXT) $(LINK) $(gmerlin_transcoder_remote_OBJECTS) $(gmerlin_transcoder_remote_LDADD) $(LIBS) mostlyclean-compile: -rm -f *.$(OBJEXT) distclean-compile: -rm -f *.tab.c @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gmerlin_transcoder_remote.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/main.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ppwidget.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/trackdialog.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tracklist.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/transcoder_window.Po@am__quote@ .c.o: @am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(COMPILE) -c $< .c.obj: @am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(COMPILE) -c `$(CYGPATH_W) '$<'` .c.lo: @am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(LTCOMPILE) -c -o $@ $< mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs install-man1: $(dist_man_MANS) @$(NORMAL_INSTALL) test -z "$(man1dir)" || $(MKDIR_P) "$(DESTDIR)$(man1dir)" @list=''; test -n "$(man1dir)" || exit 0; \ { for i in $$list; do echo "$$i"; done; \ l2='$(dist_man_MANS)'; for i in $$l2; do echo "$$i"; done | \ sed -n '/\.1[a-z]*$$/p'; \ } | while read p; do \ if test -f $$p; then d=; else d="$(srcdir)/"; fi; \ echo "$$d$$p"; echo "$$p"; \ done | \ sed -e 'n;s,.*/,,;p;h;s,.*\.,,;s,^[^1][0-9a-z]*$$,1,;x' \ -e 's,\.[0-9a-z]*$$,,;$(transform);G;s,\n,.,' | \ sed 'N;N;s,\n, ,g' | { \ list=; while read file base inst; do \ if test "$$base" = "$$inst"; then list="$$list $$file"; else \ echo " $(INSTALL_DATA) '$$file' '$(DESTDIR)$(man1dir)/$$inst'"; \ $(INSTALL_DATA) "$$file" "$(DESTDIR)$(man1dir)/$$inst" || exit $$?; \ fi; \ done; \ for i in $$list; do echo "$$i"; done | $(am__base_list) | \ while read files; do \ test -z "$$files" || { \ echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(man1dir)'"; \ $(INSTALL_DATA) $$files "$(DESTDIR)$(man1dir)" || exit $$?; }; \ done; } uninstall-man1: @$(NORMAL_UNINSTALL) @list=''; test -n "$(man1dir)" || exit 0; \ files=`{ for i in $$list; do echo "$$i"; done; \ l2='$(dist_man_MANS)'; for i in $$l2; do echo "$$i"; done | \ sed -n '/\.1[a-z]*$$/p'; \ } | sed -e 's,.*/,,;h;s,.*\.,,;s,^[^1][0-9a-z]*$$,1,;x' \ -e 's,\.[0-9a-z]*$$,,;$(transform);G;s,\n,.,'`; \ test -z "$$files" || { \ echo " ( cd '$(DESTDIR)$(man1dir)' && rm -f" $$files ")"; \ cd "$(DESTDIR)$(man1dir)" && rm -f $$files; } install-DesktopDATA: $(Desktop_DATA) @$(NORMAL_INSTALL) test -z "$(Desktopdir)" || $(MKDIR_P) "$(DESTDIR)$(Desktopdir)" @list='$(Desktop_DATA)'; test -n "$(Desktopdir)" || list=; \ for p in $$list; do \ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ echo "$$d$$p"; \ done | $(am__base_list) | \ while read files; do \ echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(Desktopdir)'"; \ $(INSTALL_DATA) $$files "$(DESTDIR)$(Desktopdir)" || exit $$?; \ done uninstall-DesktopDATA: @$(NORMAL_UNINSTALL) @list='$(Desktop_DATA)'; test -n "$(Desktopdir)" || list=; \ files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ test -n "$$files" || exit 0; \ echo " ( cd '$(DESTDIR)$(Desktopdir)' && rm -f" $$files ")"; \ cd "$(DESTDIR)$(Desktopdir)" && rm -f $$files ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | \ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in files) print i; }; }'`; \ mkid -fID $$unique tags: TAGS TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ $(TAGS_FILES) $(LISP) set x; \ here=`pwd`; \ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | \ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in files) print i; }; }'`; \ shift; \ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ test -n "$$unique" || unique=$$empty_fix; \ if test $$# -gt 0; then \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ "$$@" $$unique; \ else \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ $$unique; \ fi; \ fi ctags: CTAGS CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ $(TAGS_FILES) $(LISP) list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | \ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in files) print i; }; }'`; \ test -z "$(CTAGS_ARGS)$$unique" \ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ $$unique GTAGS: here=`$(am__cd) $(top_builddir) && pwd` \ && $(am__cd) $(top_srcdir) \ && gtags -i $(GTAGS_ARGS) "$$here" distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags distdir: $(DISTFILES) @list='$(MANS)'; if test -n "$$list"; then \ list=`for p in $$list; do \ if test -f $$p; then d=; else d="$(srcdir)/"; fi; \ if test -f "$$d$$p"; then echo "$$d$$p"; else :; fi; done`; \ if test -n "$$list" && \ grep 'ab help2man is required to generate this page' $$list >/dev/null; then \ echo "error: found man pages containing the \`missing help2man' replacement text:" >&2; \ grep -l 'ab help2man is required to generate this page' $$list | sed 's/^/ /' >&2; \ echo " to fix them, install help2man, remove and regenerate the man pages;" >&2; \ echo " typically \`make maintainer-clean' will remove them" >&2; \ exit 1; \ else :; fi; \ else :; fi @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done check-am: all-am check: check-am all-am: Makefile $(PROGRAMS) $(MANS) $(DATA) $(HEADERS) installdirs: for dir in "$(DESTDIR)$(bindir)" "$(DESTDIR)$(man1dir)" "$(DESTDIR)$(Desktopdir)"; do \ test -z "$$dir" || $(MKDIR_P) "$$dir"; \ done install: install-am install-exec: install-exec-am install-data: install-data-am uninstall: uninstall-am install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-am install-strip: $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ `test -z '$(STRIP)' || \ echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install mostlyclean-generic: clean-generic: distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." clean: clean-am clean-am: clean-binPROGRAMS clean-generic clean-libtool mostlyclean-am distclean: distclean-am -rm -rf ./$(DEPDIR) -rm -f Makefile distclean-am: clean-am distclean-compile distclean-generic \ distclean-tags dvi: dvi-am dvi-am: html: html-am html-am: info: info-am info-am: install-data-am: install-DesktopDATA install-man install-dvi: install-dvi-am install-dvi-am: install-exec-am: install-binPROGRAMS install-html: install-html-am install-html-am: install-info: install-info-am install-info-am: install-man: install-man1 install-pdf: install-pdf-am install-pdf-am: install-ps: install-ps-am install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-am -rm -rf ./$(DEPDIR) -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-compile mostlyclean-generic \ mostlyclean-libtool pdf: pdf-am pdf-am: ps: ps-am ps-am: uninstall-am: uninstall-DesktopDATA uninstall-binPROGRAMS \ uninstall-man uninstall-man: uninstall-man1 .MAKE: install-am install-strip .PHONY: CTAGS GTAGS all all-am check check-am clean clean-binPROGRAMS \ clean-generic clean-libtool ctags distclean distclean-compile \ distclean-generic distclean-libtool distclean-tags distdir dvi \ dvi-am html html-am info info-am install install-DesktopDATA \ install-am install-binPROGRAMS install-data install-data-am \ install-dvi install-dvi-am install-exec install-exec-am \ install-html install-html-am install-info install-info-am \ install-man install-man1 install-pdf install-pdf-am install-ps \ install-ps-am install-strip installcheck installcheck-am \ installdirs maintainer-clean maintainer-clean-generic \ mostlyclean mostlyclean-compile mostlyclean-generic \ mostlyclean-libtool pdf pdf-am ps ps-am tags uninstall \ uninstall-DesktopDATA uninstall-am uninstall-binPROGRAMS \ uninstall-man uninstall-man1 # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: gmerlin-1.2.0~dfsg/apps/transcoder/transcoder_window.h0000644000175000017500000000270711764363402023120 0ustar alessioalessio/***************************************************************** * gmerlin - a general purpose multimedia framework and applications * * Copyright (c) 2001 - 2011 Members of the Gmerlin project * gmerlin-general@lists.sourceforge.net * http://gmerlin.sourceforge.net * * 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 of the License, 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 this program. If not, see . * *****************************************************************/ typedef struct transcoder_window_s transcoder_window_t; transcoder_window_t * transcoder_window_create(); void transcoder_window_destroy(transcoder_window_t*); void transcoder_window_run(transcoder_window_t *); transcoder_window_t * transcoder_window_create(); void transcoder_window_destroy(transcoder_window_t*); void transcoder_window_run(transcoder_window_t *); void transcoder_window_load_profile(transcoder_window_t *, const char * file); gmerlin-1.2.0~dfsg/apps/visualizer/0000755000175000017500000000000011764363443017244 5ustar alessioalessiogmerlin-1.2.0~dfsg/apps/visualizer/Makefile.am0000644000175000017500000000104111764363403021270 0ustar alessioalessioplugindir=$(pkglibdir)/plugins INCLUDES = -I$(top_srcdir)/include AM_CFLAGS = \ @XML2_CFLAGS@ \ @GTK_CFLAGS@ \ -DLOCALE_DIR=\"$(localedir)\" \ -DPLUGIN_DIR=\"$(plugindir)\" \ -DDOC_DIR=\"$(docdir)\" \ -DDATA_DIR=\"$(pkgdatadir)\" Desktopdir = $(datadir)/applications Desktop_DATA = gmerlin-visualizer.desktop bin_PROGRAMS = gmerlin_visualizer gmerlin_visualizer_SOURCES = \ gmerlin_visualizer.c gmerlin_visualizer_LDADD = $(top_builddir)/lib/libgmerlin.la $(top_builddir)/lib/gtk/libgmerlin_gtk.la EXTRA_DIST = gmerlin-visualizer.desktop gmerlin-1.2.0~dfsg/apps/visualizer/gmerlin_visualizer.c0000644000175000017500000010625111764363403023323 0ustar alessioalessio/***************************************************************** * gmerlin - a general purpose multimedia framework and applications * * Copyright (c) 2001 - 2011 Members of the Gmerlin project * gmerlin-general@lists.sourceforge.net * http://gmerlin.sourceforge.net * * 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 of the License, 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 this program. If not, see . * *****************************************************************/ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #define LOG_DOMAIN "gmerlin_visualizer" #define TOOLBAR_TRIGGER_KEY (1<<0) #define TOOLBAR_TRIGGER_MOUSE (1<<1) #define TOOLBAR_LOCATION_TOP 0 #define TOOLBAR_LOCATION_BOTTOM 1 extern void gtk_decorated_window_move_resize_window(GtkWindow*, int, int, int, int); typedef struct { GtkWidget * window; GtkWidget * box; GtkWidget * socket; } window_t; typedef struct { GtkWidget * window; bg_gtk_plugin_widget_single_t * ra_plugins; bg_gtk_plugin_widget_single_t * ov_plugins; GtkWidget * close_button; } plugin_window_t; typedef struct { GtkWidget * config_button; GtkWidget * quit_button; GtkWidget * plugin_button; GtkWidget * restart_button; GtkWidget * log_button; GtkWidget * about_button; GtkWidget * help_button; guint log_id; guint about_id; GtkWidget * fullscreen_button; GtkWidget * nofullscreen_button; GtkWidget * toolbar; /* A GtkEventBox actually... */ GtkWidget * fps; bg_gtk_plugin_widget_single_t * vis_plugins; /* Windows are created by gtk and the x11 plugin is embedded inside after */ window_t normal_window; window_t fullscreen_window; window_t *current_window; plugin_window_t plugin_window; bg_gtk_vumeter_t * vumeter; /* Core stuff */ gavl_audio_frame_t * audio_frame; gavl_audio_format_t audio_format; bg_visualizer_t * visualizer; bg_plugin_registry_t * plugin_reg; bg_cfg_registry_t * cfg_reg; bg_plugin_handle_t * ra_handle; bg_recorder_plugin_t * ra_plugin; const bg_plugin_info_t * ov_info; const bg_plugin_info_t * ra_info; /* Config stuff */ // bg_cfg_section_t * vumeter_section; bg_cfg_section_t * visualizer_section; bg_cfg_section_t * general_section; bg_cfg_section_t * log_section; bg_dialog_t * cfg_dialog; int audio_open; int vis_open; int mouse_in_toolbar; int do_hide_toolbar; int toolbar_visible; int toolbar_location; int toolbar_trigger; int x, y, width, height; bg_gtk_log_window_t * log_window; bg_ov_callbacks_t cb; } visualizer_t; static gboolean configure_callback(GtkWidget * w, GdkEventConfigure *event, gpointer data) { visualizer_t * win; win = (visualizer_t*)data; win->x = event->x; win->y = event->y; win->width = event->width; win->height = event->height; gdk_window_get_root_origin(win->current_window->window->window, &win->x, &win->y); return FALSE; } static char * get_display_string(visualizer_t * v) { char * ret; GdkDisplay * dpy; /* Get the display string */ gtk_widget_realize(v->normal_window.socket); gtk_widget_realize(v->fullscreen_window.socket); dpy = gdk_display_get_default(); // ret = bg_sprintf("%s:%08lx:%08lx", gdk_display_get_name(dpy), // GDK_WINDOW_XID(v->normal_window.window->window), // GDK_WINDOW_XID(v->fullscreen_window.window->window)); ret = bg_sprintf("%s:%08lx:%08lx", gdk_display_get_name(dpy), (long unsigned int)gtk_socket_get_id(GTK_SOCKET(v->normal_window.socket)), (long unsigned int)gtk_socket_get_id(GTK_SOCKET(v->fullscreen_window.socket))); return ret; } static void hide_toolbar(visualizer_t * v) { gtk_widget_hide(v->toolbar); v->toolbar_visible = 0; } static gboolean toolbar_timeout(void * data) { visualizer_t * v; v = (visualizer_t *)data; if(!v->toolbar_visible) return TRUE; /* Maybe the toolbar will be hidden next time */ if(!v->do_hide_toolbar) { v->do_hide_toolbar = 1; return TRUE; } if(!v->mouse_in_toolbar) { hide_toolbar(v); } return TRUE; } static gboolean fps_timeout(void * data) { float fps; char * tmp_string; visualizer_t * v; v = (visualizer_t *)data; if(!v->toolbar_visible || !v->audio_open) return TRUE; fps = bg_visualizer_get_fps(v->visualizer); if(fps >= 0.0) { tmp_string = bg_sprintf("Fps: %.2f", fps); gtk_label_set_text(GTK_LABEL(v->fps), tmp_string); free(tmp_string); } return TRUE; } static void show_toolbar(visualizer_t * v) { if(!v->toolbar_visible) { gtk_widget_show(v->toolbar); v->toolbar_visible = 1; } v->do_hide_toolbar = 0; } static void attach_toolbar(visualizer_t * v, window_t * win) { if(v->toolbar_location == TOOLBAR_LOCATION_TOP) gtk_box_pack_start(GTK_BOX(win->box), v->toolbar, FALSE, FALSE, 0); else gtk_box_pack_end(GTK_BOX(win->box), v->toolbar, FALSE, FALSE, 0); } static void toggle_fullscreen(visualizer_t * v) { if(v->current_window == &v->normal_window) { /* Reparent toolbar */ gtk_container_remove(GTK_CONTAINER(v->normal_window.box), v->toolbar); attach_toolbar(v, &v->fullscreen_window); /* Hide normal window, show fullscreen window */ gtk_widget_show(v->fullscreen_window.window); gtk_widget_hide(v->normal_window.window); gtk_window_fullscreen(GTK_WINDOW(v->fullscreen_window.window)); /* Update toolbar */ gtk_widget_show(v->nofullscreen_button); gtk_widget_hide(v->fullscreen_button); gtk_widget_hide(v->config_button); gtk_widget_hide(v->plugin_button); bg_gtk_plugin_widget_single_show_buttons(v->vis_plugins, 0); v->current_window = &v->fullscreen_window; } else { /* Reparent toolbar */ gtk_container_remove(GTK_CONTAINER(v->fullscreen_window.box), v->toolbar); attach_toolbar(v, &v->normal_window); /* Hide normal window, show fullscreen window */ gtk_widget_show(v->normal_window.window); gtk_widget_hide(v->fullscreen_window.window); /* Update toolbar */ gtk_widget_show(v->fullscreen_button); gtk_widget_hide(v->nofullscreen_button); gtk_widget_show(v->config_button); gtk_widget_show(v->plugin_button); bg_gtk_plugin_widget_single_show_buttons(v->vis_plugins, 1); v->current_window = &v->normal_window; } hide_toolbar(v); v->mouse_in_toolbar = 0; } static void open_audio(visualizer_t * v) { int i; int was_open; gavl_time_t delay_time = GAVL_TIME_SCALE / 20; /* 50 ms */ memset(&v->audio_format, 0, sizeof(v->audio_format)); v->audio_format.num_channels = 2; v->audio_format.samplerate = 44100; v->audio_format.sample_format = GAVL_SAMPLE_S16; gavl_set_channel_setup(&v->audio_format); if(v->audio_frame) { gavl_audio_frame_destroy(v->audio_frame); v->ra_plugin->close(v->ra_handle->priv); v->audio_frame = NULL; bg_plugin_unref(v->ra_handle); was_open = 1; } else was_open = 0; v->audio_open = 0; v->ra_handle = bg_plugin_load(v->plugin_reg, v->ra_info); v->ra_plugin = (bg_recorder_plugin_t*)(v->ra_handle->plugin); /* The soundcard might be busy from last time, give the kernel some time to free the device */ if(!v->ra_plugin->open(v->ra_handle->priv, &v->audio_format, NULL)) { if(!was_open) { bg_log(BG_LOG_ERROR, LOG_DOMAIN, "Opening audio device failed, fix settings and click restart"); gtk_label_set_text(GTK_LABEL(v->fps), TR("No audio")); return; } for(i = 0; i < 20; i++) { gavl_time_delay(&delay_time); if(v->ra_plugin->open(v->ra_handle->priv, &v->audio_format, NULL)) { v->audio_open = 1; break; } } } else v->audio_open = 1; if(v->audio_open) { v->audio_frame = gavl_audio_frame_create(&v->audio_format); bg_gtk_vumeter_set_format(v->vumeter, &v->audio_format); } else { bg_log(BG_LOG_ERROR, LOG_DOMAIN, "Opening audio device failed, fix settings and click restart"); gtk_label_set_text(GTK_LABEL(v->fps), TR("No audio")); } } static void open_vis(visualizer_t * v) { char * display_string = get_display_string(v); bg_visualizer_open_id(v->visualizer, &v->audio_format, v->ov_info, display_string); free(display_string); v->vis_open = 1; } static void close_vis(visualizer_t * v) { bg_visualizer_close(v->visualizer); v->vis_open = 0; } static void grab_notify_callback(GtkWidget *widget, gboolean was_grabbed, gpointer data) { visualizer_t * win = (visualizer_t*)data; if(!was_grabbed) { bg_gtk_widget_set_can_focus(win->current_window->socket, TRUE); gtk_widget_grab_focus(win->current_window->socket); } } static void about_window_close_callback(bg_gtk_about_window_t* win, void* data) { visualizer_t * v; v = (visualizer_t*)data; gtk_widget_set_sensitive(v->about_button, 1); } static void button_callback(GtkWidget * w, gpointer data) { visualizer_t * win = (visualizer_t*)data; if((w == win->quit_button) || (w == win->normal_window.window)) gtk_main_quit(); else if(w == win->config_button) bg_dialog_show(win->cfg_dialog, win->current_window->window); else if((w == win->fullscreen_button) || (w == win->nofullscreen_button)) toggle_fullscreen(win); else if(w == win->plugin_button) { gtk_widget_show(win->plugin_window.window); gtk_widget_set_sensitive(win->plugin_button, 0); } else if(w == win->restart_button) { if(win->vis_open) { close_vis(win); open_audio(win); open_vis(win); hide_toolbar(win); } } else if(w == win->log_button) { gtk_widget_set_sensitive(win->log_button, 0); bg_gtk_log_window_show(win->log_window); } else if(w == win->about_button) { gtk_widget_set_sensitive(win->about_button, 0); bg_gtk_about_window_create("Gmerlin visualizer", VERSION, "visualizer_icon.png", about_window_close_callback, win); } else if(w == win->help_button) bg_display_html_help("userguide/Visualizer.html"); } static gboolean plug_removed_callback(GtkWidget * w, gpointer data) { /* Reuse socket */ return TRUE; } static void plug_added_callback(GtkWidget * w, gpointer data) { visualizer_t * v; v = (visualizer_t *)data; gtk_widget_hide(v->toolbar); /* Seems that this is switched off, when an earlier client exited */ bg_gtk_widget_set_can_focus(w, TRUE); gtk_widget_grab_focus(w); } static gboolean delete_callback(GtkWidget * w, GdkEventAny * evt, gpointer data) { button_callback(w, data); return TRUE; } static void plugin_window_button_callback(GtkWidget * w, gpointer data) { visualizer_t * v; v = (visualizer_t *)data; gtk_widget_set_sensitive(v->plugin_button, 1); gtk_widget_hide(v->plugin_window.window); } static gboolean plugin_window_delete_callback(GtkWidget * w, GdkEventAny * evt, gpointer data) { plugin_window_button_callback(w, data); return TRUE; } static void set_ra_plugin(const bg_plugin_info_t * plugin, void * data) { visualizer_t * v = (visualizer_t*)data; bg_plugin_registry_set_default(v->plugin_reg, BG_PLUGIN_RECORDER_AUDIO, BG_PLUGIN_RECORDER, plugin->name); v->ra_info = plugin; bg_log(BG_LOG_INFO, LOG_DOMAIN, "Changed recording plugin to %s", v->ra_info->long_name); close_vis(v); open_audio(v); open_vis(v); } static void plugin_window_init(plugin_window_t * win, visualizer_t * v) { int row = 0, num_columns = 4; GtkWidget * table; win->window = gtk_window_new(GTK_WINDOW_TOPLEVEL); gtk_window_set_modal(GTK_WINDOW(win->window), TRUE); gtk_window_set_transient_for(GTK_WINDOW(win->window), GTK_WINDOW(v->normal_window.window)); win->ra_plugins = bg_gtk_plugin_widget_single_create(TR("Audio recorder"), v->plugin_reg, BG_PLUGIN_RECORDER_AUDIO, BG_PLUGIN_ALL); bg_gtk_plugin_widget_single_set_change_callback(win->ra_plugins, set_ra_plugin, v); win->ov_plugins = bg_gtk_plugin_widget_single_create(TR("Video output"), v->plugin_reg, BG_PLUGIN_OUTPUT_VIDEO, BG_PLUGIN_ALL); win->close_button = gtk_button_new_from_stock(GTK_STOCK_CLOSE); g_signal_connect(win->close_button, "clicked", G_CALLBACK(plugin_window_button_callback), v); g_signal_connect(win->window, "delete-event", G_CALLBACK(plugin_window_delete_callback), v); gtk_widget_show(win->close_button); table = gtk_table_new(3, num_columns, 0); gtk_table_set_row_spacings(GTK_TABLE(table), 5); gtk_table_set_col_spacings(GTK_TABLE(table), 5); gtk_container_set_border_width(GTK_CONTAINER(table), 5); gtk_window_set_position(GTK_WINDOW(win->window), GTK_WIN_POS_CENTER); bg_gtk_plugin_widget_single_attach(win->ra_plugins, table, &row, &num_columns); bg_gtk_plugin_widget_single_attach(win->ov_plugins, table, &row, &num_columns); gtk_table_attach(GTK_TABLE(table), win->close_button, 0, num_columns, row, row+1, GTK_SHRINK, GTK_SHRINK, 0, 0); gtk_widget_show(table); gtk_container_add(GTK_CONTAINER(win->window), table); } static int motion_callback(void * data, int x, int y, int mask) { visualizer_t * v = (visualizer_t*)data; if(v->toolbar_trigger & TOOLBAR_TRIGGER_MOUSE) show_toolbar(v); return FALSE; } static gboolean key_callback(GtkWidget * w, GdkEventKey * evt, gpointer data) { visualizer_t * v = (visualizer_t*)data; // gtk_widget_show(v->toolbar); // g_timeout_add(2000, toolbar_timeout, v); switch(evt->keyval) { case GDK_Tab: case GDK_f: toggle_fullscreen(v); return TRUE; break; case GDK_Escape: if(v->current_window == &v->fullscreen_window) toggle_fullscreen(v); return TRUE; break; case GDK_Menu: if(v->toolbar_trigger & TOOLBAR_TRIGGER_KEY) show_toolbar(v); return TRUE; break; } return FALSE; } static gboolean window_motion_callback(GtkWidget *widget, GdkEventMotion *event, gpointer data) { visualizer_t * v = (visualizer_t*)data; if(v->toolbar_trigger & TOOLBAR_TRIGGER_MOUSE) show_toolbar(v); return FALSE; } static void window_init(visualizer_t * v, window_t * w, int fullscreen) { GtkWidget * table; w->window = bg_gtk_window_new(GTK_WINDOW_TOPLEVEL); if(!fullscreen) g_signal_connect(G_OBJECT(w->window), "configure-event", G_CALLBACK(configure_callback), (gpointer)v); gtk_window_set_title(GTK_WINDOW(w->window), "Gmerlin visualizer"); w->socket = gtk_socket_new(); w->box = gtk_vbox_new(0, 0); gtk_widget_show(w->box); table = gtk_table_new(1, 1, 0); gtk_table_attach_defaults(GTK_TABLE(table),w->socket, 0, 1, 0, 1); gtk_table_attach_defaults(GTK_TABLE(table),w->box, 0, 1, 0, 1); gtk_widget_show(table); gtk_widget_set_events(w->window, GDK_POINTER_MOTION_MASK); gtk_widget_set_events(w->socket, GDK_KEY_PRESS_MASK | GDK_BUTTON_PRESS_MASK ); // gtk_window_set_focus_on_map(w->window, 0); gtk_container_add(GTK_CONTAINER(w->window), table); g_signal_connect(G_OBJECT(w->window), "delete_event", G_CALLBACK(delete_callback), v); g_signal_connect(G_OBJECT(w->socket), "plug-removed", G_CALLBACK(plug_removed_callback), v); g_signal_connect(G_OBJECT(w->socket), "grab-notify", G_CALLBACK(grab_notify_callback), v); g_signal_connect(G_OBJECT(w->socket), "plug-added", G_CALLBACK(plug_added_callback), v); g_signal_connect(G_OBJECT(w->socket), "key-press-event", G_CALLBACK(key_callback), v); g_signal_connect(G_OBJECT(w->window), "motion-notify-event", G_CALLBACK(window_motion_callback), v); gtk_widget_show(w->socket); if(fullscreen) gtk_window_fullscreen(GTK_WINDOW(w->window)); // else // gtk_widget_set_size_request(w->window, 640, 480); } static GtkWidget * create_pixmap_button(visualizer_t * w, const char * filename, const char * tooltip) { GtkWidget * button; GtkWidget * image; char * path; path = bg_search_file_read("icons", filename); if(path) { image = gtk_image_new_from_file(path); free(path); } else image = gtk_image_new(); gtk_widget_show(image); button = gtk_button_new(); gtk_container_add(GTK_CONTAINER(button), image); g_signal_connect(G_OBJECT(button), "clicked", G_CALLBACK(button_callback), w); gtk_widget_show(button); bg_gtk_tooltips_set_tip(button, tooltip, PACKAGE); return button; } #if 0 static GtkWidget * create_pixmap_toggle_button(visualizer_t * w, const char * filename, const char * tooltip, guint * id) { GtkWidget * button; GtkWidget * image; char * path; path = bg_search_file_read("icons", filename); if(path) { image = gtk_image_new_from_file(path); free(path); } else image = gtk_image_new(); gtk_widget_show(image); button = gtk_toggle_button_new(); gtk_container_add(GTK_CONTAINER(button), image); *id = g_signal_connect(G_OBJECT(button), "toggled", G_CALLBACK(button_callback), w); gtk_widget_show(button); bg_gtk_tooltips_set_tip(button, tooltip, PACKAGE); return button; } #endif static void set_vis_param(void * data, const char * name, const bg_parameter_value_t * val) { visualizer_t * v; v = (visualizer_t *)data; bg_visualizer_set_parameter(v->visualizer, name, val); if(bg_visualizer_need_restart(v->visualizer) && v->vis_open && !name) { gtk_widget_hide(v->toolbar); close_vis(v); open_vis(v); } } static void set_general_parameter(void * data, const char * name, const bg_parameter_value_t * val) { visualizer_t * v; int i_tmp; v = (visualizer_t *)data; if(!name) return; if(!strcmp(name, "toolbar_location")) { if(!strcmp(val->val_str, "top")) i_tmp = TOOLBAR_LOCATION_TOP; else i_tmp = TOOLBAR_LOCATION_BOTTOM; if(v->toolbar_location != i_tmp) { v->toolbar_location = i_tmp; /* Reparent toolbar */ gtk_container_remove(GTK_CONTAINER(v->current_window->box), v->toolbar); attach_toolbar(v, v->current_window); } } else if(!strcmp(name, "toolbar_trigger")) { if(!strcmp(val->val_str, "mouse")) { v->toolbar_trigger = TOOLBAR_TRIGGER_MOUSE; } else if(!strcmp(val->val_str, "key")) { v->toolbar_trigger = TOOLBAR_TRIGGER_KEY; } else if(!strcmp(val->val_str, "mousekey")) { v->toolbar_trigger = TOOLBAR_TRIGGER_MOUSE | TOOLBAR_TRIGGER_KEY; } } else if(!strcmp(name, "x")) v->x = val->val_i; else if(!strcmp(name, "y")) v->y = val->val_i; else if(!strcmp(name, "width")) v->width = val->val_i; else if(!strcmp(name, "height")) v->height = val->val_i; } static int get_general_parameter(void * data, const char * name, bg_parameter_value_t * val) { visualizer_t * v; v = (visualizer_t *)data; if(!strcmp(name, "x")) { val->val_i = v->x; return 1; } else if(!strcmp(name, "y")) { val->val_i = v->y; return 1; } else if(!strcmp(name, "width")) { val->val_i = v->width; return 1; } else if(!strcmp(name, "height")) { val->val_i = v->height; return 1; } return 0; } bg_parameter_info_t parameters[] = { { .name = "toolbar_location", .long_name = "Toolbar location", .type = BG_PARAMETER_STRINGLIST, .flags = BG_PARAMETER_SYNC, .val_default = { .val_str = "top" }, .multi_names = (char const *[]){ "top", "bottom", NULL }, .multi_labels = (char const *[]){ "Top", "Bottom", NULL }, }, { .name = "toolbar_trigger", .long_name = "Toolbar trigger", .type = BG_PARAMETER_STRINGLIST, .val_default = { .val_str = "mousekey" }, .multi_names = (char const *[]){ "mouse", "key", "mousekey", NULL }, .multi_labels = (char const *[]){ "Mouse motion", "Menu key", "Mouse motion & Menu key", NULL }, }, { .name = "x", .long_name = "X", .type = BG_PARAMETER_INT, .flags = BG_PARAMETER_HIDE_DIALOG, }, { .name = "y", .long_name = "y", .type = BG_PARAMETER_INT, .flags = BG_PARAMETER_HIDE_DIALOG, }, { .name = "width", .long_name = "width", .type = BG_PARAMETER_INT, .flags = BG_PARAMETER_HIDE_DIALOG, }, { .name = "height", .long_name = "height", .type = BG_PARAMETER_INT, .flags = BG_PARAMETER_HIDE_DIALOG, }, { /* End of parameters */ }, }; static bg_dialog_t * create_cfg_dialog(visualizer_t * win) { const bg_parameter_info_t * info; bg_dialog_t * ret; ret = bg_dialog_create_multi(TR("Visualizer configuration")); bg_dialog_add(ret, TR("General"), win->general_section, set_general_parameter, NULL, (void*)(win), parameters); info = bg_visualizer_get_parameters(win->visualizer); bg_dialog_add(ret, TR("Visualizer"), win->visualizer_section, set_vis_param, NULL, (void*)(win), info); info = bg_gtk_log_window_get_parameters(win->log_window); bg_dialog_add(ret, TR("Log window"), win->log_section, bg_gtk_log_window_set_parameter, NULL, (void*)(win->log_window), info); return ret; } static void apply_config(visualizer_t * v) { const bg_parameter_info_t * info; info = bg_visualizer_get_parameters(v->visualizer); bg_cfg_section_apply(v->visualizer_section, info, bg_visualizer_set_parameter, (void*)(v->visualizer)); bg_cfg_section_apply(v->general_section, parameters, set_general_parameter, (void*)(v)); info = bg_gtk_log_window_get_parameters(v->log_window); bg_cfg_section_apply(v->log_section, info, bg_gtk_log_window_set_parameter, (void*)(v->log_window)); } static void get_config(visualizer_t * v) { const bg_parameter_info_t * info; bg_cfg_section_get(v->general_section, parameters, get_general_parameter, (void*)(v)); info = bg_gtk_log_window_get_parameters(v->log_window); bg_cfg_section_get(v->log_section, info, bg_gtk_log_window_get_parameter, (void*)(v->log_window)); } static gboolean idle_func(void * data) { visualizer_t * v; v = (visualizer_t *)data; if(v->audio_open) { v->ra_plugin->read_audio(v->ra_handle->priv, v->audio_frame, 0, v->audio_format.samples_per_frame); bg_visualizer_update(v->visualizer, v->audio_frame); if(v->toolbar_visible) bg_gtk_vumeter_update(v->vumeter, v->audio_frame); // bg_visualizer_update(v->visualizer, v->audio_frame); } return TRUE; } static gboolean crossing_callback(GtkWidget *widget, GdkEventCrossing *event, gpointer data) { visualizer_t * v = (visualizer_t*)data; if(event->detail == GDK_NOTIFY_INFERIOR) return FALSE; v->mouse_in_toolbar = (event->type == GDK_ENTER_NOTIFY) ? 1 : 0; return FALSE; } static void set_vis_plugin(const bg_plugin_info_t * plugin, void * data) { visualizer_t * v = (visualizer_t*)data; bg_visualizer_set_vis_plugin(v->visualizer, plugin); bg_plugin_registry_set_default(v->plugin_reg, BG_PLUGIN_VISUALIZATION, BG_PLUGIN_VISUALIZE_FRAME | BG_PLUGIN_VISUALIZE_GL, plugin->name); if(bg_visualizer_need_restart(v->visualizer)) { close_vis(v); open_vis(v); } hide_toolbar(v); } static void set_vis_parameter(void * data, const char * name, const bg_parameter_value_t * val) { visualizer_t * v = (visualizer_t*)data; bg_visualizer_set_vis_parameter(v->visualizer, name, val); } static void log_close_callback(bg_gtk_log_window_t * w, void * data) { visualizer_t * v = (visualizer_t*)data; gtk_widget_set_sensitive(v->log_button, 1); } static visualizer_t * visualizer_create() { const bg_plugin_info_t * info; char * tmp_path; int row, col; GtkWidget * main_table; GtkWidget * table; GtkWidget * box; visualizer_t * ret; bg_cfg_section_t * cfg_section; ret = calloc(1, sizeof(*ret)); ret->cb.motion_callback = motion_callback; ret->cb.data = ret; window_init(ret, &ret->normal_window, 0); window_init(ret, &ret->fullscreen_window, 1); ret->current_window = &ret->normal_window; ret->log_window = bg_gtk_log_window_create(log_close_callback, ret, TR("Gmerlin visualizer")); ret->config_button = create_pixmap_button(ret, "config_16.png", TRS("Configure")); ret->plugin_button = create_pixmap_button(ret, "plugin_16.png", TRS("Recording and display plugins")); ret->restart_button = create_pixmap_button(ret, "refresh_16.png", TRS("Restart visualization")); ret->quit_button = create_pixmap_button(ret, "quit_16.png", TRS("Quit")); ret->fullscreen_button = create_pixmap_button(ret, "fullscreen_16.png", TRS("Fullscreen mode")); ret->nofullscreen_button = create_pixmap_button(ret, "windowed_16.png", TRS("Leave fullscreen mode")); ret->log_button = create_pixmap_button(ret, "log_16.png", TRS("Show log window")); ret->about_button = create_pixmap_button(ret, "about_16.png", TRS("About Gmerlin visualizer")); ret->help_button = create_pixmap_button(ret, "help_16.png", TRS("Launch help in a webwroswer")); ret->fps = gtk_label_new("Fps: --:--"); gtk_misc_set_alignment(GTK_MISC(ret->fps), 0.0, 0.5); gtk_widget_show(ret->fps); gtk_widget_hide(ret->nofullscreen_button); // bg_gtk_box_pack_start_defaults(GTK_BOX(mainbox), // bg_gtk_vumeter_get_widget(ret->vumeter)); ret->toolbar = gtk_event_box_new(); gtk_widget_set_events(ret->toolbar, GDK_ENTER_NOTIFY_MASK | GDK_LEAVE_NOTIFY_MASK); g_signal_connect(G_OBJECT(ret->toolbar), "enter-notify-event", G_CALLBACK(crossing_callback), (gpointer*)ret); g_signal_connect(G_OBJECT(ret->toolbar), "leave-notify-event", G_CALLBACK(crossing_callback), (gpointer*)ret); g_object_ref(ret->toolbar); /* Must be done for widgets, which get reparented after */ ret->vumeter = bg_gtk_vumeter_create(2, 0); /* Create actual objects */ /* Create plugin regsitry */ ret->cfg_reg = bg_cfg_registry_create(); tmp_path = bg_search_file_read("visualizer", "config.xml"); bg_cfg_registry_load(ret->cfg_reg, tmp_path); if(tmp_path) free(tmp_path); cfg_section = bg_cfg_registry_find_section(ret->cfg_reg, "plugins"); ret->plugin_reg = bg_plugin_registry_create(cfg_section); ret->visualizer = bg_visualizer_create(ret->plugin_reg); bg_visualizer_set_callbacks(ret->visualizer, &ret->cb); /* Create vis plugin widget */ ret->vis_plugins = bg_gtk_plugin_widget_single_create(TR("Visualization"), ret->plugin_reg, BG_PLUGIN_VISUALIZATION, BG_PLUGIN_VISUALIZE_FRAME | BG_PLUGIN_VISUALIZE_GL); bg_gtk_plugin_widget_single_set_change_callback(ret->vis_plugins, set_vis_plugin, ret); bg_gtk_plugin_widget_single_set_parameter_callback(ret->vis_plugins, set_vis_parameter, ret); /* Create audio and video plugin widgets */ plugin_window_init(&ret->plugin_window, ret); /* Get ov info */ ret->ov_info = bg_gtk_plugin_widget_single_get_plugin(ret->plugin_window.ov_plugins); /* Load recording plugin */ ret->ra_info = bg_gtk_plugin_widget_single_get_plugin(ret->plugin_window.ra_plugins); /* Create config stuff */ ret->visualizer_section = bg_cfg_registry_find_section(ret->cfg_reg, "visualizer"); ret->general_section = bg_cfg_registry_find_section(ret->cfg_reg, "general"); ret->log_section = bg_cfg_registry_find_section(ret->cfg_reg, "log"); ret->cfg_dialog = create_cfg_dialog(ret); /* Pack everything */ main_table = gtk_table_new(2, 2, 0); gtk_table_set_row_spacings(GTK_TABLE(main_table), 5); gtk_table_set_col_spacings(GTK_TABLE(main_table), 5); gtk_container_set_border_width(GTK_CONTAINER(main_table), 5); table = gtk_table_new(1, 4, 0); gtk_table_set_row_spacings(GTK_TABLE(table), 5); gtk_table_set_col_spacings(GTK_TABLE(table), 5); gtk_container_set_border_width(GTK_CONTAINER(table), 5); row = 0; col = 0; bg_gtk_plugin_widget_single_attach(ret->vis_plugins, table, &row, &col); gtk_widget_show(table); gtk_table_attach(GTK_TABLE(main_table), table, 0, 1, 0, 1, GTK_FILL, GTK_SHRINK, 0, 0); box = gtk_hbox_new(0, 0); gtk_box_pack_start(GTK_BOX(box), ret->plugin_button, FALSE, FALSE, 0); gtk_box_pack_start(GTK_BOX(box), ret->config_button, FALSE, FALSE, 0); gtk_box_pack_start(GTK_BOX(box), ret->restart_button, FALSE, FALSE, 0); gtk_box_pack_start(GTK_BOX(box), ret->fullscreen_button, FALSE, FALSE, 0); gtk_box_pack_start(GTK_BOX(box), ret->nofullscreen_button, FALSE, FALSE, 0); gtk_box_pack_start(GTK_BOX(box), ret->log_button, FALSE, FALSE, 0); gtk_box_pack_start(GTK_BOX(box), ret->about_button, FALSE, FALSE, 0); gtk_box_pack_start(GTK_BOX(box), ret->help_button, FALSE, FALSE, 0); gtk_box_pack_start(GTK_BOX(box), ret->quit_button, FALSE, FALSE, 0); gtk_box_pack_start(GTK_BOX(box), ret->fps, TRUE, TRUE, 5); gtk_widget_show(box); gtk_table_attach(GTK_TABLE(main_table), box, 0, 1, 1, 2, GTK_FILL, GTK_SHRINK, 0, 0); gtk_table_attach(GTK_TABLE(main_table), bg_gtk_vumeter_get_widget(ret->vumeter), 1, 2, 0, 2, GTK_FILL | GTK_EXPAND, GTK_FILL, 0, 0); gtk_widget_show(main_table); gtk_container_add(GTK_CONTAINER(ret->toolbar), main_table); // gtk_widget_show(ret->toolbar); /* Start with non-fullscreen mode */ attach_toolbar(ret, &ret->normal_window); apply_config(ret); /* Get visualization plugin */ info = bg_gtk_plugin_widget_single_get_plugin(ret->vis_plugins); bg_visualizer_set_vis_plugin(ret->visualizer, info); /* Initialize stuff */ open_audio(ret); open_vis(ret); gtk_widget_show(ret->current_window->window); if(ret->width && ret->height) gtk_decorated_window_move_resize_window(GTK_WINDOW(ret->current_window->window), ret->x, ret->y, ret->width, ret->height); else gtk_decorated_window_move_resize_window(GTK_WINDOW(ret->current_window->window), 100, 100, 640, 480); while(gdk_events_pending() || gtk_events_pending()) gtk_main_iteration(); g_idle_add(idle_func, ret); g_timeout_add(3000, toolbar_timeout, ret); g_timeout_add(1000, fps_timeout, ret); return ret; } static void visualizer_destroy(visualizer_t * v) { char * tmp_path; get_config(v); tmp_path = bg_search_file_write("visualizer", "config.xml"); bg_cfg_registry_save(v->cfg_reg, tmp_path); if(tmp_path) free(tmp_path); free(v); } int main(int argc, char ** argv) { visualizer_t * win; bg_gtk_init(&argc, &argv, "visualizer_icon.png", NULL, NULL); win = visualizer_create(); gtk_main(); if(win->vis_open) bg_visualizer_close(win->visualizer); visualizer_destroy(win); return 0; } gmerlin-1.2.0~dfsg/apps/visualizer/gmerlin-visualizer.desktop0000644000175000017500000000042311764363403024462 0ustar alessioalessio[Desktop Entry] Encoding=UTF-8 Name=Gmerlin visualizer Name[de]=Gmerlin visualisierer Comment=Run visualization plugins Comment[de]=Visualisierungs Plugins laufen lassen Exec=gmerlin_visualizer Icon=gmerlin-visualizer.png Type=Application Categories=Application;AudioVideo; gmerlin-1.2.0~dfsg/apps/visualizer/Makefile.in0000644000175000017500000005216211764363423021315 0ustar alessioalessio# Makefile.in generated by automake 1.11.1 from Makefile.am. # @configure_input@ # Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, # 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation, # Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ VPATH = @srcdir@ pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ bin_PROGRAMS = gmerlin_visualizer$(EXEEXT) subdir = apps/visualizer DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/m4/check_funcs.m4 \ $(top_srcdir)/m4/gavl_simd.m4 $(top_srcdir)/m4/gettext.m4 \ $(top_srcdir)/m4/iconv.m4 $(top_srcdir)/m4/lib-ld.m4 \ $(top_srcdir)/m4/lib-link.m4 $(top_srcdir)/m4/lib-prefix.m4 \ $(top_srcdir)/m4/lqt_opt_cflags.m4 $(top_srcdir)/m4/nls.m4 \ $(top_srcdir)/m4/po.m4 $(top_srcdir)/m4/progtest.m4 \ $(top_srcdir)/acinclude.m4 $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/include/config.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = am__installdirs = "$(DESTDIR)$(bindir)" "$(DESTDIR)$(Desktopdir)" PROGRAMS = $(bin_PROGRAMS) am_gmerlin_visualizer_OBJECTS = gmerlin_visualizer.$(OBJEXT) gmerlin_visualizer_OBJECTS = $(am_gmerlin_visualizer_OBJECTS) gmerlin_visualizer_DEPENDENCIES = $(top_builddir)/lib/libgmerlin.la \ $(top_builddir)/lib/gtk/libgmerlin_gtk.la DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)/include depcomp = $(SHELL) $(top_srcdir)/depcomp am__depfiles_maybe = depfiles am__mv = mv -f COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) LTCOMPILE = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \ --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) CCLD = $(CC) LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \ --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \ $(LDFLAGS) -o $@ SOURCES = $(gmerlin_visualizer_SOURCES) DIST_SOURCES = $(gmerlin_visualizer_SOURCES) am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; am__vpath_adj = case $$p in \ $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ *) f=$$p;; \ esac; am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; am__install_max = 40 am__nobase_strip_setup = \ srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` am__nobase_strip = \ for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" am__nobase_list = $(am__nobase_strip_setup); \ for p in $$list; do echo "$$p $$p"; done | \ sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ if (++n[$$2] == $(am__install_max)) \ { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ END { for (dir in files) print dir, files[dir] }' am__base_list = \ sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' DATA = $(Desktop_DATA) ETAGS = etags CTAGS = ctags DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ ALSA_CFLAGS = @ALSA_CFLAGS@ ALSA_LIBS = @ALSA_LIBS@ ALSA_REQUIRED = @ALSA_REQUIRED@ AMTAR = @AMTAR@ AR = @AR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ BG_VERSION = @BG_VERSION@ BG_VERSION_MAJOR = @BG_VERSION_MAJOR@ BG_VERSION_MICRO = @BG_VERSION_MICRO@ BG_VERSION_MINOR = @BG_VERSION_MINOR@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CDDB_CFLAGS = @CDDB_CFLAGS@ CDDB_LIBS = @CDDB_LIBS@ CDIO_CDDA_CFLAGS = @CDIO_CDDA_CFLAGS@ CDIO_CDDA_LIBS = @CDIO_CDDA_LIBS@ CDIO_CFLAGS = @CDIO_CFLAGS@ CDIO_LIBS = @CDIO_LIBS@ CDIO_PARANOIA_CFLAGS = @CDIO_PARANOIA_CFLAGS@ CDIO_PARANOIA_LIBS = @CDIO_PARANOIA_LIBS@ CDIO_REQUIRED = @CDIO_REQUIRED@ CFLAGS = @CFLAGS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CYGPATH_W = @CYGPATH_W@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DOXYGEN = @DOXYGEN@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ ESD_CFLAGS = @ESD_CFLAGS@ ESD_CONFIG = @ESD_CONFIG@ ESD_LIBS = @ESD_LIBS@ ESD_REQUIRED = @ESD_REQUIRED@ EXEEXT = @EXEEXT@ FGREP = @FGREP@ FONTCONFIG_CFLAGS = @FONTCONFIG_CFLAGS@ FONTCONFIG_LIBS = @FONTCONFIG_LIBS@ FREETYPE_CFLAGS = @FREETYPE_CFLAGS@ FREETYPE_LIBS = @FREETYPE_LIBS@ GAVL_CFLAGS = @GAVL_CFLAGS@ GAVL_LIBS = @GAVL_LIBS@ GAVL_REQUIRED = @GAVL_REQUIRED@ GLX_CFLAGS = @GLX_CFLAGS@ GLX_LIBS = @GLX_LIBS@ GL_CFLAGS = @GL_CFLAGS@ GL_LIBS = @GL_LIBS@ GMERLIN_DEP_LIBS = @GMERLIN_DEP_LIBS@ GMERLIN_PLUGIN_LDFLAGS = @GMERLIN_PLUGIN_LDFLAGS@ GMSGFMT = @GMSGFMT@ GMSGFMT_015 = @GMSGFMT_015@ GREP = @GREP@ GTK_CFLAGS = @GTK_CFLAGS@ GTK_LIBS = @GTK_LIBS@ GTK_REQUIRED = @GTK_REQUIRED@ ICONV_LIBS = @ICONV_LIBS@ INCLUDES = -I$(top_srcdir)/include INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ INTLLIBS = @INTLLIBS@ INTL_MACOSX_LIBS = @INTL_MACOSX_LIBS@ JACK_CFLAGS = @JACK_CFLAGS@ JACK_LIBS = @JACK_LIBS@ JACK_REQUIRED = @JACK_REQUIRED@ JPEG_CFLAGS = @JPEG_CFLAGS@ JPEG_LIBS = @JPEG_LIBS@ JPEG_REQUIRED = @JPEG_REQUIRED@ LD = @LD@ LDFLAGS = @LDFLAGS@ LIBCDDB_REQUIRED = @LIBCDDB_REQUIRED@ LIBEXIF_CFLAGS = @LIBEXIF_CFLAGS@ LIBEXIF_LIBS = @LIBEXIF_LIBS@ LIBICONV = @LIBICONV@ LIBINTL = @LIBINTL@ LIBM = @LIBM@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIPO = @LIPO@ LN_S = @LN_S@ LQT_CFLAGS = @LQT_CFLAGS@ LQT_LIBS = @LQT_LIBS@ LQT_REQUIRED = @LQT_REQUIRED@ LTLIBICONV = @LTLIBICONV@ LTLIBINTL = @LTLIBINTL@ LTLIBOBJS = @LTLIBOBJS@ LTVERSION_AGE = @LTVERSION_AGE@ LTVERSION_CURRENT = @LTVERSION_CURRENT@ LTVERSION_REVISION = @LTVERSION_REVISION@ LV_CFLAGS = @LV_CFLAGS@ LV_LIBS = @LV_LIBS@ LV_REQUIRED = @LV_REQUIRED@ MAKEINFO = @MAKEINFO@ MKDIR_P = @MKDIR_P@ MODULE_LIBADD = @MODULE_LIBADD@ MSGFMT = @MSGFMT@ MSGFMT_015 = @MSGFMT_015@ MSGMERGE = @MSGMERGE@ MUSICBRAINZ_CFLAGS = @MUSICBRAINZ_CFLAGS@ MUSICBRAINZ_LIBS = @MUSICBRAINZ_LIBS@ MUSICBRAINZ_REQUIRED = @MUSICBRAINZ_REQUIRED@ NM = @NM@ NMEDIT = @NMEDIT@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OTOOL = @OTOOL@ OTOOL64 = @OTOOL64@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PKG_CONFIG = @PKG_CONFIG@ PNG_CFLAGS = @PNG_CFLAGS@ PNG_LIBS = @PNG_LIBS@ PNG_REQUIRED = @PNG_REQUIRED@ POSUB = @POSUB@ PULSEAUDIO_CFLAGS = @PULSEAUDIO_CFLAGS@ PULSEAUDIO_LIBS = @PULSEAUDIO_LIBS@ PULSEAUDIO_REQUIRED = @PULSEAUDIO_REQUIRED@ RANLIB = @RANLIB@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ SQLITE3_LIBS = @SQLITE3_LIBS@ STRIP = @STRIP@ TEXINFO = @TEXINFO@ TIFF_CFLAGS = @TIFF_CFLAGS@ TIFF_LIBS = @TIFF_LIBS@ TIFF_REQUIRED = @TIFF_REQUIRED@ TOP_SRCDIR = @TOP_SRCDIR@ USE_NLS = @USE_NLS@ V4LCONVERT_CFLAGS = @V4LCONVERT_CFLAGS@ V4LCONVERT_LIBS = @V4LCONVERT_LIBS@ V4LCONVERT_REQUIRED = @V4LCONVERT_REQUIRED@ VERSION = @VERSION@ XDPMS_LIBS = @XDPMS_LIBS@ XFIXES_LIBS = @XFIXES_LIBS@ XGETTEXT = @XGETTEXT@ XGETTEXT_015 = @XGETTEXT_015@ XINERAMA_LIBS = @XINERAMA_LIBS@ XMKMF = @XMKMF@ XML2_CFLAGS = @XML2_CFLAGS@ XML2_LIBS = @XML2_LIBS@ XML2_REQUIRED = @XML2_REQUIRED@ XTEST_LIBS = @XTEST_LIBS@ XV_LIBS = @XV_LIBS@ X_CFLAGS = @X_CFLAGS@ X_LIBS = @X_LIBS@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_CC = @ac_ct_CC@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_vendor = @build_vendor@ builddir = @builddir@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ lt_ECHO = @lt_ECHO@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ plugindir = $(pkglibdir)/plugins AM_CFLAGS = \ @XML2_CFLAGS@ \ @GTK_CFLAGS@ \ -DLOCALE_DIR=\"$(localedir)\" \ -DPLUGIN_DIR=\"$(plugindir)\" \ -DDOC_DIR=\"$(docdir)\" \ -DDATA_DIR=\"$(pkgdatadir)\" Desktopdir = $(datadir)/applications Desktop_DATA = gmerlin-visualizer.desktop gmerlin_visualizer_SOURCES = \ gmerlin_visualizer.c gmerlin_visualizer_LDADD = $(top_builddir)/lib/libgmerlin.la $(top_builddir)/lib/gtk/libgmerlin_gtk.la EXTRA_DIST = gmerlin-visualizer.desktop all: all-am .SUFFIXES: .SUFFIXES: .c .lo .o .obj $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ && { if test -f $@; then exit 0; else break; fi; }; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu apps/visualizer/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --gnu apps/visualizer/Makefile .PRECIOUS: Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): install-binPROGRAMS: $(bin_PROGRAMS) @$(NORMAL_INSTALL) test -z "$(bindir)" || $(MKDIR_P) "$(DESTDIR)$(bindir)" @list='$(bin_PROGRAMS)'; test -n "$(bindir)" || list=; \ for p in $$list; do echo "$$p $$p"; done | \ sed 's/$(EXEEXT)$$//' | \ while read p p1; do if test -f $$p || test -f $$p1; \ then echo "$$p"; echo "$$p"; else :; fi; \ done | \ sed -e 'p;s,.*/,,;n;h' -e 's|.*|.|' \ -e 'p;x;s,.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/' | \ sed 'N;N;N;s,\n, ,g' | \ $(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1 } \ { d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \ if ($$2 == $$4) files[d] = files[d] " " $$1; \ else { print "f", $$3 "/" $$4, $$1; } } \ END { for (d in files) print "f", d, files[d] }' | \ while read type dir files; do \ if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \ test -z "$$files" || { \ echo " $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files '$(DESTDIR)$(bindir)$$dir'"; \ $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files "$(DESTDIR)$(bindir)$$dir" || exit $$?; \ } \ ; done uninstall-binPROGRAMS: @$(NORMAL_UNINSTALL) @list='$(bin_PROGRAMS)'; test -n "$(bindir)" || list=; \ files=`for p in $$list; do echo "$$p"; done | \ sed -e 'h;s,^.*/,,;s/$(EXEEXT)$$//;$(transform)' \ -e 's/$$/$(EXEEXT)/' `; \ test -n "$$list" || exit 0; \ echo " ( cd '$(DESTDIR)$(bindir)' && rm -f" $$files ")"; \ cd "$(DESTDIR)$(bindir)" && rm -f $$files clean-binPROGRAMS: @list='$(bin_PROGRAMS)'; test -n "$$list" || exit 0; \ echo " rm -f" $$list; \ rm -f $$list || exit $$?; \ test -n "$(EXEEXT)" || exit 0; \ list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ echo " rm -f" $$list; \ rm -f $$list gmerlin_visualizer$(EXEEXT): $(gmerlin_visualizer_OBJECTS) $(gmerlin_visualizer_DEPENDENCIES) @rm -f gmerlin_visualizer$(EXEEXT) $(LINK) $(gmerlin_visualizer_OBJECTS) $(gmerlin_visualizer_LDADD) $(LIBS) mostlyclean-compile: -rm -f *.$(OBJEXT) distclean-compile: -rm -f *.tab.c @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gmerlin_visualizer.Po@am__quote@ .c.o: @am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(COMPILE) -c $< .c.obj: @am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(COMPILE) -c `$(CYGPATH_W) '$<'` .c.lo: @am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(LTCOMPILE) -c -o $@ $< mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs install-DesktopDATA: $(Desktop_DATA) @$(NORMAL_INSTALL) test -z "$(Desktopdir)" || $(MKDIR_P) "$(DESTDIR)$(Desktopdir)" @list='$(Desktop_DATA)'; test -n "$(Desktopdir)" || list=; \ for p in $$list; do \ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ echo "$$d$$p"; \ done | $(am__base_list) | \ while read files; do \ echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(Desktopdir)'"; \ $(INSTALL_DATA) $$files "$(DESTDIR)$(Desktopdir)" || exit $$?; \ done uninstall-DesktopDATA: @$(NORMAL_UNINSTALL) @list='$(Desktop_DATA)'; test -n "$(Desktopdir)" || list=; \ files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ test -n "$$files" || exit 0; \ echo " ( cd '$(DESTDIR)$(Desktopdir)' && rm -f" $$files ")"; \ cd "$(DESTDIR)$(Desktopdir)" && rm -f $$files ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | \ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in files) print i; }; }'`; \ mkid -fID $$unique tags: TAGS TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ $(TAGS_FILES) $(LISP) set x; \ here=`pwd`; \ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | \ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in files) print i; }; }'`; \ shift; \ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ test -n "$$unique" || unique=$$empty_fix; \ if test $$# -gt 0; then \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ "$$@" $$unique; \ else \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ $$unique; \ fi; \ fi ctags: CTAGS CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ $(TAGS_FILES) $(LISP) list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | \ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in files) print i; }; }'`; \ test -z "$(CTAGS_ARGS)$$unique" \ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ $$unique GTAGS: here=`$(am__cd) $(top_builddir) && pwd` \ && $(am__cd) $(top_srcdir) \ && gtags -i $(GTAGS_ARGS) "$$here" distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags distdir: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done check-am: all-am check: check-am all-am: Makefile $(PROGRAMS) $(DATA) installdirs: for dir in "$(DESTDIR)$(bindir)" "$(DESTDIR)$(Desktopdir)"; do \ test -z "$$dir" || $(MKDIR_P) "$$dir"; \ done install: install-am install-exec: install-exec-am install-data: install-data-am uninstall: uninstall-am install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-am install-strip: $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ `test -z '$(STRIP)' || \ echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install mostlyclean-generic: clean-generic: distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." clean: clean-am clean-am: clean-binPROGRAMS clean-generic clean-libtool mostlyclean-am distclean: distclean-am -rm -rf ./$(DEPDIR) -rm -f Makefile distclean-am: clean-am distclean-compile distclean-generic \ distclean-tags dvi: dvi-am dvi-am: html: html-am html-am: info: info-am info-am: install-data-am: install-DesktopDATA install-dvi: install-dvi-am install-dvi-am: install-exec-am: install-binPROGRAMS install-html: install-html-am install-html-am: install-info: install-info-am install-info-am: install-man: install-pdf: install-pdf-am install-pdf-am: install-ps: install-ps-am install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-am -rm -rf ./$(DEPDIR) -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-compile mostlyclean-generic \ mostlyclean-libtool pdf: pdf-am pdf-am: ps: ps-am ps-am: uninstall-am: uninstall-DesktopDATA uninstall-binPROGRAMS .MAKE: install-am install-strip .PHONY: CTAGS GTAGS all all-am check check-am clean clean-binPROGRAMS \ clean-generic clean-libtool ctags distclean distclean-compile \ distclean-generic distclean-libtool distclean-tags distdir dvi \ dvi-am html html-am info info-am install install-DesktopDATA \ install-am install-binPROGRAMS install-data install-data-am \ install-dvi install-dvi-am install-exec install-exec-am \ install-html install-html-am install-info install-info-am \ install-man install-pdf install-pdf-am install-ps \ install-ps-am install-strip installcheck installcheck-am \ installdirs maintainer-clean maintainer-clean-generic \ mostlyclean mostlyclean-compile mostlyclean-generic \ mostlyclean-libtool pdf pdf-am ps ps-am tags uninstall \ uninstall-DesktopDATA uninstall-am uninstall-binPROGRAMS # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: gmerlin-1.2.0~dfsg/apps/cmdlineplayer/0000755000175000017500000000000011764363443017677 5ustar alessioalessiogmerlin-1.2.0~dfsg/apps/cmdlineplayer/Makefile.am0000644000175000017500000000050511764363402021726 0ustar alessioalessioplugindir=$(pkglibdir)/plugins AM_CFLAGS = \ -DLOCALE_DIR=\"$(localedir)\" \ -DPLUGIN_DIR=\"$(plugindir)\" \ -DDOC_DIR=\"$(docdir)\" \ -DDATA_DIR=\"$(pkgdatadir)\" INCLUDES = -I$(top_srcdir)/include bin_PROGRAMS = gmerlin_play dist_man_MANS = gmerlin_play.1 gmerlin_play_LDADD = $(top_builddir)/lib/libgmerlin.la -ldl gmerlin-1.2.0~dfsg/apps/cmdlineplayer/gmerlin_play.c0000644000175000017500000006716411764363402022536 0ustar alessioalessio/***************************************************************** * gmerlin - a general purpose multimedia framework and applications * * Copyright (c) 2001 - 2011 Members of the Gmerlin project * gmerlin-general@lists.sourceforge.net * http://gmerlin.sourceforge.net * * 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 of the License, 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 this program. If not, see . * *****************************************************************/ // #define INFO_WINDOW #include #include #include #include #include #include #include #include #include #include #include #include #ifdef INFO_WINDOW #include #include #endif // INFO_WINDOW #define LOG_DOMAIN "gmerlin_player" /* In commandline apps, global variables are allowed :) */ static int time_active = 0; // Whether to display the time static gavl_time_t total_time = 0; // Total time of the current track int num_tracks; int current_track = -1; bg_player_t * player; bg_plugin_registry_t * plugin_reg; bg_cfg_registry_t * cfg_reg; bg_plugin_handle_t * input_handle = NULL; int display_time = 1; bg_plugin_handle_t * oa_handle = NULL; bg_plugin_handle_t * ov_handle = NULL; char ** gmls = NULL; int gml_index = 0; /* Sections from the plugin registry */ bg_cfg_section_t * oa_section = NULL; bg_cfg_section_t * ov_section = NULL; bg_cfg_section_t * i_section = NULL; /* Sections from the player */ bg_cfg_section_t * audio_section; bg_cfg_section_t * video_section; bg_cfg_section_t * osd_section; bg_cfg_section_t * input_section; char * input_plugin_name = NULL; const bg_plugin_info_t * ov_info = NULL; char * window_id = NULL; /* Set up by registry */ static bg_parameter_info_t oa_parameters[] = { { .name = "plugin", .long_name = "Audio output plugin", .opt = "p", .type = BG_PARAMETER_MULTI_MENU, }, { /* End of parameters */ } }; static bg_parameter_info_t ov_parameters[] = { { .name = "plugin", .long_name = "Video output plugin", .opt = "p", .type = BG_PARAMETER_MULTI_MENU, }, { .name = "window", .long_name = "Window ID", .opt = "w", .type = BG_PARAMETER_STRING, }, { /* End of parameters */ } }; static bg_parameter_info_t i_parameters[] = { { .name = "plugin", .long_name = "input plugin", .opt = "p", .type = BG_PARAMETER_MULTI_MENU, }, { /* End of parameters */ } }; /* Set from player */ const bg_parameter_info_t * osd_parameters; const bg_parameter_info_t * audio_parameters; const bg_parameter_info_t * video_parameters; const bg_parameter_info_t * input_parameters; char * track_spec = NULL; char * track_spec_ptr; /* * Commandline options stuff */ static void set_oa_parameter(void * data, const char * name, const bg_parameter_value_t * val) { const bg_plugin_info_t * info; // fprintf(stderr, "set_oa_parameter: %s\n", name); if(name && !strcmp(name, "plugin")) { // fprintf(stderr, "set_oa_parameter: plugin: %s\n", val->val_str); info = bg_plugin_find_by_name(plugin_reg, val->val_str); oa_handle = bg_plugin_load(plugin_reg, info); } else { if(oa_handle && oa_handle->plugin && oa_handle->plugin->set_parameter) oa_handle->plugin->set_parameter(oa_handle->priv, name, val); } } static void opt_oa(void * data, int * argc, char *** _argv, int arg) { if(arg >= *argc) { fprintf(stderr, "Option -oa requires an argument\n"); exit(-1); } if(!bg_cmdline_apply_options(oa_section, set_oa_parameter, NULL, oa_parameters, (*_argv)[arg])) exit(-1); bg_cmdline_remove_arg(argc, _argv, arg); } static void set_ov_parameter(void * data, const char * name, const bg_parameter_value_t * val) { if(name && !strcmp(name, "plugin")) { ov_info = bg_plugin_find_by_name(plugin_reg, val->val_str); } else if(name && !strcmp(name, "window")) { window_id = bg_strdup(window_id, val->val_str); } #if 0 else { if(ov_handle && ov_handle->plugin && ov_handle->plugin->set_parameter) ov_handle->plugin->set_parameter(ov_handle->priv, name, val); } #endif } static void set_i_parameter(void * data, const char * name, const bg_parameter_value_t * val) { if(name && !strcmp(name, "plugin")) input_plugin_name = bg_strdup(input_plugin_name, val->val_str); } static void opt_ov(void * data, int * argc, char *** _argv, int arg) { if(arg >= *argc) { fprintf(stderr, "Option -ov requires an argument\n"); exit(-1); } if(!bg_cmdline_apply_options(ov_section, set_ov_parameter, NULL, ov_parameters, (*_argv)[arg])) exit(-1); bg_cmdline_remove_arg(argc, _argv, arg); } static void opt_i(void * data, int * argc, char *** _argv, int arg) { bg_cfg_section_t * cmdline_section; bg_cfg_section_t * registry_section; if(arg >= *argc) { fprintf(stderr, "Option -i requires an argument\n"); exit(-1); } if(!i_section) i_section = bg_cfg_section_create_from_parameters("i", i_parameters); if(!bg_cmdline_apply_options(i_section, set_i_parameter, NULL, i_parameters, (*_argv)[arg])) exit(-1); /* Put the parameters into the registry */ if(input_plugin_name) { cmdline_section = bg_cfg_section_find_subsection(i_section, "plugin"); cmdline_section = bg_cfg_section_find_subsection(cmdline_section, input_plugin_name); registry_section = bg_plugin_registry_get_section(plugin_reg, input_plugin_name); bg_cfg_section_transfer(cmdline_section, registry_section); bg_cfg_registry_save(cfg_reg, "test.xml"); } bg_cmdline_remove_arg(argc, _argv, arg); } static void opt_osd(void * data, int * argc, char *** _argv, int arg) { if(arg >= *argc) { fprintf(stderr, "Option -osd requires an argument\n"); exit(-1); } if(!bg_cmdline_apply_options(osd_section, bg_player_set_osd_parameter, player, osd_parameters, (*_argv)[arg])) exit(-1); bg_cmdline_remove_arg(argc, _argv, arg); } static void opt_aud(void * data, int * argc, char *** _argv, int arg) { if(arg >= *argc) { fprintf(stderr, "Option -aud requires an argument\n"); exit(-1); } if(!bg_cmdline_apply_options(audio_section, bg_player_set_audio_parameter, player, audio_parameters, (*_argv)[arg])) exit(-1); bg_cmdline_remove_arg(argc, _argv, arg); } static void opt_vid(void * data, int * argc, char *** _argv, int arg) { if(arg >= *argc) { fprintf(stderr, "Option -vid requires an argument\n"); exit(-1); } if(!bg_cmdline_apply_options(video_section, bg_player_set_video_parameter, player, video_parameters, (*_argv)[arg])) exit(-1); bg_cmdline_remove_arg(argc, _argv, arg); } static void opt_inopt(void * data, int * argc, char *** _argv, int arg) { if(arg >= *argc) { fprintf(stderr, "Option -inopt requires an argument\n"); exit(-1); } if(!bg_cmdline_apply_options(input_section, bg_player_set_input_parameter, player, input_parameters, (*_argv)[arg])) exit(-1); bg_cmdline_remove_arg(argc, _argv, arg); } static void opt_nt(void * data, int * argc, char *** _argv, int arg) { display_time = 0; } static void opt_vol(void * data, int * argc, char *** _argv, int arg) { if(arg >= *argc) { fprintf(stderr, "Option -vol requires an argument\n"); exit(-1); } bg_player_set_volume(player, strtod((*_argv[arg]), NULL)); bg_cmdline_remove_arg(argc, _argv, arg); } static void opt_tracks(void * data, int * argc, char *** _argv, int arg) { if(arg >= *argc) { fprintf(stderr, "Option -tracks requires an argument\n"); exit(-1); } track_spec = bg_strdup(track_spec, (*_argv)[arg]); track_spec_ptr = track_spec; bg_cmdline_remove_arg(argc, _argv, arg); } static void opt_v(void * data, int * argc, char *** _argv, int arg) { int val, verbose = 0; if(arg >= *argc) { fprintf(stderr, "Option -v requires an argument\n"); exit(-1); } val = atoi((*_argv)[arg]); if(val > 0) verbose |= BG_LOG_ERROR; if(val > 1) verbose |= BG_LOG_WARNING; if(val > 2) verbose |= BG_LOG_INFO; if(val > 3) verbose |= BG_LOG_DEBUG; bg_log_set_verbose(verbose); bg_cmdline_remove_arg(argc, _argv, arg); } // static void opt_help(void * data, int * argc, char *** argv, int arg); static bg_cmdline_arg_t global_options[] = { { .arg = "-oa", .help_arg = "", .help_string = "Set audio output options", .callback = opt_oa, .parameters = oa_parameters, }, { .arg = "-ov", .help_arg = "", .help_string = "Set video output options", .callback = opt_ov, .parameters = ov_parameters, }, { .arg = "-i", .help_arg = "", .help_string = "Set and configure input plugin", .callback = opt_i, .parameters = i_parameters, }, { .arg = "-aud", .help_arg = "", .help_string = "Set audio processing options", .callback = opt_aud, }, { .arg = "-vid", .help_arg = "", .help_string = "Set video processing options", .callback = opt_vid, }, { .arg = "-inopt", .help_arg = "", .help_string = "Set generic input options", .callback = opt_inopt, }, { .arg = "-osd", .help_arg = "", .help_string = "Set OSD options", .callback = opt_osd, }, { .arg = "-nt", .help_string = "Disable time display", .callback = opt_nt, }, { .arg = "-vol", .help_arg = "", .help_string = "Set volume in dB (max: 0.0)", .callback = opt_vol, }, { .arg = "-v", .help_arg = "level", .help_string = "Set verbosity level (0..4)", .callback = opt_v, }, { .arg = "-tracks", .help_arg = "", .help_string = " can be a ranges mixed with comma separated tracks", .callback = opt_tracks, }, { /* End of options */ } }; static void update_global_options() { global_options[3].parameters = audio_parameters; global_options[4].parameters = video_parameters; global_options[5].parameters = input_parameters; global_options[6].parameters = osd_parameters; } static int set_track_from_spec() { char * rest; if(*track_spec_ptr == '\0') return 0; /* Beginning */ if(track_spec_ptr == track_spec) { current_track = strtol(track_spec_ptr, &rest, 10)-1; track_spec_ptr = rest; } else { if(*track_spec_ptr == '\0') return 0; else if(*track_spec_ptr == '-') { current_track++; if(current_track >= num_tracks) return 0; /* Open range */ if(!isdigit(*(track_spec_ptr+1))) return 1; if(current_track+1 == atoi(track_spec_ptr+1)) { /* End of range reached, advance pointer */ track_spec_ptr++; // FIXME ??? strtol(track_spec_ptr, &rest, 10); track_spec_ptr = rest; } } else if(*track_spec_ptr == ',') { track_spec_ptr++; if(*track_spec_ptr == '\0') return 0; current_track = strtol(track_spec_ptr, &rest, 10)-1; track_spec_ptr = rest; } } return 1; } /* Input plugin stuff */ static int play_track(bg_player_t * player, const char * gml, const char * plugin_name) { const bg_plugin_info_t * info = NULL; bg_input_plugin_t * plugin; bg_track_info_t * track_info; int result; char * redir_url; char * redir_plugin; if(plugin_name) info = bg_plugin_find_by_name(plugin_reg, plugin_name); if(input_handle && (input_handle->info->flags & BG_PLUGIN_REMOVABLE)) { plugin = (bg_input_plugin_t*)(input_handle->plugin); } else { if(input_handle) { bg_plugin_unref(input_handle); input_handle = NULL; } if(!bg_input_plugin_load(plugin_reg, gml, info, &input_handle, NULL, 0)) { bg_log(BG_LOG_ERROR, LOG_DOMAIN, "Cannot open %s", gml); return 0; } plugin = (bg_input_plugin_t*)(input_handle->plugin); if(plugin->get_num_tracks) num_tracks = plugin->get_num_tracks(input_handle->priv); else num_tracks = 1; } if(num_tracks == 1) { if(current_track > 0) { bg_log(BG_LOG_ERROR, LOG_DOMAIN, "No such track %d", current_track+1); return 0; } current_track = 0; } else { if(!track_spec) { current_track++; if(current_track >= num_tracks) return 0; } else { #if 0 if(track_spec == track_spec_ptr) { while(set_track_from_spec()) { fprintf(stderr, "Track %d\n", current_track + 1); } track_spec_ptr = track_spec; current_track = -1; } #endif if(!set_track_from_spec()) return 0; } } track_info = plugin->get_track_info(input_handle->priv, current_track); if(!track_info) return 0; if(track_info->url) { redir_url = bg_strdup(NULL, track_info->url); redir_plugin = bg_strdup(NULL, input_handle->info->name); bg_log(BG_LOG_DEBUG, LOG_DOMAIN, "Got redirector %s (%d/%d)", redir_url, current_track+1, num_tracks); bg_plugin_unref(input_handle); input_handle = NULL; result = play_track(player, redir_url, redir_plugin); free(redir_url); free(redir_plugin); return result; } if(!track_info->name) bg_set_track_name_default(track_info, gml); bg_player_play(player, input_handle, current_track, 0, track_info->name); return 1; } static void print_time(gavl_time_t time) { char str[GAVL_TIME_STRING_LEN]; int i; int len; int total_len; if(!display_time) return; total_len = 2*GAVL_TIME_STRING_LEN + 7; if(time_active) putc('\r', stderr); gavl_time_prettyprint(time, str); fprintf(stderr, "[ "); len = strlen(str); for(i = 0; i < GAVL_TIME_STRING_LEN - len - 1; i++) { fprintf(stderr, " "); } fprintf(stderr, "%s ]/", str); gavl_time_prettyprint(total_time, str); fprintf(stderr, "[ "); len = strlen(str); for(i = 0; i < GAVL_TIME_STRING_LEN - len - 1; i++) { fprintf(stderr, " "); } fprintf(stderr, "%s ]", str); time_active = 1; } static int handle_message(bg_player_t * player, bg_msg_t * message) { int arg_i1; char * arg_str1; gavl_time_t t; gavl_audio_format_t audio_format; gavl_video_format_t video_format; gavl_metadata_t metadata; char * tmp_string_1; char * tmp_string_2; switch(bg_msg_get_id(message)) { case BG_PLAYER_MSG_TIME_CHANGED: t = bg_msg_get_arg_time(message, 0); print_time(t); break; case BG_PLAYER_MSG_TRACK_DURATION: total_time = bg_msg_get_arg_time(message, 0); break; case BG_PLAYER_MSG_TRACK_NAME: arg_str1 = bg_msg_get_arg_string(message, 0); if(arg_str1) { if(time_active) { putc('\n', stderr); time_active = 0; } bg_log(BG_LOG_INFO, LOG_DOMAIN, "Name: %s", arg_str1); free(arg_str1); } break; case BG_PLAYER_MSG_TRACK_NUM_STREAMS: arg_i1 = bg_msg_get_arg_int(message, 0); if(arg_i1) { bg_log(BG_LOG_INFO, LOG_DOMAIN, "Audio streams %d", arg_i1); } arg_i1 = bg_msg_get_arg_int(message, 1); if(arg_i1) { bg_log(BG_LOG_INFO, LOG_DOMAIN, "Video streams %d", arg_i1); } arg_i1 = bg_msg_get_arg_int(message, 2); if(arg_i1) { bg_log(BG_LOG_INFO, LOG_DOMAIN, "Subtitle streams %d", arg_i1); } break; case BG_PLAYER_MSG_AUDIO_STREAM: arg_i1 = bg_msg_get_arg_int(message, 0); bg_msg_get_arg_audio_format(message, 1, &audio_format, NULL); tmp_string_1 = bg_audio_format_to_string(&audio_format, 0); bg_msg_get_arg_audio_format(message, 2, &audio_format, NULL); tmp_string_2 = bg_audio_format_to_string(&audio_format, 0); bg_log(BG_LOG_INFO, LOG_DOMAIN, "Playing audio stream %d\nInput format:\n%s\nOutput format:\n%s", arg_i1+1, tmp_string_1, tmp_string_2); free(tmp_string_1); free(tmp_string_2); break; case BG_PLAYER_MSG_VIDEO_STREAM: arg_i1 = bg_msg_get_arg_int(message, 0); bg_msg_get_arg_video_format(message, 1, &video_format, NULL); tmp_string_1 = bg_video_format_to_string(&video_format, 0); bg_msg_get_arg_video_format(message, 2, &video_format, NULL); tmp_string_2 = bg_video_format_to_string(&video_format, 0); bg_log(BG_LOG_INFO, LOG_DOMAIN, "Playing video stream %d\nInput format:\n%s\nOutput format:\n%s", arg_i1+1, tmp_string_1, tmp_string_2); free(tmp_string_1); free(tmp_string_2); break; case BG_PLAYER_MSG_AUDIO_STREAM_INFO: gavl_metadata_init(&metadata); bg_msg_get_arg_metadata(message, 1, &metadata); fprintf(stderr, "Audio stream\n"); gavl_metadata_dump(&metadata, 2); gavl_metadata_free(&metadata); break; case BG_PLAYER_MSG_VIDEO_STREAM_INFO: gavl_metadata_init(&metadata); bg_msg_get_arg_metadata(message, 1, &metadata); fprintf(stderr, "Video stream\n"); gavl_metadata_dump(&metadata, 2); gavl_metadata_free(&metadata); break; case BG_PLAYER_MSG_SUBTITLE_STREAM_INFO: gavl_metadata_init(&metadata); bg_msg_get_arg_metadata(message, 1, &metadata); fprintf(stderr, "Subtitle stream\n"); gavl_metadata_dump(&metadata, 2); gavl_metadata_free(&metadata); break; case BG_PLAYER_MSG_CLEANUP: bg_log(BG_LOG_DEBUG, LOG_DOMAIN, "Player cleaned up"); break; case BG_PLAYER_MSG_METADATA: /* Metadata */ gavl_metadata_init(&metadata); bg_msg_get_arg_metadata(message, 0, &metadata); fprintf(stderr, "Metadata:\n"); gavl_metadata_dump(&metadata, 2); gavl_metadata_free(&metadata); break; case BG_PLAYER_MSG_STATE_CHANGED: arg_i1 = bg_msg_get_arg_int(message, 0); switch(arg_i1) { case BG_PLAYER_STATE_STOPPED: break; case BG_PLAYER_STATE_PLAYING: bg_log(BG_LOG_DEBUG, LOG_DOMAIN, "Player now playing"); break; case BG_PLAYER_STATE_SEEKING: if(time_active) { putc('\n', stderr); time_active = 0; } bg_log(BG_LOG_DEBUG, LOG_DOMAIN, "Player now seeking"); break; case BG_PLAYER_STATE_CHANGING: case BG_PLAYER_STATE_EOF: bg_log(BG_LOG_DEBUG, LOG_DOMAIN, "Player now changing"); if(time_active) { putc('\n', stderr); time_active = 0; } if(num_tracks == 1) gml_index++; if(!gmls[gml_index]) return 0; else if(!play_track(player, gmls[gml_index], input_plugin_name)) return 0; break; case BG_PLAYER_STATE_BUFFERING: break; case BG_PLAYER_STATE_PAUSED: break; } break; case BG_PLAYER_MSG_TRACK_CHANGED: break; } return 1; } #ifdef INFO_WINDOW static gboolean idle_callback(gpointer data) { bg_msg_t * msg; bg_msg_queue_t * q = (bg_msg_queue_t *)data; msg = bg_msg_queue_try_lock_read(q); if(!msg) return TRUE; if(!handle_message(player, msg)) gtk_main_quit(); bg_msg_queue_unlock_read(q); return TRUE; } static void info_close_callback(bg_gtk_info_window_t * info_window, void * data) { fprintf(stderr, "Info window now closed\n"); } #endif const bg_cmdline_app_data_t app_data = { .package = PACKAGE, .version = VERSION, .name = "gmerlin_player", .synopsis = TRS("[options] gml...\n"), .help_before = TRS("Commandline Multimedia player\n"), .args = (bg_cmdline_arg_array_t[]) { { TRS("Options"), global_options }, { } }, .files = (bg_cmdline_ext_doc_t[]) { { "~/.gmerlin/plugins.xml", TRS("Cache of the plugin registry (shared by all applicatons)") }, { "~/.gmerlin/generic/config.xml", TRS("Default plugin parameters are read from there. Use gmerlin_plugincfg to change them.") }, { /* End */ } }, }; int main(int argc, char ** argv) { int i; bg_msg_t * message; char * tmp_path; #ifdef INFO_WINDOW bg_gtk_info_window_t * info_window; #endif const bg_plugin_info_t * info; bg_cfg_section_t * cfg_section; bg_msg_queue_t * message_queue; #ifdef INFO_WINDOW bg_gtk_init(&argc, &argv); #endif /* Create plugin regsitry */ cfg_reg = bg_cfg_registry_create(); tmp_path = bg_search_file_read("generic", "config.xml"); bg_cfg_registry_load(cfg_reg, tmp_path); if(tmp_path) free(tmp_path); cfg_section = bg_cfg_registry_find_section(cfg_reg, "plugins"); plugin_reg = bg_plugin_registry_create(cfg_section); player = bg_player_create(plugin_reg); bg_player_set_volume(player, 0.0); /* Create config sections */ audio_parameters = bg_player_get_audio_parameters(player); audio_section = bg_cfg_section_create_from_parameters("audio", audio_parameters); video_parameters = bg_player_get_video_parameters(player); video_section = bg_cfg_section_create_from_parameters("video", video_parameters); osd_parameters = bg_player_get_osd_parameters(player); osd_section = bg_cfg_section_create_from_parameters("osd", osd_parameters); input_parameters = bg_player_get_input_parameters(player); input_section = bg_cfg_section_create_from_parameters("input", input_parameters); update_global_options(); #ifdef INFO_WINDOW info_window = bg_gtk_info_window_create(player, info_close_callback, NULL); bg_gtk_info_window_show(info_window); #endif /* Set the plugin parameter for the commandline */ bg_plugin_registry_set_parameter_info(plugin_reg, BG_PLUGIN_OUTPUT_AUDIO, BG_PLUGIN_PLAYBACK, &oa_parameters[0]); bg_plugin_registry_set_parameter_info(plugin_reg, BG_PLUGIN_OUTPUT_VIDEO, BG_PLUGIN_PLAYBACK, &ov_parameters[0]); bg_plugin_registry_set_parameter_info(plugin_reg, BG_PLUGIN_INPUT, BG_PLUGIN_FILE|BG_PLUGIN_URL|BG_PLUGIN_REMOVABLE, &i_parameters[0]); oa_section = bg_cfg_section_create_from_parameters("oa", oa_parameters); ov_section = bg_cfg_section_create_from_parameters("oa", ov_parameters); /* Set message queue */ message_queue = bg_msg_queue_create(); bg_player_add_message_queue(player, message_queue); /* Apply default options */ bg_cfg_section_apply(audio_section, audio_parameters, bg_player_set_audio_parameter, player); bg_cfg_section_apply(video_section, video_parameters, bg_player_set_video_parameter, player); bg_cfg_section_apply(osd_section, osd_parameters, bg_player_set_osd_parameter, player); bg_cfg_section_apply(input_section, input_parameters, bg_player_set_input_parameter, player); /* Get commandline options */ bg_cmdline_init(&app_data); bg_cmdline_parse(global_options, &argc, &argv, NULL); gmls = bg_cmdline_get_locations_from_args(&argc, &argv); if(!gmls) { fprintf(stderr, "No input files given\n"); return 0; } /* Start the player thread */ bg_player_run(player); /* Load audio output */ if(!oa_handle) { info = bg_plugin_registry_get_default(plugin_reg, BG_PLUGIN_OUTPUT_AUDIO, BG_PLUGIN_PLAYBACK); if(info) { oa_handle = bg_plugin_load(plugin_reg, info); } } bg_player_set_oa_plugin(player, oa_handle); /* Load video output */ if(!ov_info) { ov_info = bg_plugin_registry_get_default(plugin_reg, BG_PLUGIN_OUTPUT_VIDEO, BG_PLUGIN_PLAYBACK); } if(ov_info) { ov_handle = bg_ov_plugin_load(plugin_reg, ov_info, window_id); cfg_section = bg_cfg_section_find_subsection(ov_section, "plugin"); cfg_section = bg_cfg_section_find_subsection(cfg_section, ov_info->name); i = bg_parameter_get_selected(&ov_parameters[0], ov_info->name); bg_cfg_section_apply(cfg_section, ov_parameters[0].multi_parameters[i], ov_handle->plugin->set_parameter, ov_handle->priv); } bg_player_set_ov_plugin(player, ov_handle); /* Play first track */ play_track(player, gmls[gml_index], input_plugin_name); /* Main loop */ #ifndef INFO_WINDOW while(1) { message = bg_msg_queue_lock_read(message_queue); if(!handle_message(player, message)) { bg_msg_queue_unlock_read(message_queue); break; } bg_msg_queue_unlock_read(message_queue); } #else g_timeout_add(10, idle_callback, message_queue); gtk_main(); #endif // INFO_WINDOW bg_player_quit(player); bg_player_destroy(player); bg_msg_queue_destroy(message_queue); if(oa_handle) bg_plugin_unref(oa_handle); if(ov_handle) bg_plugin_unref(ov_handle); if(input_handle) bg_plugin_unref(input_handle); tmp_path = bg_search_file_read("generic", "config.xml"); bg_cfg_registry_load(cfg_reg, tmp_path); if(tmp_path) free(tmp_path); bg_cfg_registry_destroy(cfg_reg); bg_plugin_registry_destroy(plugin_reg); return 0; } gmerlin-1.2.0~dfsg/apps/cmdlineplayer/gmerlin_play.10000644000175000017500000005126411764363402022446 0ustar alessioalessio.TH GMERLIN_PLAYER 1 "March 2012" Gmerlin "User Manuals" .SH NAME gmerlin_player .SH SYNOPSIS .B gmerlin_player .I [options] .I gml... .SH DESCRIPTION Commandline Multimedia player .SH OPTIONS .B -oa .I .RS 2 Set audio output options .RE .RS 2 .BR p "=option[{suboptions}]" .P Supported options: oa_alsa oa_pulse oa_oss oa_esd .P Default: oa_alsa .P Audio output plugin .P .B Suboptions for p=oa_alsa .P .RS 2 .BR card "=" .P Supported strings: default hw:0,0 hw:0,4 .P Default: default .P Card .P .BR surround40 "=[1|0] (default: 1)" .P Enable 4.0 Surround .P Use the surround 4.0 (aka quadrophonic) device .P .BR surround41 "=[1|0] (default: 1)" .P Enable 4.1 Surround .P Use the surround 4.1 device .P .BR surround50 "=[1|0] (default: 1)" .P Enable 5.0 Surround .P Use the surround 5.0 device .P .BR surround51 "=[1|0] (default: 1)" .P Enable 5.1 Surround .P Use the surround 5.1 device .P .BR user_device "=" .P User device .P Enter a custom device to use for playback. Leave empty to use the settings above .P .BR buffer_time "= (10..10000, default: 1000)" .P Buffer time .P Set the buffer time (in milliseconds). Larger values improve playback performance on slow systems under load. Smaller values decrease the latency of the volume control. .P .RE .B Suboptions for p=oa_oss .P .RS 2 .BR multichannel_mode "=" .P Supported strings: none multidev creative .P Default: none .P Multichannel Mode .P .BR device "= (Default: /dev/dsp)" .P Device .P .BR use_rear_device "=[1|0] (default: 0)" .P Use Rear Device .P .BR rear_device "= (Default: /dev/dsp1)" .P Rear Device .P .BR use_center_lfe_device "=[1|0] (default: 0)" .P Use Center/LFE Device .P .BR center_lfe_device "= (Default: /dev/dsp2)" .P Center/LFE Device .P .RE .B Suboptions for p=oa_esd .P .RS 2 .BR esd_host "=" .P Host (empty: local) .P .RE .RE .B -ov .I .RS 2 Set video output options .RE .RS 2 .BR p "=option[{suboptions}]" .P Supported options: ov_x11 ov_v4l2 .P Default: ov_x11 .P Video output plugin .P .B Suboptions for p=ov_x11 .P .RS 2 .BR auto_resize "=[1|0] (default: 1)" .P Auto resize window .P .BR disable_xscreensaver_normal "=[1|0] (default: 0)" .P Disable Screensaver for normal playback .P .BR disable_xscreensaver_fullscreen "=[1|0] (default: 1)" .P Disable Screensaver for fullscreen playback .P .BR force_hw_scale "=[1|0] (default: 1)" .P Force hardware scaling .P Use hardware scaling even if it involves more CPU intensive pixelformat conversions .P .BR background_color "=,, (default: 0.000,0.000,0.000)" .P , and are in the range 0.0..1.0 .P Background color .P Specify the background color for videos with alpha channel. This is only used by the OpenGL driver. .P .BR scale_mode "=" .P Supported strings: auto nearest bilinear quadratic cubic_bspline cubic_mitchell cubic_catmull sinc_lanczos .P Default: auto .P Scale mode .P Choose scaling method. Auto means to choose based on the conversion quality. Nearest is fastest, Sinc with Lanczos window is slowest. .P .BR scale_order "= (4..1000, default: 4)" .P Scale order .P Order for sinc scaling .P .BR scale_quality "= (1..5, default: 2)" .P Scale quality .P Scale quality .P .RE .B Suboptions for p=ov_v4l2 .P .RS 2 .BR device "=option[{suboptions}]" .P Supported options: /dev/video0 .P Default: /dev/video0 .P V4L2 Device .P .BR force_rw "=[1|0] (default: 1)" .P Force write .P Don't use memory mapping .P .RE .BR w "=" .P Window ID .P .RE .B -i .I .RS 2 Set and configure input plugin .RE .RS 2 .BR p "=option[{suboptions}]" .P Supported options: i_cdaudio i_avdec i_vcd i_dvd i_singlepic_stills i_lqt i_edl i_singlepic i_mikmod .P Default: i_cdaudio .P input plugin .P .B Suboptions for p=i_cdaudio .P .RS 2 .BR trackname_template "= (Default: %p - %t)" .P Trackname template .P Template for track name generation from metadata %p: Artist %a: Album %g: Genre %t: Track name %n: Track number (d = number of digits, 1-9) %y: Year %c: Comment .P .BR use_cdtext "=[1|0] (default: 1)" .P Use CD-Text .P Try to get CD metadata from CD-Text .P .BR use_local "=[1|0] (default: 1)" .P Use locally saved metadata .P Whenever we obtain CD metadata from the internet, we save them into $HOME/.gmerlin/cdaudio_metadata. If you got wrong metadata for a CD, disabling this option will retrieve the metadata again and overwrite the saved data. .P .BR use_musicbrainz "=[1|0] (default: 1)" .P Use Musicbrainz .P .BR musicbrainz_host "= (Default: mm.musicbrainz.org)" .P Server .P .BR musicbrainz_port "= (1..65535, default: 80)" .P Port .P .BR musicbrainz_proxy_host "=" .P Proxy .P Proxy server (leave empty for direct connection) .P .BR musicbrainz_proxy_port "= (1..65535, default: 80)" .P Proxy port .P Proxy port .P .BR use_cddb "=[1|0] (default: 1)" .P Use Cddb .P .BR cddb_host "= (Default: freedb.org)" .P Server .P .BR cddb_port "= (1..65535, default: 80)" .P Port .P .BR cddb_path "= (Default: /~cddb/cddb.cgi)" .P Path .P .BR cddb_proxy_host "=" .P Proxy .P Proxy server (leave empty for direct connection) .P .BR cddb_proxy_port "= (1..65535, default: 80)" .P Proxy port .P Proxy port .P .BR cddb_proxy_user "=" .P Proxy username .P User name for proxy (leave empty for poxies, which don't require authentication) .P .BR cddb_proxy_pass "=" .P Proxy password .P Password for proxy .P .BR cddb_timeout "= (0..1000, default: 10)" .P Timeout .P Timeout (in seconds) for connections to the CDDB server .P .BR cdparanoia_speed "=" .P Supported strings: Auto 4 8 16 32 .P Default: Auto .P Speed .P .BR cdparanoia_max_retries "= (0..200, default: 20)" .P Maximum retries .P Maximum number of retries, 0 = infinite .P .BR cdparanoia_disable_paranoia "=[1|0] (default: 0)" .P Disable paranoia .P Disable all data verification and correction features. .P .BR cdparanoia_disable_extra_paranoia "=[1|0] (default: 0)" .P Disable extra paranoia .P Disables intra-read data verification; only overlap checking atread boundaries is performed. It can wedge if errors occur in the attempted overlap area. Not recommended. .P .RE .B Suboptions for p=i_avdec .P .RS 2 .BR audio_dynrange "=[1|0] (default: 1)" .P Dynamic range control .P Enable dynamic range control for codecs, which support this (currently only A52 and DTS). .P .BR pp "= (0.00..1.00, default: 0.20)" .P Postprocessing level .P Set postprocessing (to remove compression artifacts). 0 means no postprocessing, 1 means maximum postprocessing. .P .BR shrink "= (0..3, default: 0)" .P Shrink factor .P This enables downscaling of images while decoding. Currently only supported for JPEG-2000. .P .BR vdpau "=[1|0] (default: 1)" .P Use vdpau .P Use VDPAU .P .BR connect_timeout "= (0..2000000, default: 5000)" .P Connect timeout (milliseconds) .P .BR read_timeout "= (0..2000000, default: 5000)" .P Read timeout (milliseconds) .P .BR network_buffer_size "= (1..1000, default: 32)" .P Network buffer size (kB) .P .BR network_bandwidth "=" .P Supported strings: 14400 19200 28800 33600 34400 57600 115200 262200 393200 524300 1500000 10500000 .P Default: 524300 .P Bandwidth .P .BR http_shoutcast_metadata "=[1|0] (default: 1)" .P Enable shoutcast title streaming .P .BR http_use_proxy "=[1|0] (default: 0)" .P Use proxy .P .BR http_proxy_host "=" .P Proxy host .P .BR http_proxy_port "= (1..65535, default: 80)" .P Proxy port .P .BR http_proxy_auth "=[1|0] (default: 0)" .P Proxy needs authentication .P .BR http_proxy_user "=" .P Proxy username .P .BR http_proxy_pass "=" .P Proxy password .P .BR rtp_try_tcp "=[1|0] (default: 0)" .P Try RTP over TCP .P Use this if your filewall blocks all UDP traffic. Not all servers support TCP .P .BR rtp_port_base "= (0..65530, default: 0)" .P Port base for RTP .P Port base for RTP over UDP. Values of 1024 or smaller enable random ports (recommended for RTSP aware firewalls). Values larger than 1024 define the base port. 2 consecutive ports are used for each A/V stream, these must be accessable through the firewall. Odd values are rounded to the next even value. .P .BR ftp_anonymous "=[1|0] (default: 1)" .P Login as anonymous .P .BR ftp_anonymous_password "= (Default: gates@nanosoft.com)" .P Anonymous ftp password .P .BR seek_subtitles "=" .P Supported strings: never video always .P Default: never .P Seek external subtitles .P If the input is a regular file, gmerlin_avdecoder can scan the directory for matching subtitle files. For a file movie.mpg, possible subtitle files are e.g. movie_english.srt, movie_german.srt. The rule is, that the first part of the filename of the subtitle file must be equal to the movie filename up to the extension. Furthermore, the subtitle filename must have an extension supported by any of the subtitle readers. Subtitle seeking can be disabled, enabled for video files or enabled for all files. .P .BR default_subtitle_encoding "= (Default: LATIN1)" .P Default subtitle encoding .P This sets the default encoding for text subtitles,when the original encoding is unknown. It must be a character set namerecognized by iconv. Type 'iconv -l' at the commandline for a list of supported encodings. .P .BR sample_accuracy "=" .P Supported strings: never always when_necessary .P Default: never .P Sample accurate .P Try sample accurate seeking. For most formats, this is not necessary, since normal seeking works fine. Some formats are only seekable in sample accurate mode. Choose "When necessary" to enable seeking for most formats with the smallest overhead. .P .BR cache_time "= (default: 500)" .P Cache time (milliseconds) .P If building an index takes longer than the specified time, it will be cached. .P .BR cache_size "= (default: 20)" .P Cache size (Megabytes) .P Set the maximum total size of the cache directory. .P .BR threads "= (1..1024, default: 1)" .P Number of decoding threads .P Set the number of threads used by Video codecs .P .BR dv_datetime "=[1|0] (default: 0)" .P Export date and time as timecodes for DV .P .RE .B Suboptions for p=i_dvd .P .RS 2 .BR audio_dynrange "=[1|0] (default: 1)" .P Dynamic range control .P Enable dynamic range control for codecs, which support this (currently only A52 and DTS). .P .RE .B Suboptions for p=i_singlepic_stills .P .RS 2 .BR display_time "={[[HH:]MM:]SS} (default: 0:00)" .P Seconds can be fractional (i.e. with decimal point) Display time .P Time to pass until the next track will be selected. 0 means infinite. .P .RE .B Suboptions for p=i_lqt .P .RS 2 .BR ac "={option[{suboptions}][:option[{suboptions}]...]}" .P Supported options: ima4 rawaudio twos ulaw sowt alaw in24 in32 fl32 fl64 lpcm vorbis vorbis_qt ffmpeg_mp3 ffmpeg_mp2 ffmpeg_ac3 ffmpeg_qdm2 ffmpeg_alac ffmpeg_adpcm_ms ffmpeg_ima_adpcm_wav faad2 Audio Codecs .P Sort and configure audio codecs .P .BR vc "={option[{suboptions}][:option[{suboptions}]...]}" .P Supported options: raw v308 v408 v410 yuv2 yuv4 yv12 2vuy v210 rtjpeg jpeg mjpa png ffmpeg_mpg1 ffmpeg_mpg4 ffmpeg_msmpeg4v1 ffmpeg_msmpeg4v2 ffmpeg_msmpeg4v3 ffmpeg_msmpeg4v3_wmp ffmpeg_h263_dec ffmpeg_h263 ffmpeg_h264 ffmpeg_i263 ffmpeg_svq1 ffmpeg_svq3 ffmpeg_mjpg ffmpeg_mjpegb ffmpeg_TGA ffmpeg_TIFF ffmpeg_8BPS ffmpeg_indeo ffmpeg_rpza ffmpeg_smc ffmpeg_cinepak ffmpeg_cyuv ffmpeg_rle ffmpeg_wrle ffmpeg_dv ffmpeg_dvcpro ffmpeg_dv50 ffmpeg_dvcprohd ffmpeg_ffvhuff ffmpeg_ffv1 ffmpeg_dnxhd ffmpeg_imx schroedinger yuvs Video Codecs .P Sort and configure video codecs .P .B Suboptions for ffmpeg_mpg1 .P .RS 2 .BR ff_flag_gray "=[1|0] (default: 0)" .P Grayscale mode .P .RE .B Suboptions for ffmpeg_mpg4 .P .RS 2 .BR ff_flag_gray "=[1|0] (default: 0)" .P Grayscale mode .P .RE .B Suboptions for ffmpeg_msmpeg4v1 .P .RS 2 .BR ff_flag_gray "=[1|0] (default: 0)" .P Grayscale mode .P .RE .B Suboptions for ffmpeg_msmpeg4v2 .P .RS 2 .BR ff_flag_gray "=[1|0] (default: 0)" .P Grayscale mode .P .RE .B Suboptions for ffmpeg_msmpeg4v3 .P .RS 2 .BR ff_flag_gray "=[1|0] (default: 0)" .P Grayscale mode .P .RE .B Suboptions for ffmpeg_msmpeg4v3_wmp .P .RS 2 .BR ff_flag_gray "=[1|0] (default: 0)" .P Grayscale mode .P .RE .B Suboptions for ffmpeg_h263_dec .P .RS 2 .BR ff_flag_gray "=[1|0] (default: 0)" .P Grayscale mode .P .RE .B Suboptions for ffmpeg_h263 .P .RS 2 .BR ff_flag_gray "=[1|0] (default: 0)" .P Grayscale mode .P .RE .B Suboptions for ffmpeg_h264 .P .RS 2 .BR ff_flag_gray "=[1|0] (default: 0)" .P Grayscale mode .P .RE .B Suboptions for ffmpeg_i263 .P .RS 2 .BR ff_flag_gray "=[1|0] (default: 0)" .P Grayscale mode .P .RE .B Suboptions for ffmpeg_svq1 .P .RS 2 .BR ff_flag_gray "=[1|0] (default: 0)" .P Grayscale mode .P .RE .B Suboptions for ffmpeg_svq3 .P .RS 2 .BR ff_flag_gray "=[1|0] (default: 0)" .P Grayscale mode .P .RE .B Suboptions for ffmpeg_mjpg .P .RS 2 .BR ff_flag_gray "=[1|0] (default: 0)" .P Grayscale mode .P .RE .B Suboptions for ffmpeg_indeo .P .RS 2 .BR ff_flag_gray "=[1|0] (default: 0)" .P Grayscale mode .P .RE .B Suboptions for ffmpeg_cinepak .P .RS 2 .BR ff_flag_gray "=[1|0] (default: 0)" .P Grayscale mode .P .RE .B Suboptions for ffmpeg_cyuv .P .RS 2 .BR ff_flag_gray "=[1|0] (default: 0)" .P Grayscale mode .P .RE .B Suboptions for ffmpeg_dv .P .RS 2 .BR ff_flag_gray "=[1|0] (default: 0)" .P Grayscale mode .P .RE .B Suboptions for ffmpeg_dvcpro .P .RS 2 .BR ff_flag_gray "=[1|0] (default: 0)" .P Grayscale mode .P .RE .B Suboptions for ffmpeg_dv50 .P .RS 2 .BR ff_flag_gray "=[1|0] (default: 0)" .P Grayscale mode .P .RE .B Suboptions for ffmpeg_dvcprohd .P .RS 2 .BR ff_flag_gray "=[1|0] (default: 0)" .P Grayscale mode .P .RE .B Suboptions for ffmpeg_ffvhuff .P .RS 2 .BR ff_flag_gray "=[1|0] (default: 0)" .P Grayscale mode .P .RE .B Suboptions for ffmpeg_ffv1 .P .RS 2 .BR ff_flag_gray "=[1|0] (default: 0)" .P Grayscale mode .P .RE .B Suboptions for ffmpeg_dnxhd .P .RS 2 .BR ff_flag_gray "=[1|0] (default: 0)" .P Grayscale mode .P .RE .B Suboptions for ffmpeg_imx .P .RS 2 .BR ff_flag_gray "=[1|0] (default: 0)" .P Grayscale mode .P .RE .RE .B Suboptions for p=i_singlepic .P .RS 2 .BR timescale "= (1..100000, default: 25)" .P Timescale .P .BR frame_duration "= (1..100000, default: 1)" .P Frame duration .P .RE .B Suboptions for p=i_mikmod .P .RS 2 .BR output "=" .P Supported strings: mono8 stereo8 mono16 stereo16 .P Default: stereo16 .P Output format .P .BR mixing_frequency "= (4000..60000, default: 44100)" .P Samplerate .P .BR hidden "=[1|0] (default: 0)" .P Look for hidden patterns in module .P .BR sur "=[1|0] (default: 0)" .P Use surround mixing .P .BR fade "=[1|0] (default: 0)" .P Force volume fade at the end of module .P .BR interpol "=[1|0] (default: 0)" .P Use interpolate mixing .P .RE .RE .B -aud .I .RS 2 Set audio processing options .RE .RS 2 .BR sampleformat "=" .P Supported strings: none 8 16 32 f d .P Default: none .P Force sampleformat .P Force a sampleformat to be used for processing. None means to take the input format. .P .BR q "= (1..5, default: 2)" .P Conversion Quality .P Set the conversion quality for format conversions. Lower quality means more speed. Values above 3 enable slow high quality calculations. .P .BR dither_mode "=" .P Supported strings: auto none rect tri shaped .P Default: auto .P Dither mode .P Dither mode. Auto means to use the quality level. Subsequent options are ordered by increasing quality (i.e. decreasing speed). .P .BR fixed_samplerate "=[1|0] (default: 0)" .P Fixed samplerate .P If disabled, the output samplerate is taken from the source. If enabled, the samplerate you specify below us used. .P .BR samplerate "= (8000..192000, default: 44100)" .P Samplerate .P Samplerate .P .BR resample_mode "=" .P Supported strings: auto zoh linear sinc_fast sinc_medium sinc_best .P Default: auto .P Resample mode .P Resample mode. Auto means to use the quality level. Subsequent options are ordered by increasing quality (i.e. decreasing speed). .P .BR fixed_channel_setup "=[1|0] (default: 0)" .P Fixed channel setup .P If disabled, the output channel configuration is taken from the source. If enabled, the setup you specify below us used. .P .BR num_front_channels "= (1..5, default: 2)" .P Front channels .P .BR num_rear_channels "= (0..3, default: 0)" .P Rear channels .P .BR num_lfe_channels "=[1|0] (default: 0)" .P LFE .P .BR front_to_rear "=" .P Supported strings: mute copy diff .P Default: copy .P Front to rear mode .P Mix mode when the output format has rear channels, but the source doesn't. .P .BR stereo_to_mono "=" .P Supported strings: left right mix .P Default: mix .P Stereo to mono mode .P Mix mode when downmixing Stereo to Mono. .P .RE .B -vid .I .RS 2 Set video processing options .RE .RS 2 .BR q "= (1..5, default: 2)" .P Conversion Quality .P Set the conversion quality for format conversions. Lower quality means more speed. Values above 3 enable slow high quality calculations. .P .BR alpha_mode "=" .P Supported strings: ignore blend_color .P Default: ignore .P Alpha mode .P This option is used if the source has an alpha (=transparency) channel, but the output supports no transparency. Either, the transparency is ignored, or the background color you specify below is blended in. .P .BR background_color "=,, (default: 0.000,0.000,0.000)" .P , and are in the range 0.0..1.0 .P Background color .P Background color to use, when alpha mode above is "Blend background color". .P .BR sm "=[1|0] (default: 0)" .P Resample chroma .P Always perform chroma resampling if chroma subsampling factors or chroma placements are different. Usually, this is only done for qualities above 3. .P .BR still_framerate "= (1.00..100.00, default: 10.00)" .P Still image framerate .P Set framerate with which still images will be redisplayed periodically .P .BR threads "= (1..1024, default: 1)" .P Number of threads .P Threads to launch for processing operations. Changing this requires program restart .P .RE .B -inopt .I .RS 2 Set generic input options .RE .RS 2 .BR still_framerate "= (0..100, default: 10)" .P Still image repitition rate .P When showing still images, gmerlin repeats them periodically to make realtime filter tweaking work. .P .BR sync_offset "= (-1000..1000, default: 0)" .P Sync offset [ms] .P Use this for playing buggy files, which have a constant offset between audio and video. Use positive values if the video is ahead of audio .P .RE .B -osd .I .RS 2 Set OSD options .RE .RS 2 .BR enable_osd "=[1|0] (default: 1)" .P Enable OSD .P .BR font_size "= (12.00..100.00, default: 30.00)" .P Size .P Specify fontsize for OSD. The value you enter, is for an image width of 640. For other widths, the value will be scaled .P .BR color "=,,, (default: 1.000,1.000,1.000,1.000)" .P , , and are in the range 0.0..1.0 .P Foreground color .P .BR border_color "=,, (default: 0.000,0.000,0.000)" .P , and are in the range 0.0..1.0 .P Border color .P .BR border_width "= (0.00..10.00, default: 2.00)" .P Border width .P .BR justify_h "=" .P Supported strings: center left right .P Default: center .P Horizontal justify .P .BR justify_v "=" .P Supported strings: center top bottom .P Default: center .P Vertical justify .P .BR border_left "= (0..65535, default: 10)" .P Left border .P Distance from the left text border to the image border .P .BR border_right "= (0..65535, default: 10)" .P Right border .P Distance from the right text border to the image border .P .BR border_top "= (0..65535, default: 10)" .P Top border .P Distance from the top text border to the image border .P .BR border_bottom "= (0..65535, default: 10)" .P Bottom border .P Distance from the bottom text border to the image border .P .BR duration "= (0..10000, default: 2000)" .P Duration (milliseconds) .P .RE .B -nt .RS 2 Disable time display .RE .B -vol .I .RS 2 Set volume in dB (max: 0.0) .RE .B -v .I level .RS 2 Set verbosity level (0..4) .RE .B -tracks .I .RS 2 can be a ranges mixed with comma separated tracks .RE .SH GENERIC OPTIONS The following generic options are available for all gmerlin applications .B -help .RS 2 Print this help message and exit .RE .B -help-man .RS 2 Print this help message as a manual page and exit .RE .B -help-texi .RS 2 Print this help message in texinfo format and exit .RE .B -version .RS 2 Print version info and exit .RE .SH FILES .B ~/.gmerlin/plugins.xml .RS 2 Cache of the plugin registry (shared by all applicatons) .RE .P .B ~/.gmerlin/generic/config.xml .RS 2 Default plugin parameters are read from there. Use gmerlin_plugincfg to change them. .RE .P gmerlin-1.2.0~dfsg/apps/cmdlineplayer/Makefile.in0000644000175000017500000005444111764363423021752 0ustar alessioalessio# Makefile.in generated by automake 1.11.1 from Makefile.am. # @configure_input@ # Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, # 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation, # Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ VPATH = @srcdir@ pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ bin_PROGRAMS = gmerlin_play$(EXEEXT) subdir = apps/cmdlineplayer DIST_COMMON = $(dist_man_MANS) $(srcdir)/Makefile.am \ $(srcdir)/Makefile.in ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/m4/check_funcs.m4 \ $(top_srcdir)/m4/gavl_simd.m4 $(top_srcdir)/m4/gettext.m4 \ $(top_srcdir)/m4/iconv.m4 $(top_srcdir)/m4/lib-ld.m4 \ $(top_srcdir)/m4/lib-link.m4 $(top_srcdir)/m4/lib-prefix.m4 \ $(top_srcdir)/m4/lqt_opt_cflags.m4 $(top_srcdir)/m4/nls.m4 \ $(top_srcdir)/m4/po.m4 $(top_srcdir)/m4/progtest.m4 \ $(top_srcdir)/acinclude.m4 $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/include/config.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = am__installdirs = "$(DESTDIR)$(bindir)" "$(DESTDIR)$(man1dir)" PROGRAMS = $(bin_PROGRAMS) gmerlin_play_SOURCES = gmerlin_play.c gmerlin_play_OBJECTS = gmerlin_play.$(OBJEXT) gmerlin_play_DEPENDENCIES = $(top_builddir)/lib/libgmerlin.la DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)/include depcomp = $(SHELL) $(top_srcdir)/depcomp am__depfiles_maybe = depfiles am__mv = mv -f COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) LTCOMPILE = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \ --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) CCLD = $(CC) LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \ --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \ $(LDFLAGS) -o $@ SOURCES = gmerlin_play.c DIST_SOURCES = gmerlin_play.c am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; am__vpath_adj = case $$p in \ $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ *) f=$$p;; \ esac; am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; am__install_max = 40 am__nobase_strip_setup = \ srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` am__nobase_strip = \ for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" am__nobase_list = $(am__nobase_strip_setup); \ for p in $$list; do echo "$$p $$p"; done | \ sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ if (++n[$$2] == $(am__install_max)) \ { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ END { for (dir in files) print dir, files[dir] }' am__base_list = \ sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' man1dir = $(mandir)/man1 NROFF = nroff MANS = $(dist_man_MANS) ETAGS = etags CTAGS = ctags DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ ALSA_CFLAGS = @ALSA_CFLAGS@ ALSA_LIBS = @ALSA_LIBS@ ALSA_REQUIRED = @ALSA_REQUIRED@ AMTAR = @AMTAR@ AR = @AR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ BG_VERSION = @BG_VERSION@ BG_VERSION_MAJOR = @BG_VERSION_MAJOR@ BG_VERSION_MICRO = @BG_VERSION_MICRO@ BG_VERSION_MINOR = @BG_VERSION_MINOR@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CDDB_CFLAGS = @CDDB_CFLAGS@ CDDB_LIBS = @CDDB_LIBS@ CDIO_CDDA_CFLAGS = @CDIO_CDDA_CFLAGS@ CDIO_CDDA_LIBS = @CDIO_CDDA_LIBS@ CDIO_CFLAGS = @CDIO_CFLAGS@ CDIO_LIBS = @CDIO_LIBS@ CDIO_PARANOIA_CFLAGS = @CDIO_PARANOIA_CFLAGS@ CDIO_PARANOIA_LIBS = @CDIO_PARANOIA_LIBS@ CDIO_REQUIRED = @CDIO_REQUIRED@ CFLAGS = @CFLAGS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CYGPATH_W = @CYGPATH_W@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DOXYGEN = @DOXYGEN@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ ESD_CFLAGS = @ESD_CFLAGS@ ESD_CONFIG = @ESD_CONFIG@ ESD_LIBS = @ESD_LIBS@ ESD_REQUIRED = @ESD_REQUIRED@ EXEEXT = @EXEEXT@ FGREP = @FGREP@ FONTCONFIG_CFLAGS = @FONTCONFIG_CFLAGS@ FONTCONFIG_LIBS = @FONTCONFIG_LIBS@ FREETYPE_CFLAGS = @FREETYPE_CFLAGS@ FREETYPE_LIBS = @FREETYPE_LIBS@ GAVL_CFLAGS = @GAVL_CFLAGS@ GAVL_LIBS = @GAVL_LIBS@ GAVL_REQUIRED = @GAVL_REQUIRED@ GLX_CFLAGS = @GLX_CFLAGS@ GLX_LIBS = @GLX_LIBS@ GL_CFLAGS = @GL_CFLAGS@ GL_LIBS = @GL_LIBS@ GMERLIN_DEP_LIBS = @GMERLIN_DEP_LIBS@ GMERLIN_PLUGIN_LDFLAGS = @GMERLIN_PLUGIN_LDFLAGS@ GMSGFMT = @GMSGFMT@ GMSGFMT_015 = @GMSGFMT_015@ GREP = @GREP@ GTK_CFLAGS = @GTK_CFLAGS@ GTK_LIBS = @GTK_LIBS@ GTK_REQUIRED = @GTK_REQUIRED@ ICONV_LIBS = @ICONV_LIBS@ INCLUDES = -I$(top_srcdir)/include INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ INTLLIBS = @INTLLIBS@ INTL_MACOSX_LIBS = @INTL_MACOSX_LIBS@ JACK_CFLAGS = @JACK_CFLAGS@ JACK_LIBS = @JACK_LIBS@ JACK_REQUIRED = @JACK_REQUIRED@ JPEG_CFLAGS = @JPEG_CFLAGS@ JPEG_LIBS = @JPEG_LIBS@ JPEG_REQUIRED = @JPEG_REQUIRED@ LD = @LD@ LDFLAGS = @LDFLAGS@ LIBCDDB_REQUIRED = @LIBCDDB_REQUIRED@ LIBEXIF_CFLAGS = @LIBEXIF_CFLAGS@ LIBEXIF_LIBS = @LIBEXIF_LIBS@ LIBICONV = @LIBICONV@ LIBINTL = @LIBINTL@ LIBM = @LIBM@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIPO = @LIPO@ LN_S = @LN_S@ LQT_CFLAGS = @LQT_CFLAGS@ LQT_LIBS = @LQT_LIBS@ LQT_REQUIRED = @LQT_REQUIRED@ LTLIBICONV = @LTLIBICONV@ LTLIBINTL = @LTLIBINTL@ LTLIBOBJS = @LTLIBOBJS@ LTVERSION_AGE = @LTVERSION_AGE@ LTVERSION_CURRENT = @LTVERSION_CURRENT@ LTVERSION_REVISION = @LTVERSION_REVISION@ LV_CFLAGS = @LV_CFLAGS@ LV_LIBS = @LV_LIBS@ LV_REQUIRED = @LV_REQUIRED@ MAKEINFO = @MAKEINFO@ MKDIR_P = @MKDIR_P@ MODULE_LIBADD = @MODULE_LIBADD@ MSGFMT = @MSGFMT@ MSGFMT_015 = @MSGFMT_015@ MSGMERGE = @MSGMERGE@ MUSICBRAINZ_CFLAGS = @MUSICBRAINZ_CFLAGS@ MUSICBRAINZ_LIBS = @MUSICBRAINZ_LIBS@ MUSICBRAINZ_REQUIRED = @MUSICBRAINZ_REQUIRED@ NM = @NM@ NMEDIT = @NMEDIT@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OTOOL = @OTOOL@ OTOOL64 = @OTOOL64@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PKG_CONFIG = @PKG_CONFIG@ PNG_CFLAGS = @PNG_CFLAGS@ PNG_LIBS = @PNG_LIBS@ PNG_REQUIRED = @PNG_REQUIRED@ POSUB = @POSUB@ PULSEAUDIO_CFLAGS = @PULSEAUDIO_CFLAGS@ PULSEAUDIO_LIBS = @PULSEAUDIO_LIBS@ PULSEAUDIO_REQUIRED = @PULSEAUDIO_REQUIRED@ RANLIB = @RANLIB@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ SQLITE3_LIBS = @SQLITE3_LIBS@ STRIP = @STRIP@ TEXINFO = @TEXINFO@ TIFF_CFLAGS = @TIFF_CFLAGS@ TIFF_LIBS = @TIFF_LIBS@ TIFF_REQUIRED = @TIFF_REQUIRED@ TOP_SRCDIR = @TOP_SRCDIR@ USE_NLS = @USE_NLS@ V4LCONVERT_CFLAGS = @V4LCONVERT_CFLAGS@ V4LCONVERT_LIBS = @V4LCONVERT_LIBS@ V4LCONVERT_REQUIRED = @V4LCONVERT_REQUIRED@ VERSION = @VERSION@ XDPMS_LIBS = @XDPMS_LIBS@ XFIXES_LIBS = @XFIXES_LIBS@ XGETTEXT = @XGETTEXT@ XGETTEXT_015 = @XGETTEXT_015@ XINERAMA_LIBS = @XINERAMA_LIBS@ XMKMF = @XMKMF@ XML2_CFLAGS = @XML2_CFLAGS@ XML2_LIBS = @XML2_LIBS@ XML2_REQUIRED = @XML2_REQUIRED@ XTEST_LIBS = @XTEST_LIBS@ XV_LIBS = @XV_LIBS@ X_CFLAGS = @X_CFLAGS@ X_LIBS = @X_LIBS@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_CC = @ac_ct_CC@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_vendor = @build_vendor@ builddir = @builddir@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ lt_ECHO = @lt_ECHO@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ plugindir = $(pkglibdir)/plugins AM_CFLAGS = \ -DLOCALE_DIR=\"$(localedir)\" \ -DPLUGIN_DIR=\"$(plugindir)\" \ -DDOC_DIR=\"$(docdir)\" \ -DDATA_DIR=\"$(pkgdatadir)\" dist_man_MANS = gmerlin_play.1 gmerlin_play_LDADD = $(top_builddir)/lib/libgmerlin.la -ldl all: all-am .SUFFIXES: .SUFFIXES: .c .lo .o .obj $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ && { if test -f $@; then exit 0; else break; fi; }; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu apps/cmdlineplayer/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --gnu apps/cmdlineplayer/Makefile .PRECIOUS: Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): install-binPROGRAMS: $(bin_PROGRAMS) @$(NORMAL_INSTALL) test -z "$(bindir)" || $(MKDIR_P) "$(DESTDIR)$(bindir)" @list='$(bin_PROGRAMS)'; test -n "$(bindir)" || list=; \ for p in $$list; do echo "$$p $$p"; done | \ sed 's/$(EXEEXT)$$//' | \ while read p p1; do if test -f $$p || test -f $$p1; \ then echo "$$p"; echo "$$p"; else :; fi; \ done | \ sed -e 'p;s,.*/,,;n;h' -e 's|.*|.|' \ -e 'p;x;s,.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/' | \ sed 'N;N;N;s,\n, ,g' | \ $(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1 } \ { d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \ if ($$2 == $$4) files[d] = files[d] " " $$1; \ else { print "f", $$3 "/" $$4, $$1; } } \ END { for (d in files) print "f", d, files[d] }' | \ while read type dir files; do \ if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \ test -z "$$files" || { \ echo " $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files '$(DESTDIR)$(bindir)$$dir'"; \ $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files "$(DESTDIR)$(bindir)$$dir" || exit $$?; \ } \ ; done uninstall-binPROGRAMS: @$(NORMAL_UNINSTALL) @list='$(bin_PROGRAMS)'; test -n "$(bindir)" || list=; \ files=`for p in $$list; do echo "$$p"; done | \ sed -e 'h;s,^.*/,,;s/$(EXEEXT)$$//;$(transform)' \ -e 's/$$/$(EXEEXT)/' `; \ test -n "$$list" || exit 0; \ echo " ( cd '$(DESTDIR)$(bindir)' && rm -f" $$files ")"; \ cd "$(DESTDIR)$(bindir)" && rm -f $$files clean-binPROGRAMS: @list='$(bin_PROGRAMS)'; test -n "$$list" || exit 0; \ echo " rm -f" $$list; \ rm -f $$list || exit $$?; \ test -n "$(EXEEXT)" || exit 0; \ list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ echo " rm -f" $$list; \ rm -f $$list gmerlin_play$(EXEEXT): $(gmerlin_play_OBJECTS) $(gmerlin_play_DEPENDENCIES) @rm -f gmerlin_play$(EXEEXT) $(LINK) $(gmerlin_play_OBJECTS) $(gmerlin_play_LDADD) $(LIBS) mostlyclean-compile: -rm -f *.$(OBJEXT) distclean-compile: -rm -f *.tab.c @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gmerlin_play.Po@am__quote@ .c.o: @am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(COMPILE) -c $< .c.obj: @am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(COMPILE) -c `$(CYGPATH_W) '$<'` .c.lo: @am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(LTCOMPILE) -c -o $@ $< mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs install-man1: $(dist_man_MANS) @$(NORMAL_INSTALL) test -z "$(man1dir)" || $(MKDIR_P) "$(DESTDIR)$(man1dir)" @list=''; test -n "$(man1dir)" || exit 0; \ { for i in $$list; do echo "$$i"; done; \ l2='$(dist_man_MANS)'; for i in $$l2; do echo "$$i"; done | \ sed -n '/\.1[a-z]*$$/p'; \ } | while read p; do \ if test -f $$p; then d=; else d="$(srcdir)/"; fi; \ echo "$$d$$p"; echo "$$p"; \ done | \ sed -e 'n;s,.*/,,;p;h;s,.*\.,,;s,^[^1][0-9a-z]*$$,1,;x' \ -e 's,\.[0-9a-z]*$$,,;$(transform);G;s,\n,.,' | \ sed 'N;N;s,\n, ,g' | { \ list=; while read file base inst; do \ if test "$$base" = "$$inst"; then list="$$list $$file"; else \ echo " $(INSTALL_DATA) '$$file' '$(DESTDIR)$(man1dir)/$$inst'"; \ $(INSTALL_DATA) "$$file" "$(DESTDIR)$(man1dir)/$$inst" || exit $$?; \ fi; \ done; \ for i in $$list; do echo "$$i"; done | $(am__base_list) | \ while read files; do \ test -z "$$files" || { \ echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(man1dir)'"; \ $(INSTALL_DATA) $$files "$(DESTDIR)$(man1dir)" || exit $$?; }; \ done; } uninstall-man1: @$(NORMAL_UNINSTALL) @list=''; test -n "$(man1dir)" || exit 0; \ files=`{ for i in $$list; do echo "$$i"; done; \ l2='$(dist_man_MANS)'; for i in $$l2; do echo "$$i"; done | \ sed -n '/\.1[a-z]*$$/p'; \ } | sed -e 's,.*/,,;h;s,.*\.,,;s,^[^1][0-9a-z]*$$,1,;x' \ -e 's,\.[0-9a-z]*$$,,;$(transform);G;s,\n,.,'`; \ test -z "$$files" || { \ echo " ( cd '$(DESTDIR)$(man1dir)' && rm -f" $$files ")"; \ cd "$(DESTDIR)$(man1dir)" && rm -f $$files; } ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | \ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in files) print i; }; }'`; \ mkid -fID $$unique tags: TAGS TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ $(TAGS_FILES) $(LISP) set x; \ here=`pwd`; \ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | \ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in files) print i; }; }'`; \ shift; \ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ test -n "$$unique" || unique=$$empty_fix; \ if test $$# -gt 0; then \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ "$$@" $$unique; \ else \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ $$unique; \ fi; \ fi ctags: CTAGS CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ $(TAGS_FILES) $(LISP) list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | \ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in files) print i; }; }'`; \ test -z "$(CTAGS_ARGS)$$unique" \ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ $$unique GTAGS: here=`$(am__cd) $(top_builddir) && pwd` \ && $(am__cd) $(top_srcdir) \ && gtags -i $(GTAGS_ARGS) "$$here" distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags distdir: $(DISTFILES) @list='$(MANS)'; if test -n "$$list"; then \ list=`for p in $$list; do \ if test -f $$p; then d=; else d="$(srcdir)/"; fi; \ if test -f "$$d$$p"; then echo "$$d$$p"; else :; fi; done`; \ if test -n "$$list" && \ grep 'ab help2man is required to generate this page' $$list >/dev/null; then \ echo "error: found man pages containing the \`missing help2man' replacement text:" >&2; \ grep -l 'ab help2man is required to generate this page' $$list | sed 's/^/ /' >&2; \ echo " to fix them, install help2man, remove and regenerate the man pages;" >&2; \ echo " typically \`make maintainer-clean' will remove them" >&2; \ exit 1; \ else :; fi; \ else :; fi @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done check-am: all-am check: check-am all-am: Makefile $(PROGRAMS) $(MANS) installdirs: for dir in "$(DESTDIR)$(bindir)" "$(DESTDIR)$(man1dir)"; do \ test -z "$$dir" || $(MKDIR_P) "$$dir"; \ done install: install-am install-exec: install-exec-am install-data: install-data-am uninstall: uninstall-am install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-am install-strip: $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ `test -z '$(STRIP)' || \ echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install mostlyclean-generic: clean-generic: distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." clean: clean-am clean-am: clean-binPROGRAMS clean-generic clean-libtool mostlyclean-am distclean: distclean-am -rm -rf ./$(DEPDIR) -rm -f Makefile distclean-am: clean-am distclean-compile distclean-generic \ distclean-tags dvi: dvi-am dvi-am: html: html-am html-am: info: info-am info-am: install-data-am: install-man install-dvi: install-dvi-am install-dvi-am: install-exec-am: install-binPROGRAMS install-html: install-html-am install-html-am: install-info: install-info-am install-info-am: install-man: install-man1 install-pdf: install-pdf-am install-pdf-am: install-ps: install-ps-am install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-am -rm -rf ./$(DEPDIR) -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-compile mostlyclean-generic \ mostlyclean-libtool pdf: pdf-am pdf-am: ps: ps-am ps-am: uninstall-am: uninstall-binPROGRAMS uninstall-man uninstall-man: uninstall-man1 .MAKE: install-am install-strip .PHONY: CTAGS GTAGS all all-am check check-am clean clean-binPROGRAMS \ clean-generic clean-libtool ctags distclean distclean-compile \ distclean-generic distclean-libtool distclean-tags distdir dvi \ dvi-am html html-am info info-am install install-am \ install-binPROGRAMS install-data install-data-am install-dvi \ install-dvi-am install-exec install-exec-am install-html \ install-html-am install-info install-info-am install-man \ install-man1 install-pdf install-pdf-am install-ps \ install-ps-am install-strip installcheck installcheck-am \ installdirs maintainer-clean maintainer-clean-generic \ mostlyclean mostlyclean-compile mostlyclean-generic \ mostlyclean-libtool pdf pdf-am ps ps-am tags uninstall \ uninstall-am uninstall-binPROGRAMS uninstall-man \ uninstall-man1 # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: gmerlin-1.2.0~dfsg/apps/alsamixer/0000755000175000017500000000000011764363443017034 5ustar alessioalessiogmerlin-1.2.0~dfsg/apps/alsamixer/Makefile.am0000644000175000017500000000120411764363402021060 0ustar alessioalessioplugindir=$(pkglibdir)/plugins INCLUDES = -I$(top_srcdir)/include AM_CFLAGS = \ @XML2_CFLAGS@ \ @GTK_CFLAGS@ \ @ALSA_CFLAGS@ \ -DLOCALE_DIR=\"$(localedir)\" \ -DPLUGIN_DIR=\"$(plugindir)\" \ -DDOC_DIR=\"$(docdir)\" \ -DDATA_DIR=\"$(pkgdatadir)\" Desktopdir = $(datadir)/applications Desktop_DATA = gmerlin-alsamixer.desktop bin_PROGRAMS = gmerlin_alsamixer gmerlin_alsamixer_SOURCES = card.c main.c mixer.c g_control.c g_card.c g_mixer.c gmerlin_alsamixer_LDADD = $(top_builddir)/lib/libgmerlin.la $(top_builddir)/lib/gtk/libgmerlin_gtk.la @ALSA_LIBS@ -lpthread noinst_HEADERS = alsamixer.h gui.h EXTRA_DIST = gmerlin-alsamixer.desktop gmerlin-1.2.0~dfsg/apps/alsamixer/card.c0000644000175000017500000002407211764363402020111 0ustar alessioalessio/***************************************************************** * gmerlin - a general purpose multimedia framework and applications * * Copyright (c) 2001 - 2011 Members of the Gmerlin project * gmerlin-general@lists.sourceforge.net * http://gmerlin.sourceforge.net * * 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 of the License, 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 this program. If not, see . * *****************************************************************/ #include #include #include #include #define LOG_DOMAIN "card" #include "alsamixer.h" int alsa_mixer_control_read(alsa_mixer_control_t * c) { if(snd_hctl_elem_read(c->hctl, c->val)) { bg_log(BG_LOG_ERROR, LOG_DOMAIN, "snd_hctl_elem_read failed"); return 0; } return 1; } int alsa_mixer_control_write(alsa_mixer_control_t * c) { if(snd_hctl_elem_write(c->hctl, c->val)) { bg_log(BG_LOG_ERROR, LOG_DOMAIN, "snd_hctl_elem_write failed"); return 0; } return 1; } static alsa_mixer_group_t * get_group(alsa_card_t * c, const char * label) { int i; for(i = 0; i < c->num_groups; i++) { if(!strcmp(c->groups[i].label, label)) { return &c->groups[i]; } } c->num_groups++; c->groups = realloc(c->groups, c->num_groups * sizeof(*(c->groups))); memset(c->groups + (c->num_groups-1), 0, sizeof(*(c->groups))); c->groups[c->num_groups-1].label = bg_strdup(c->groups[c->num_groups-1].label, label); return &c->groups[c->num_groups-1]; } static alsa_mixer_control_t * create_control(snd_hctl_elem_t * hctl_elem) { alsa_mixer_control_t * ret; ret = calloc(1, sizeof(*ret)); ret->hctl = hctl_elem; snd_ctl_elem_value_malloc(&ret->val); alsa_mixer_control_read(ret); return ret; } alsa_card_t * alsa_card_create(int index) { char name[32]; alsa_card_t * card; int err; snd_hctl_elem_t * hctl_elem; snd_ctl_t * ctl; const char * element_name; snd_ctl_elem_info_t * info; snd_ctl_elem_id_t * id; snd_ctl_card_info_t * card_info; char ** strings; int num_strings; char * label; char * tmp_label; int done; // int is_bass = 0; // int is_treble = 0; // int is_tone_switch; int is_switch = 0; int is_volume = 0; int is_playback = 0; int is_capture = 0; int elem_index; int i; alsa_mixer_group_t * group; sprintf(name, "hw:%d", index); card = calloc(1, sizeof(*card)); if((err = snd_hctl_open(&card->hctl, name, 0))) { bg_log(BG_LOG_ERROR, LOG_DOMAIN, "snd_hctl_open failed"); goto fail; } if((err = snd_hctl_load(card->hctl)) < 0) { bg_log(BG_LOG_ERROR, LOG_DOMAIN, "snd_hctl_load failed"); goto fail; } ctl = snd_hctl_ctl(card->hctl); if(snd_ctl_card_info_malloc(&card_info)) { bg_log(BG_LOG_ERROR, LOG_DOMAIN, "snd_ctl_card_info_malloc failed"); goto fail; } if(snd_ctl_card_info(ctl, card_info)) { bg_log(BG_LOG_ERROR, LOG_DOMAIN, "snd_ctl_card_info failed"); goto fail; } card->name = bg_strdup(card->name, snd_ctl_card_info_get_mixername(card_info)); hctl_elem = snd_hctl_first_elem(card->hctl); while(hctl_elem) { done = 0; snd_ctl_elem_info_malloc(&info); snd_ctl_elem_id_malloc(&id); snd_hctl_elem_get_id(hctl_elem, id); // dump_ctl_elem_id(id); element_name = snd_ctl_elem_id_get_name(id); elem_index = snd_ctl_elem_id_get_index(id); /* Special case: Tone control */ if(!strcmp(element_name, "Tone Control - Switch")) { group = get_group(card, "Tone"); group->tone_switch = create_control(hctl_elem); done = 1; } else if(!strcmp(element_name, "Tone Control - Bass")) { group = get_group(card, "Tone"); group->tone_bass = create_control(hctl_elem); done = 1; } else if(!strcmp(element_name, "Tone Control - Treble")) { group = get_group(card, "Tone"); group->tone_treble = create_control(hctl_elem); done = 1; } if(done) { snd_ctl_elem_id_free(id); hctl_elem = snd_hctl_elem_next(hctl_elem); continue; } strings = bg_strbreak(element_name, ' '); num_strings = 0; while(strings[num_strings]) num_strings++; is_switch = 0; is_volume = 0; is_playback = 0; is_capture = 0; if(num_strings >= 2) { if(!strcmp(strings[num_strings-1], "Switch")) { is_switch = 1; num_strings--; } else if(!strcmp(strings[num_strings-1], "Volume")) { is_volume = 1; num_strings--; } if(!strcmp(strings[num_strings-1], "Playback")) { is_playback = 1; num_strings--; } else if(!strcmp(strings[num_strings-1], "Capture")) { is_capture = 1; num_strings--; } } if(num_strings) { label = NULL; for(i = 0; i < num_strings; i++) { label = bg_strcat(label, strings[i]); if(i < num_strings - 1) { label = bg_strcat(label, " "); } } } else if(is_capture && (is_volume || is_switch)) { label = bg_strdup(NULL, TR("Capture")); } else { label = bg_strdup(NULL, TR("Unknown")); } if(elem_index > 0) { tmp_label = bg_sprintf("%s %d", label, elem_index+1); free(label); label = tmp_label; } group = get_group(card, label); if(is_capture) { if(is_switch) group->capture_switch = create_control(hctl_elem); else if(is_volume) group->capture_volume = create_control(hctl_elem); else group->ctl = create_control(hctl_elem); } else if(is_playback) { if(is_switch) group->playback_switch = create_control(hctl_elem); else if(is_volume) group->playback_volume = create_control(hctl_elem); else group->ctl = create_control(hctl_elem); } else group->ctl = create_control(hctl_elem); free(label); bg_strbreak_free(strings); snd_ctl_elem_id_free(id); hctl_elem = snd_hctl_elem_next(hctl_elem); } return card; fail: alsa_card_destroy(card); return NULL; } void alsa_card_destroy(alsa_card_t * c) { free(c); } static void dump_ctl_elem_id(snd_ctl_elem_id_t * id) { FILE * out = stderr; fprintf(out, " ID:\n"); fprintf(out, " numid: %d\n", snd_ctl_elem_id_get_numid(id)); fprintf(out, " device: %d\n", snd_ctl_elem_id_get_device(id)); fprintf(out, " subdevice: %d\n", snd_ctl_elem_id_get_subdevice(id)); fprintf(out, " .name = %s\n", snd_ctl_elem_id_get_name(id)); fprintf(out, " index: %d\n", snd_ctl_elem_id_get_index(id)); fprintf(out, " interface: %s\n", snd_ctl_elem_iface_name(snd_ctl_elem_id_get_interface(id))); } static void dump_ctl_elem_info(snd_hctl_elem_t * hctl, snd_ctl_elem_info_t * info) { FILE * out = stderr; snd_ctl_elem_type_t type; int i, num_items; fprintf(out, " ELEM_INFO:\n"); type = snd_ctl_elem_info_get_type(info); fprintf(out, " Type: %s\n", snd_ctl_elem_type_name(type)); fprintf(out, " Owner: %d\n", snd_ctl_elem_info_get_owner(info)); fprintf(out, " Count: %d\n", snd_ctl_elem_info_get_count(info)); // fprintf(out, " : %d\n", snd_ctl_elem_info_get_count(info)); if(type == SND_CTL_ELEM_TYPE_INTEGER) { fprintf(out, " Min: %ld, Max: %ld, Step: %ld\n", snd_ctl_elem_info_get_min(info), snd_ctl_elem_info_get_max(info), snd_ctl_elem_info_get_step(info)); } else if(type == SND_CTL_ELEM_TYPE_INTEGER64) { fprintf(out, " Min: %lld, Max: %lld, Step: %lld\n", snd_ctl_elem_info_get_min64(info), snd_ctl_elem_info_get_max64(info), snd_ctl_elem_info_get_step64(info)); } else if(type == SND_CTL_ELEM_TYPE_ENUMERATED) { num_items = snd_ctl_elem_info_get_items(info); for(i = 0; i < num_items; i++) { snd_ctl_elem_info_set_item(info,i); snd_hctl_elem_info(hctl,info); fprintf(out, " Item %d: %s\n", i+1, snd_ctl_elem_info_get_item_name(info)); } } } static void dump_hctl_elem(snd_hctl_elem_t * h) { snd_ctl_elem_id_t * id; snd_ctl_elem_info_t * info; snd_ctl_elem_id_malloc(&id); snd_hctl_elem_get_id(h, id); dump_ctl_elem_id(id); snd_ctl_elem_id_free(id); snd_ctl_elem_info_malloc(&info); snd_hctl_elem_info(h, info); dump_ctl_elem_info(h, info); snd_ctl_elem_info_free(info); } static void dump_control(alsa_mixer_control_t * c) { FILE * out = stderr; fprintf(out, "HCTL:\n"); dump_hctl_elem(c->hctl); } static void dump_group(alsa_mixer_group_t * g) { FILE * out = stderr; if(g->playback_switch) { fprintf(out, "Playback switch:"); dump_control(g->playback_switch); } if(g->playback_volume) { fprintf(out, "Playback volume:\n"); dump_control(g->playback_volume); } if(g->capture_switch) { fprintf(out, "Capture switch:\n"); dump_control(g->capture_switch); } if(g->capture_volume) { fprintf(out, "Capture volume:\n"); dump_control(g->capture_volume); } if(g->ctl) { fprintf(out, "Control:\n"); dump_control(g->ctl); } } void alsa_card_dump(alsa_card_t * c) { int i; FILE * out = stderr; for(i = 0; i < c->num_groups; i++) { fprintf(out, "Group %d: %s\n", i+1, c->groups[i].label); dump_group(&c->groups[i]); } } gmerlin-1.2.0~dfsg/apps/alsamixer/main.c0000644000175000017500000000422011764363402020115 0ustar alessioalessio/***************************************************************** * gmerlin - a general purpose multimedia framework and applications * * Copyright (c) 2001 - 2011 Members of the Gmerlin project * gmerlin-general@lists.sourceforge.net * http://gmerlin.sourceforge.net * * 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 of the License, 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 this program. If not, see . * *****************************************************************/ #include #include #include #include #include "gui.h" #include #include static void nocards() { bg_gtk_message(TR("Could not find any Alsa mixers.\nCheck your setup!\n"), BG_GTK_MESSAGE_ERROR, NULL); exit(-1); } int main(int argc, char ** argv) { char * tmp_path; alsa_mixer_t * mixer; mixer_window_t * mixer_window; bg_cfg_registry_t * cfg_reg; cfg_reg = bg_cfg_registry_create(); tmp_path = bg_search_file_read("alsamixer", "config.xml"); bg_cfg_registry_load(cfg_reg, tmp_path); if(tmp_path) free(tmp_path); // alsa_mixer_dump(mixer); bg_gtk_init(&argc, &argv, "mixer_icon.png", NULL, NULL); mixer = alsa_mixer_create(); if(!mixer) { nocards(); } mixer_window = mixer_window_create(mixer, cfg_reg); mixer_window_run(mixer_window); mixer_window_destroy(mixer_window); alsa_mixer_destroy(mixer); /* Cleanup */ tmp_path = bg_search_file_write("alsamixer", "config.xml"); bg_cfg_registry_save(cfg_reg, tmp_path); if(tmp_path) free(tmp_path); bg_cfg_registry_destroy(cfg_reg); return 0; } gmerlin-1.2.0~dfsg/apps/alsamixer/gui.h0000644000175000017500000000716411764363402017774 0ustar alessioalessio/***************************************************************** * gmerlin - a general purpose multimedia framework and applications * * Copyright (c) 2001 - 2011 Members of the Gmerlin project * gmerlin-general@lists.sourceforge.net * http://gmerlin.sourceforge.net * * 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 of the License, 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 this program. If not, see . * *****************************************************************/ #include #include "alsamixer.h" #include typedef struct card_widget_s card_widget_t; /* Control widget */ typedef struct control_widget_s control_widget_t; control_widget_t * control_widget_create(alsa_mixer_group_t * c, bg_cfg_section_t * section, card_widget_t * card); void control_widget_destroy(control_widget_t *); GtkWidget * control_widget_get_widget(control_widget_t *); int control_widget_is_upper(control_widget_t *); int control_widget_get_index(control_widget_t *); void control_widget_set_index(control_widget_t *, int); int control_widget_get_own_window(control_widget_t *); void control_widget_set_own_window(control_widget_t *, int); void control_widget_set_parameter(void * data, const char * name, const bg_parameter_value_t * v); int control_widget_get_parameter(void * data, const char * name, bg_parameter_value_t * v); void control_widget_read_config(control_widget_t *); void control_widget_write_config(control_widget_t *); void control_widget_set_hidden(control_widget_t *, int hidden); int control_widget_get_hidden(control_widget_t *); const char * control_widget_get_label(control_widget_t *); /* Coords are handled by the card widgets, but the control widgets store them */ void control_widget_get_coords(control_widget_t *, int * x, int * y, int * width, int * height); void control_widget_set_coords(control_widget_t *, int x, int y, int width, int height); /* Card widget */ card_widget_t * card_widget_create(alsa_card_t * c, bg_cfg_section_t * section); void card_widget_destroy(card_widget_t *); GtkWidget * card_widget_get_widget(card_widget_t *); int card_widget_num_upper_controls(card_widget_t *); int card_widget_num_lower_controls(card_widget_t *); void card_widget_move_control_left(card_widget_t*, control_widget_t*); void card_widget_move_control_right(card_widget_t*, control_widget_t*); void card_widget_move_control_first(card_widget_t*, control_widget_t*); void card_widget_move_control_last(card_widget_t*, control_widget_t*); void card_widget_tearoff_control(card_widget_t*, control_widget_t*); void card_widget_tearon_control(card_widget_t*, control_widget_t*); void card_widget_get_window_coords(card_widget_t*); void card_widget_configure(card_widget_t *); /* Mixer window */ typedef struct mixer_window_s mixer_window_t; mixer_window_t * mixer_window_create(alsa_mixer_t * mixer, bg_cfg_registry_t * cfg_reg); void mixer_window_destroy(mixer_window_t *); void mixer_window_run(mixer_window_t *); gmerlin-1.2.0~dfsg/apps/alsamixer/g_card.c0000644000175000017500000004404211764363402020416 0ustar alessioalessio/***************************************************************** * gmerlin - a general purpose multimedia framework and applications * * Copyright (c) 2001 - 2011 Members of the Gmerlin project * gmerlin-general@lists.sourceforge.net * http://gmerlin.sourceforge.net * * 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 of the License, 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 this program. If not, see . * *****************************************************************/ #include #include #include #include "gui.h" #include #define LOWER_ROWS 3 #define TIMEOUT_INTERVAL 50 struct card_widget_s { char * label; int num_controls; int num_upper_controls; int num_lower_controls; control_widget_t ** controls; control_widget_t ** lower_controls; control_widget_t ** upper_controls; GtkWidget * upper_table; GtkWidget * w; snd_hctl_t *hctl; bg_cfg_section_t * section; GList * control_windows; }; static gboolean timeout_func(gpointer data) { card_widget_t * w; w = (card_widget_t *)data; snd_hctl_nonblock(w->hctl, 1); if(snd_hctl_wait(w->hctl, 1) >= 0) { snd_hctl_handle_events(w->hctl); } return TRUE; } static void sort_controls(control_widget_t ** controls, int num_controls) { int i, j; int keep_going; control_widget_t * tmp_widget; /* If the first index is -1, just give indices */ if(control_widget_get_index(controls[0]) == -1) { for(i = 0; i < num_controls; i++) control_widget_set_index(controls[i], i); } else /* Bubblesort */ { for(i = 0; i < num_controls-1; i++) { keep_going = 0; for(j = num_controls-1; j > i; j--) { if(control_widget_get_index(controls[j-1]) > control_widget_get_index(controls[j])) { tmp_widget = controls[j-1]; controls[j-1] = controls[j]; controls[j] = tmp_widget; keep_going = 1; } } if(!keep_going) break; } } } card_widget_t * card_widget_create(alsa_card_t * c, bg_cfg_section_t * section) { int i; GtkWidget * scrolledwin; GtkWidget * table; // GtkWidget * box; GtkWidget * w; GtkWidget * sep; int lower_cols; int upper_index = 0; int lower_index = 0; int row; int col; bg_cfg_section_t * subsection; card_widget_t * ret; ret = calloc(1, sizeof(*ret)); ret->controls = calloc(c->num_groups, sizeof(*(ret->controls))); ret->hctl = c->hctl; ret->label = bg_strdup(NULL, c->name); /* Create controls and count them */ for(i = 0; i < c->num_groups; i++) { subsection = bg_cfg_section_find_subsection(section, c->groups[i].label); ret->controls[ret->num_controls] = control_widget_create(&c->groups[i], subsection, ret); if(ret->controls[ret->num_controls]) { if(control_widget_is_upper(ret->controls[ret->num_controls])) ret->num_upper_controls++; else ret->num_lower_controls++; ret->num_controls++; } } if(ret->num_upper_controls) ret->upper_controls = calloc(ret->num_upper_controls, sizeof(*ret->upper_controls)); if(ret->num_lower_controls) ret->lower_controls = calloc(ret->num_lower_controls, sizeof(*ret->lower_controls)); /* Fill in the arrays for the upper and lower controls */ upper_index = 0; lower_index = 0; for(i = 0; i < ret->num_controls; i++) { control_widget_read_config(ret->controls[i]); if(control_widget_is_upper(ret->controls[i])) { ret->upper_controls[upper_index] = ret->controls[i]; upper_index++; } else { ret->lower_controls[lower_index] = ret->controls[i]; lower_index++; } } sort_controls(ret->upper_controls, ret->num_upper_controls); /* Pack the objects */ ret->w = gtk_vbox_new(0, 0); if(ret->num_upper_controls) { scrolledwin = gtk_scrolled_window_new(NULL, NULL); gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolledwin), GTK_POLICY_AUTOMATIC, GTK_POLICY_NEVER); ret->upper_table = gtk_table_new(1, 2 * ret->num_upper_controls - 1, 0); for(i = 0; i < ret->num_upper_controls; i++) { w = control_widget_get_widget(ret->upper_controls[i]); g_object_ref(G_OBJECT(w)); gtk_table_attach(GTK_TABLE(ret->upper_table), w, i*2, i*2+1, 0, 1, GTK_FILL|GTK_SHRINK, GTK_EXPAND|GTK_FILL, 0, 0); if(i < ret->num_upper_controls - 1) { sep = gtk_vseparator_new(); gtk_widget_show(sep); gtk_table_attach(GTK_TABLE(ret->upper_table), sep, i*2+1, i*2+2, 0, 1, GTK_FILL|GTK_SHRINK, GTK_EXPAND|GTK_FILL, 0, 0); } } gtk_widget_show(ret->upper_table); gtk_scrolled_window_add_with_viewport(GTK_SCROLLED_WINDOW(scrolledwin), ret->upper_table); gtk_widget_show(scrolledwin); bg_gtk_box_pack_start_defaults(GTK_BOX(ret->w), scrolledwin); } if(ret->num_lower_controls) { lower_cols = ((ret->num_lower_controls+LOWER_ROWS-1)/LOWER_ROWS); scrolledwin = gtk_scrolled_window_new(NULL, NULL); gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolledwin), GTK_POLICY_AUTOMATIC, GTK_POLICY_NEVER); table = gtk_table_new(LOWER_ROWS, lower_cols, FALSE); row = 0; col = 0; for(i = 0; i < ret->num_lower_controls; i++) { w = control_widget_get_widget(ret->lower_controls[i]); g_object_ref(G_OBJECT(w)); gtk_table_attach(GTK_TABLE(table), w, col, col+1, row, row+1, GTK_FILL, GTK_FILL, 0, 0); col++; if(col == lower_cols) { col = 0; row++; } } gtk_widget_show(table); gtk_scrolled_window_add_with_viewport(GTK_SCROLLED_WINDOW(scrolledwin), table); gtk_widget_show(scrolledwin); gtk_box_pack_start(GTK_BOX(ret->w), scrolledwin, FALSE, FALSE, 0); } /* Tear off controls */ for(i = 0; i < ret->num_upper_controls; i++) { if(control_widget_get_own_window(ret->upper_controls[i])) { card_widget_tearoff_control(ret, ret->upper_controls[i]); } } /* Add update callback */ g_timeout_add(TIMEOUT_INTERVAL, timeout_func, ret); gtk_widget_show(ret->w); return ret; } void card_widget_destroy(card_widget_t * w) { int i; for(i = 0; i < w->num_controls; i++) { control_widget_write_config(w->controls[i]); g_object_unref(G_OBJECT(control_widget_get_widget(w->controls[i]))); } if(w->label) free(w->label); free(w); } GtkWidget * card_widget_get_widget(card_widget_t * w) { return w->w; } int card_widget_num_upper_controls(card_widget_t * w) { return w->num_upper_controls; } int card_widget_num_lower_controls(card_widget_t * w) { return w->num_lower_controls; } /* Move functions */ static void move_left(card_widget_t * c, int index) { GtkWidget * wid; int new_index = index-1; wid = control_widget_get_widget(c->upper_controls[index]); c->upper_controls[new_index] = c->upper_controls[index]; if(!control_widget_get_own_window(c->upper_controls[index])) { gtk_container_remove(GTK_CONTAINER(c->upper_table), wid); gtk_table_attach_defaults(GTK_TABLE(c->upper_table), wid, new_index*2, new_index*2+1, 0, 1); } control_widget_set_index(c->upper_controls[new_index], new_index); } static void move_right(card_widget_t * c, int index) { GtkWidget * wid; int new_index = index+1; wid = control_widget_get_widget(c->upper_controls[index]); c->upper_controls[new_index] = c->upper_controls[index]; if(!control_widget_get_own_window(c->upper_controls[index])) { gtk_container_remove(GTK_CONTAINER(c->upper_table), wid); gtk_table_attach_defaults(GTK_TABLE(c->upper_table), wid, new_index*2, new_index*2+1, 0, 1); } control_widget_set_index(c->upper_controls[new_index], new_index); } void card_widget_move_control_left(card_widget_t * c, control_widget_t * w) { int oldpos, newpos; GtkWidget * wid; oldpos = control_widget_get_index(w); wid = control_widget_get_widget(w); /* Remove widget from table */ gtk_container_remove(GTK_CONTAINER(c->upper_table), wid); /* Move other widgets */ move_right(c, oldpos-1); /* Insert at new position */ newpos = oldpos - 1; c->upper_controls[newpos] = w; control_widget_set_index(c->upper_controls[newpos], newpos); gtk_table_attach_defaults(GTK_TABLE(c->upper_table), wid, newpos*2, newpos*2+1, 0, 1); } void card_widget_move_control_right(card_widget_t * c, control_widget_t * w) { int oldpos, newpos; GtkWidget * wid; oldpos = control_widget_get_index(w); wid = control_widget_get_widget(w); /* Remove widget from table */ gtk_container_remove(GTK_CONTAINER(c->upper_table), wid); /* Move other widgets */ move_left(c, oldpos+1); /* Insert at new position */ newpos = oldpos + 1; c->upper_controls[newpos] = w; control_widget_set_index(c->upper_controls[newpos], newpos); gtk_table_attach_defaults(GTK_TABLE(c->upper_table), wid, newpos*2, newpos*2+1, 0, 1); } void card_widget_move_control_first(card_widget_t * c, control_widget_t * w) { int oldpos, newpos, i; GtkWidget * wid; oldpos = control_widget_get_index(w); wid = control_widget_get_widget(w); /* Remove widget from table */ gtk_container_remove(GTK_CONTAINER(c->upper_table), wid); /* Move other widgets */ for(i = oldpos - 1; i >= 0; i--) { move_right(c, i); } /* Insert at new position */ newpos = 0; c->upper_controls[newpos] = w; control_widget_set_index(c->upper_controls[newpos], newpos); gtk_table_attach_defaults(GTK_TABLE(c->upper_table), wid, newpos*2, newpos*2+1, 0, 1); } void card_widget_move_control_last(card_widget_t * c, control_widget_t * w) { int oldpos, newpos, i; GtkWidget * wid; oldpos = control_widget_get_index(w); wid = control_widget_get_widget(w); /* Remove widget from table */ gtk_container_remove(GTK_CONTAINER(c->upper_table), wid); /* Move other widgets */ for(i = oldpos + 1; i < c->num_upper_controls; i++) { move_left(c, i); } /* Insert at new position */ newpos = c->num_upper_controls-1; c->upper_controls[newpos] = w; control_widget_set_index(c->upper_controls[newpos], newpos); gtk_table_attach_defaults(GTK_TABLE(c->upper_table), wid, newpos*2, newpos*2+1, 0, 1); } /* Stuff for own windows */ typedef struct { control_widget_t * control; card_widget_t * card; GtkWidget * window; } own_window_t; void card_widget_get_window_coords(card_widget_t * w) { int x, y, width, height; own_window_t * win; GList * item; item = w->control_windows; while(item) { win = (own_window_t*)(item->data); gtk_window_get_position(GTK_WINDOW(win->window), &x, &y); gtk_window_get_size(GTK_WINDOW(win->window), &width, &height); control_widget_set_coords(win->control, x, y, width, height); item = item->next; } } static gboolean delete_callback(GtkWidget * w, GdkEvent * evt, gpointer data) { own_window_t * win; win = (own_window_t*)data; card_widget_tearon_control(win->card, win->control); return FALSE; } static void unmap_callback(GtkWidget * w, gpointer data) { own_window_t * win; int x, y, width, height; win = (own_window_t*)data; gtk_window_get_position(GTK_WINDOW(win->window), &x, &y); gtk_window_get_size(GTK_WINDOW(win->window), &width, &height); control_widget_set_coords(win->control, x, y, width, height); } static void map_callback(GtkWidget * w, gpointer data) { int x, y, width, height; own_window_t * win; win = (own_window_t*)data; control_widget_get_coords(win->control, &x, &y, &width, &height); gtk_window_resize(GTK_WINDOW(win->window), width, height); gtk_window_move(GTK_WINDOW(win->window), x, y); } void card_widget_tearoff_control(card_widget_t * c, control_widget_t * w) { own_window_t * win; win = calloc(1, sizeof(*win)); win->control = w; win->card = c; c->control_windows = g_list_append(c->control_windows, win); gtk_container_remove(GTK_CONTAINER(c->upper_table), control_widget_get_widget(w)); win->window = bg_gtk_window_new(GTK_WINDOW_TOPLEVEL); gtk_window_set_title(GTK_WINDOW(win->window), "Gmerlin Alsamixer"); gtk_window_set_position(GTK_WINDOW(win->window), GTK_WIN_POS_CENTER); gtk_container_add(GTK_CONTAINER(win->window), control_widget_get_widget(w)); control_widget_set_own_window(w, 1); g_signal_connect(G_OBJECT(win->window), "delete-event", G_CALLBACK(delete_callback), win); g_signal_connect(G_OBJECT(win->window), "map", G_CALLBACK(map_callback), win); g_signal_connect(G_OBJECT(win->window), "unmap", G_CALLBACK(unmap_callback), win); gtk_widget_show(win->window); } void card_widget_tearon_control(card_widget_t * c, control_widget_t * w) { own_window_t * win = NULL; GList * item; int index; item = c->control_windows; while(item) { win = (own_window_t*)(item->data); if(w == win->control) break; item = item->next; } if(!win) return; gtk_widget_hide(win->window); gtk_container_remove(GTK_CONTAINER(win->window), control_widget_get_widget(win->control)); // g_object_unref(win->window); c->control_windows = g_list_remove(c->control_windows, win); free(win); index = control_widget_get_index(w); gtk_table_attach_defaults(GTK_TABLE(c->upper_table), control_widget_get_widget(w), index*2, index*2+1, 0, 1); control_widget_set_own_window(w, 0); } /* Configuration stuff */ typedef struct { card_widget_t * cw; GtkWidget ** control_buttons; GtkWidget * window; GtkWidget * close_button; } config_window; static void config_button_callback(GtkWidget * w, gpointer data) { config_window * win; win = (config_window *)data; gtk_widget_hide(win->window); gtk_main_quit(); // g_object_unref(win->window); free(win->control_buttons); free(win); } static void config_toggle_callback(GtkWidget * w, gpointer data) { int i; config_window * win; win = (config_window *)data; for(i = 0; i < win->cw->num_upper_controls; i++) { if(w == win->control_buttons[i]) { if(control_widget_get_own_window(win->cw->upper_controls[i])) { card_widget_tearon_control(win->cw, win->cw->upper_controls[i]); } control_widget_set_hidden(win->cw->upper_controls[i], !gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(win->control_buttons[i]))); } } } static gboolean config_delete_callback(GtkWidget * w, GdkEvent * evt, gpointer data) { config_button_callback(w, data); return TRUE; } void card_widget_configure(card_widget_t * c) { char * window_title; int i; config_window * win; GtkWidget * buttonbox; GtkWidget * mainbox; GtkWidget * scrolledwindow; win = calloc(1, sizeof(*win)); win->cw = c; win->window = bg_gtk_window_new(GTK_WINDOW_TOPLEVEL); gtk_window_set_title(GTK_WINDOW(win->window), TR("Card controls")); gtk_window_set_modal(GTK_WINDOW(win->window), 1); g_signal_connect(G_OBJECT(win->window), "delete_event",G_CALLBACK(config_delete_callback), win); window_title = bg_sprintf(TR("Controls for %s"), c->label); gtk_window_set_title(GTK_WINDOW(win->window), window_title); free(window_title); gtk_widget_set_size_request(win->window, 200, 300); gtk_window_set_position(GTK_WINDOW(win->window), GTK_WIN_POS_CENTER); /* Create buttons */ win->control_buttons = calloc(c->num_upper_controls, sizeof(*win->control_buttons)); buttonbox = gtk_vbox_new(1, 0); for(i = 0; i < c->num_upper_controls; i++) { win->control_buttons[i] = gtk_check_button_new_with_label(control_widget_get_label(c->upper_controls[i])); gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(win->control_buttons[i]), !control_widget_get_hidden(c->upper_controls[i])); g_signal_connect(G_OBJECT(win->control_buttons[i]), "toggled", G_CALLBACK(config_toggle_callback), win); gtk_widget_show(win->control_buttons[i]); bg_gtk_box_pack_start_defaults(GTK_BOX(buttonbox), win->control_buttons[i]); } gtk_widget_show(buttonbox); /* Close button */ win->close_button = gtk_button_new_from_stock(GTK_STOCK_CLOSE); g_signal_connect(G_OBJECT(win->close_button), "clicked", G_CALLBACK(config_button_callback), win); gtk_widget_show(win->close_button); scrolledwindow = gtk_scrolled_window_new(NULL, NULL); gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolledwindow), GTK_POLICY_NEVER, GTK_POLICY_ALWAYS); gtk_scrolled_window_add_with_viewport(GTK_SCROLLED_WINDOW(scrolledwindow), buttonbox); gtk_widget_show(scrolledwindow); mainbox = gtk_vbox_new(0, 5); bg_gtk_box_pack_start_defaults(GTK_BOX(mainbox), scrolledwindow); gtk_box_pack_start(GTK_BOX(mainbox), win->close_button, FALSE, FALSE, 0); gtk_widget_show(mainbox); gtk_container_add(GTK_CONTAINER(win->window), mainbox); gtk_widget_show(win->window); gtk_main(); } gmerlin-1.2.0~dfsg/apps/alsamixer/alsamixer.h0000644000175000017500000000406211764363402021167 0ustar alessioalessio/***************************************************************** * gmerlin - a general purpose multimedia framework and applications * * Copyright (c) 2001 - 2011 Members of the Gmerlin project * gmerlin-general@lists.sourceforge.net * http://gmerlin.sourceforge.net * * 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 of the License, 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 this program. If not, see . * *****************************************************************/ #include typedef struct { snd_hctl_elem_t * hctl; snd_ctl_elem_value_t * val; } alsa_mixer_control_t; int alsa_mixer_control_read(alsa_mixer_control_t*); int alsa_mixer_control_write(alsa_mixer_control_t*); typedef struct { char * label; alsa_mixer_control_t * playback_volume; alsa_mixer_control_t * playback_switch; alsa_mixer_control_t * capture_volume; alsa_mixer_control_t * capture_switch; alsa_mixer_control_t * tone_treble; alsa_mixer_control_t * tone_bass; alsa_mixer_control_t * tone_switch; alsa_mixer_control_t * ctl; /* For all others */ } alsa_mixer_group_t; typedef struct { char * name; int num_groups; alsa_mixer_group_t * groups; snd_ctl_card_info_t * card_info; snd_hctl_t * hctl; } alsa_card_t; alsa_card_t * alsa_card_create(int index); void alsa_card_destroy(alsa_card_t *); void alsa_card_dump(alsa_card_t *); typedef struct { int num_cards; alsa_card_t ** cards; } alsa_mixer_t; alsa_mixer_t * alsa_mixer_create(); void alsa_mixer_destroy(alsa_mixer_t *); void alsa_mixer_dump(alsa_mixer_t *); gmerlin-1.2.0~dfsg/apps/alsamixer/mixer.c0000644000175000017500000000343211764363402020321 0ustar alessioalessio/***************************************************************** * gmerlin - a general purpose multimedia framework and applications * * Copyright (c) 2001 - 2011 Members of the Gmerlin project * gmerlin-general@lists.sourceforge.net * http://gmerlin.sourceforge.net * * 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 of the License, 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 this program. If not, see . * *****************************************************************/ #include "alsamixer.h" alsa_mixer_t * alsa_mixer_create() { int i; alsa_mixer_t * ret; int card_index = -1; ret = calloc(1, sizeof(*ret)); while(!snd_card_next(&card_index)) { if(card_index > -1) ret->num_cards++; else break; } if(!ret->num_cards) { free(ret); return NULL; } ret->cards = calloc(ret->num_cards, sizeof(*ret->cards)); for(i = 0; i < ret->num_cards; i++) { ret->cards[i] = alsa_card_create(i); } return ret; } void alsa_mixer_destroy(alsa_mixer_t * m) { int i; for(i = 0; i < m->num_cards; i++) { alsa_card_destroy(m->cards[i]); } free(m->cards); free(m); } void alsa_mixer_dump(alsa_mixer_t * m) { int i; for(i = 0; i < m->num_cards; i++) { alsa_card_dump(m->cards[i]); } } gmerlin-1.2.0~dfsg/apps/alsamixer/g_control.c0000644000175000017500000013247711764363402021177 0ustar alessioalessio/***************************************************************** * gmerlin - a general purpose multimedia framework and applications * * Copyright (c) 2001 - 2011 Members of the Gmerlin project * gmerlin-general@lists.sourceforge.net * http://gmerlin.sourceforge.net * * 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 of the License, 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 this program. If not, see . * *****************************************************************/ #include #include #include #include #include "gui.h" #include #define LOG_DOMAIN "g_control" #include #include #if GTK_MINOR_VERSION >= 4 #define GTK_2_4 #endif #define SLIDER_HEIGHT 120 #define TYPE_SINGLEBOOL 0 #define TYPE_BOOL 1 #define TYPE_ENUM 2 #define TYPE_SINGLEENUM 3 #define TYPE_INTEGER 4 #define TYPE_INTEGER64 5 /* Combined types */ #define TYPE_VOLUME 16 #define TYPE_TONE 17 static bg_gtk_about_window_t * about_window = NULL; static void about_window_close_callback(bg_gtk_about_window_t * w, void * data) { about_window = NULL; } static GtkWidget * create_pixmap_toggle_button(const char * filename) { GtkWidget * button; GtkWidget * image; char * path; path = bg_search_file_read("icons", filename); if(path) { image = gtk_image_new_from_file(path); free(path); } else image = gtk_image_new(); gtk_widget_show(image); button = gtk_toggle_button_new(); gtk_container_add(GTK_CONTAINER(button), image); return button; } typedef struct { GtkWidget * w; GtkWidget * handler_widget; gulong id; /* ID of the signal handler */ } widget_t; static void widget_block(widget_t * w) { g_signal_handler_block(w->handler_widget, w->id); } static void widget_unblock(widget_t * w) { g_signal_handler_unblock(w->handler_widget, w->id); } typedef struct { int type; int num; widget_t * widgets; /* For sliders */ float val_min; float val_max; /* Combo box stuff */ #ifndef GTK_2_4 GList * popdown_strings; #endif /* Control */ alsa_mixer_control_t * control; /* Lock button */ GtkWidget * lock_button; int locked; } widget_array_t; /* Callbacks */ static void enum_callback(GtkWidget * w, gpointer data) { int index; int value; #ifndef GTK_2_4 GList * list; const char * label; #endif widget_array_t * arr = (widget_array_t *)data; for(index = 0; index < arr->num; index++) { #ifdef GTK_2_4 if(arr->widgets[index].w == w) break; #else if(GTK_COMBO(arr->widgets[index].w)->entry == w) break; #endif } if(index == arr->num) { return; } /* Get the string and the index of the enum */ #ifdef GTK_2_4 value = gtk_combo_box_get_active(GTK_COMBO_BOX(arr->widgets[index].w)); #else label = gtk_entry_get_text(GTK_ENTRY(GTK_COMBO(arr->widgets[index].w)->entry)); if(*label == '\0') return; list = arr->popdown_strings; value = 0; while(1) { if(!strcmp(list->data, label)) break; else { list = list->next; value++; } } #endif /* Transfer value */ snd_ctl_elem_value_set_enumerated(arr->control->val, index, value); /* Write value */ snd_hctl_elem_write(arr->control->hctl, arr->control->val); } static int hctl_enum_callback(snd_hctl_elem_t *elem, unsigned int mask) { int i; widget_array_t * arr; unsigned int value; #ifndef GTK_2_4 char * val_str; #endif if(mask & SND_CTL_EVENT_MASK_VALUE) { arr = (widget_array_t*)snd_hctl_elem_get_callback_private(elem); snd_hctl_elem_read(elem, arr->control->val); for(i = 0; i < arr->num; i++) { value = snd_ctl_elem_value_get_enumerated(arr->control->val, i); #ifdef GTK_2_4 widget_block(&arr->widgets[i]); gtk_combo_box_set_active(GTK_COMBO_BOX(arr->widgets[i].w), value); widget_unblock(&arr->widgets[i]); #else val_str = g_list_nth_data(arr->popdown_strings, value); widget_block(&arr->widgets[i]); gtk_entry_set_text(GTK_ENTRY(GTK_COMBO(arr->widgets[i].w)->entry), val_str); widget_unblock(&arr->widgets[i]); #endif } } return 0; } static void int_callback(GtkWidget * w, gpointer data) { int i; int index; int value; widget_array_t * arr = (widget_array_t *)data; for(index = 0; index < arr->num; index++) { if(arr->widgets[index].w == w) break; } if(index == arr->num) { return; } value = (int)(gtk_range_get_value(GTK_RANGE(arr->widgets[index].w))); widget_block(&arr->widgets[index]); gtk_range_set_value(GTK_RANGE(arr->widgets[index].w), (float)value); widget_unblock(&arr->widgets[index]); /* Transfer value */ snd_ctl_elem_value_set_integer(arr->control->val, index, value); if(arr->locked) { for(i = 0; i < arr->num; i++) { if(i == index) continue; widget_block(&arr->widgets[i]); gtk_range_set_value(GTK_RANGE(arr->widgets[i].w), (float)value); widget_unblock(&arr->widgets[i]); snd_ctl_elem_value_set_integer(arr->control->val, i, value); } } /* Write value */ snd_hctl_elem_write(arr->control->hctl, arr->control->val); } static int hctl_int_callback(snd_hctl_elem_t *elem, unsigned int mask) { int i; widget_array_t * arr; int value; if(mask & SND_CTL_EVENT_MASK_VALUE) { arr = (widget_array_t*)snd_hctl_elem_get_callback_private(elem); snd_hctl_elem_read(elem, arr->control->val); for(i = 0; i < arr->num; i++) { value = snd_ctl_elem_value_get_integer(arr->control->val, i); widget_block(&arr->widgets[i]); gtk_range_set_value(GTK_RANGE(arr->widgets[i].w), (float)value); widget_unblock(&arr->widgets[i]); } } return 0; } static void int64_callback(GtkWidget * w, gpointer data) { int index; int i; int64_t value; widget_array_t * arr = (widget_array_t *)data; for(index = 0; index < arr->num; index++) { if(arr->widgets[index].w == w) break; } if(index == arr->num) { return; } value = (int64_t)(gtk_range_get_value(GTK_RANGE(arr->widgets[index].w))); /* Transfer value */ snd_ctl_elem_value_set_integer64(arr->control->val, index, value); if(arr->locked) { for(i = 0; i < arr->num; i++) { if(i == index) continue; widget_block(&arr->widgets[i]); gtk_range_set_value(GTK_RANGE(arr->widgets[i].w), (float)value); widget_unblock(&arr->widgets[i]); snd_ctl_elem_value_set_integer64(arr->control->val, i, value); } } /* Write value */ snd_hctl_elem_write(arr->control->hctl, arr->control->val); } static int hctl_int64_callback(snd_hctl_elem_t *elem, unsigned int mask) { int i; widget_array_t * arr; int64_t value; if(mask & SND_CTL_EVENT_MASK_VALUE) { arr = (widget_array_t*)snd_hctl_elem_get_callback_private(elem); snd_hctl_elem_read(elem, arr->control->val); for(i = 0; i < arr->num; i++) { value = snd_ctl_elem_value_get_integer64(arr->control->val, i); widget_block(&arr->widgets[i]); gtk_range_set_value(GTK_RANGE(arr->widgets[i].w), (float)value); widget_unblock(&arr->widgets[i]); } } return 0; } static void bool_callback(GtkWidget * w, gpointer data) { int index; int value; widget_array_t * arr = (widget_array_t *)data; for(index = 0; index < arr->num; index++) { if(arr->widgets[index].w == w) break; } if(index == arr->num) { return; } value = (int)(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(arr->widgets[index].w))); /* Transfer value */ snd_ctl_elem_value_set_boolean(arr->control->val, index, value); /* Write value */ snd_hctl_elem_write(arr->control->hctl, arr->control->val); } static int hctl_bool_callback(snd_hctl_elem_t *elem, unsigned int mask) { int i; widget_array_t * arr; int value; if(mask & SND_CTL_EVENT_MASK_VALUE) { arr = (widget_array_t*)snd_hctl_elem_get_callback_private(elem); snd_hctl_elem_read(elem, arr->control->val); for(i = 0; i < arr->num; i++) { value = snd_ctl_elem_value_get_boolean(arr->control->val, i); widget_block(&arr->widgets[i]); gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(arr->widgets[i].w), value); widget_unblock(&arr->widgets[i]); } } return 0; } static void lock_callback(GtkWidget * w, gpointer data) { widget_array_t * arr = (widget_array_t *)data; arr->locked = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(w)); } static void init_array(widget_array_t * ret, alsa_mixer_control_t * c, snd_ctl_elem_info_t * _info, int lock_button) { int req_width, req_height; int i; #ifdef GTK_2_4 int j; #endif int num_items; snd_ctl_elem_type_t type; snd_ctl_elem_info_t * info; snd_hctl_elem_t * hctl = c->hctl; // ret if(_info) info = _info; else { snd_ctl_elem_info_malloc(&info); snd_hctl_elem_info(hctl, info); } ret->control = c; ret->num = snd_ctl_elem_info_get_count(info); type = snd_ctl_elem_info_get_type(info); ret->widgets = calloc(ret->num, sizeof(*(ret->widgets))); switch(type) { case SND_CTL_ELEM_TYPE_BOOLEAN: for(i = 0; i < ret->num; i++) { ret->widgets[i].w = gtk_toggle_button_new(); ret->widgets[i].id = g_signal_connect(G_OBJECT(ret->widgets[i].w), "toggled", G_CALLBACK(bool_callback), (gpointer)ret); ret->widgets[i].handler_widget = ret->widgets[i].w; gtk_widget_show(ret->widgets[i].w); } snd_hctl_elem_set_callback(c->hctl, hctl_bool_callback); snd_hctl_elem_set_callback_private(c->hctl, ret); hctl_bool_callback(c->hctl, SND_CTL_EVENT_MASK_VALUE); break; case SND_CTL_ELEM_TYPE_INTEGER64: ret->val_min = (float)snd_ctl_elem_info_get_min64(info); ret->val_max = (float)snd_ctl_elem_info_get_max64(info); for(i = 0; i < ret->num; i++) { ret->widgets[i].w = gtk_vscale_new_with_range(ret->val_min, ret->val_max, 1.0); gtk_widget_get_size_request(ret->widgets[i].w, &req_width, &req_height); gtk_widget_set_size_request(ret->widgets[i].w, req_width, SLIDER_HEIGHT); gtk_range_set_inverted(GTK_RANGE(ret->widgets[i].w), TRUE); ret->widgets[i].id = g_signal_connect(G_OBJECT(ret->widgets[i].w), "value_changed", G_CALLBACK(int64_callback), (gpointer)ret); ret->widgets[i].handler_widget = ret->widgets[i].w; gtk_scale_set_draw_value(GTK_SCALE(ret->widgets[i].w), 0); gtk_scale_set_digits(GTK_SCALE(ret->widgets[i].w), 0); gtk_widget_show(ret->widgets[i].w); } snd_hctl_elem_set_callback(c->hctl, hctl_int64_callback); snd_hctl_elem_set_callback_private(c->hctl, ret); hctl_int64_callback(c->hctl, SND_CTL_EVENT_MASK_VALUE); break; case SND_CTL_ELEM_TYPE_INTEGER: ret->val_min = (float)snd_ctl_elem_info_get_min(info); ret->val_max = (float)snd_ctl_elem_info_get_max(info); for(i = 0; i < ret->num; i++) { ret->widgets[i].w = gtk_vscale_new_with_range(ret->val_min, ret->val_max, 1.0); gtk_widget_get_size_request(ret->widgets[i].w, &req_width, &req_height); gtk_widget_set_size_request(ret->widgets[i].w, req_width, SLIDER_HEIGHT); gtk_range_set_inverted(GTK_RANGE(ret->widgets[i].w), TRUE); ret->widgets[i].id = g_signal_connect(G_OBJECT(ret->widgets[i].w), "value_changed", G_CALLBACK(int_callback), (gpointer)ret); ret->widgets[i].handler_widget = ret->widgets[i].w; gtk_scale_set_draw_value(GTK_SCALE(ret->widgets[i].w), 0); gtk_scale_set_digits(GTK_SCALE(ret->widgets[i].w), 0); gtk_widget_show(ret->widgets[i].w); } snd_hctl_elem_set_callback(c->hctl, hctl_int_callback); snd_hctl_elem_set_callback_private(c->hctl, ret); hctl_int_callback(c->hctl, SND_CTL_EVENT_MASK_VALUE); break; case SND_CTL_ELEM_TYPE_ENUMERATED: num_items = snd_ctl_elem_info_get_items(info); #ifndef GTK_2_4 for(i = 0; i < num_items; i++) { snd_ctl_elem_info_set_item(info,i); snd_hctl_elem_info(hctl,info); ret->popdown_strings = g_list_append(ret->popdown_strings, bg_strdup(NULL, snd_ctl_elem_info_get_item_name(info))); } #endif for(i = 0; i < ret->num; i++) { #ifdef GTK_2_4 ret->widgets[i].w = bg_gtk_combo_box_new_text(); ret->widgets[i].handler_widget = ret->widgets[i].w; for(j = 0; j < num_items; j++) { snd_ctl_elem_info_set_item(info,j); snd_hctl_elem_info(hctl,info); bg_gtk_combo_box_append_text(ret->widgets[i].w, snd_ctl_elem_info_get_item_name(info)); } ret->widgets[i].id = g_signal_connect(G_OBJECT(ret->widgets[i].w), "changed", G_CALLBACK(enum_callback), (gpointer)ret); #else ret->widgets[i].w = gtk_combo_new(); gtk_editable_set_editable(GTK_EDITABLE(GTK_COMBO(ret->widgets[i].w)->entry), FALSE); ret->widgets[i].handler_widget = GTK_COMBO(ret->widgets[i].w)->entry; gtk_combo_set_popdown_strings(GTK_COMBO(ret->widgets[i].w), ret->popdown_strings); /* The signal must be connected AFTER the popdown strings are set */ ret->widgets[i].id = g_signal_connect(G_OBJECT(GTK_EDITABLE(GTK_COMBO(ret->widgets[i].w)->entry)), "changed", G_CALLBACK(enum_callback), (gpointer)ret); #endif gtk_widget_show(ret->widgets[i].w); } snd_hctl_elem_set_callback(c->hctl, hctl_enum_callback); snd_hctl_elem_set_callback_private(c->hctl, ret); hctl_enum_callback(c->hctl, SND_CTL_EVENT_MASK_VALUE); break; case SND_CTL_ELEM_TYPE_NONE: case SND_CTL_ELEM_TYPE_BYTES: case SND_CTL_ELEM_TYPE_IEC958: break; } if(!_info) snd_ctl_elem_info_free(info); /* Create lock button */ if(lock_button && (ret->num > 1)) { ret->lock_button = create_pixmap_toggle_button("lock_16.png"); g_signal_connect(G_OBJECT(ret->lock_button), "toggled", G_CALLBACK(lock_callback), ret); gtk_widget_show(ret->lock_button); } } typedef struct { GtkWidget * left; GtkWidget * right; GtkWidget * first; GtkWidget * last; GtkWidget * tearoff; GtkWidget * config; GtkWidget * about; GtkWidget * help; GtkWidget * menu; } menu_t; struct control_widget_s { int type; char * label; union { struct { widget_array_t playback_sliders; widget_array_t capture_sliders; widget_array_t playback_switches; widget_array_t capture_switches; } volume; struct { widget_array_t treble; widget_array_t bass; widget_array_t switches; } tone; struct { widget_t checkbutton; alsa_mixer_control_t * control; } singlebool; struct { widget_array_t buttons; } bool; struct { widget_array_t combos; } enumerated; struct { widget_array_t sliders; alsa_mixer_control_t * control; } integer; } priv; GtkWidget * w; int upper; bg_cfg_section_t * section; bg_parameter_info_t * parameters; /* Index within the card widget (only for upper widgets) */ int index; card_widget_t * card; menu_t menu; /* True if we are in an own window */ int own_window; /* Coordinates for own window */ int x, y, width, height; /* True if we don't show this at all */ int hidden; }; static void menu_callback(GtkWidget * w, gpointer data) { control_widget_t * wid; wid = (control_widget_t *)data; if(w == wid->menu.left) { card_widget_move_control_left(wid->card, wid); } else if(w == wid->menu.right) { card_widget_move_control_right(wid->card, wid); } else if(w == wid->menu.first) { card_widget_move_control_first(wid->card, wid); } else if(w == wid->menu.last) { card_widget_move_control_last(wid->card, wid); } else if(w == wid->menu.tearoff) { card_widget_tearoff_control(wid->card, wid); } else if(w == wid->menu.config) { card_widget_configure(wid->card); // card_widget_tearoff_control(wid->card, wid); } else if(w == wid->menu.about) { about_window = bg_gtk_about_window_create("Gmerlin Alsamixer", VERSION, "mixer_icon.png", about_window_close_callback, NULL); } else if(w == wid->menu.help) bg_display_html_help("userguide/Alsamixer.html"); } static GtkWidget * create_pixmap_item(const char * filename, char * label) { GtkWidget * item; GtkWidget * image; char * path; path = bg_search_file_read("icons", filename); if(path) { image = gtk_image_new_from_file(path); free(path); } else image = gtk_image_new(); gtk_widget_show(image); item = gtk_image_menu_item_new_with_label(label); gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(item), image); return item; } static void init_menu(control_widget_t * w) { w->menu.left = create_pixmap_item("left_16.png", "Move control left by one"); w->menu.right = create_pixmap_item("right_16.png", "Move control right by one"); w->menu.first = create_pixmap_item("first_16.png", "Move control to the leftmost position"); w->menu.last = create_pixmap_item("last_16.png", "Move control to the rightmost position"); w->menu.tearoff = create_pixmap_item("windowed_16.png", "Detach control"); w->menu.config = create_pixmap_item("config_16.png", "Alsamixer options"); w->menu.about = create_pixmap_item("about_16.png", "About..."); w->menu.help = create_pixmap_item("help_16.png", "Userguide"); g_signal_connect(w->menu.left, "activate", G_CALLBACK(menu_callback), w); g_signal_connect(w->menu.right, "activate", G_CALLBACK(menu_callback), w); g_signal_connect(w->menu.first, "activate", G_CALLBACK(menu_callback), w); g_signal_connect(w->menu.last, "activate", G_CALLBACK(menu_callback), w); g_signal_connect(w->menu.tearoff, "activate", G_CALLBACK(menu_callback), w); g_signal_connect(w->menu.config, "activate", G_CALLBACK(menu_callback), w); g_signal_connect(w->menu.about, "activate", G_CALLBACK(menu_callback), w); g_signal_connect(w->menu.help, "activate", G_CALLBACK(menu_callback), w); gtk_widget_show(w->menu.left); gtk_widget_show(w->menu.right); gtk_widget_show(w->menu.first); gtk_widget_show(w->menu.last); gtk_widget_show(w->menu.tearoff); gtk_widget_show(w->menu.config); gtk_widget_show(w->menu.about); gtk_widget_show(w->menu.help); w->menu.menu = gtk_menu_new(); gtk_menu_shell_append(GTK_MENU_SHELL(w->menu.menu), w->menu.left); gtk_menu_shell_append(GTK_MENU_SHELL(w->menu.menu), w->menu.right); gtk_menu_shell_append(GTK_MENU_SHELL(w->menu.menu), w->menu.first); gtk_menu_shell_append(GTK_MENU_SHELL(w->menu.menu), w->menu.last); gtk_menu_shell_append(GTK_MENU_SHELL(w->menu.menu), w->menu.tearoff); gtk_menu_shell_append(GTK_MENU_SHELL(w->menu.menu), w->menu.config); gtk_menu_shell_append(GTK_MENU_SHELL(w->menu.menu), w->menu.about); gtk_menu_shell_append(GTK_MENU_SHELL(w->menu.menu), w->menu.help); gtk_widget_show(w->menu.menu); } int control_widget_get_index(control_widget_t * w) { return w->index; } void control_widget_set_index(control_widget_t * w, int index) { int leftmost; int rightmost; w->index = index; if(w->index == card_widget_num_upper_controls(w->card)-1) rightmost = 1; else rightmost = 0; if(!w->index) leftmost = 1; else leftmost = 0; if(w->menu.left) gtk_widget_set_sensitive(w->menu.left, !leftmost); if(w->menu.last) gtk_widget_set_sensitive(w->menu.last, !rightmost); if(w->menu.right) gtk_widget_set_sensitive(w->menu.right, !rightmost); if(w->menu.first) gtk_widget_set_sensitive(w->menu.first, !leftmost); } static void init_tone(control_widget_t * w, alsa_mixer_group_t * c) { GtkWidget * label; int row, num_rows; int num_cols; int i; num_rows = 1; num_cols = 0; if(c->tone_switch) { num_rows++; init_array(&w->priv.tone.switches, c->tone_switch, NULL, 0); if(w->priv.tone.switches.num > num_cols) num_cols = w->priv.tone.switches.num; } if(c->tone_bass) { num_rows+=2; init_array(&w->priv.tone.bass, c->tone_bass, NULL, 1); if(w->priv.tone.bass.num > num_cols) num_cols = w->priv.tone.bass.num; if(w->priv.tone.bass.num > 1) num_rows++; } if(c->tone_treble) { num_rows+=2; init_array(&w->priv.tone.treble, c->tone_treble, NULL, 1); if(w->priv.tone.treble.num > num_cols) num_cols = w->priv.tone.treble.num; if(w->priv.tone.treble.num > 1) num_rows++; } w->w = gtk_table_new(num_rows, num_cols, 0); row = 0; w->label = bg_strdup(w->label, TR("Tone")); label = gtk_label_new(w->label); gtk_widget_show(label); gtk_table_attach(GTK_TABLE(w->w), label, 0, num_cols, row, row+1, GTK_FILL, GTK_FILL, 0, 0); row++; /* Tone switch */ if(c->tone_switch) { if(w->priv.tone.switches.num == 1) { gtk_table_attach(GTK_TABLE(w->w), w->priv.tone.switches.widgets[0].w, 0, num_cols, row, row+1, GTK_FILL, GTK_FILL, 0, 0); } else { for(i = 0; i < w->priv.tone.switches.num; i++) { gtk_table_attach(GTK_TABLE(w->w), w->priv.tone.switches.widgets[i].w, i, i+1, row, row+1, GTK_FILL, GTK_FILL, 0, 0); } } row++; } if(c->tone_treble) { label = gtk_label_new(TR("Treble")); gtk_widget_show(label); gtk_table_attach(GTK_TABLE(w->w), label, 0, num_cols, row, row+1, GTK_FILL, GTK_FILL, 0, 0); row++; if(w->priv.tone.treble.num == 1) { gtk_table_attach_defaults(GTK_TABLE(w->w), w->priv.tone.treble.widgets[0].w, 0, num_cols, row, row+1); } else { for(i = 0; i < w->priv.tone.treble.num; i++) { gtk_table_attach_defaults(GTK_TABLE(w->w), w->priv.tone.treble.widgets[i].w, i, i+1, row, row+1); } row++; gtk_table_attach(GTK_TABLE(w->w), w->priv.tone.treble.lock_button, 0, num_cols, row, row+1, GTK_FILL, GTK_FILL, 0, 0); } row++; } if(c->tone_bass) { label = gtk_label_new(TR("Bass")); gtk_widget_show(label); gtk_table_attach(GTK_TABLE(w->w), label, 0, num_cols, row, row+1, GTK_FILL, GTK_FILL, 0, 0); row++; if(w->priv.tone.bass.num == 1) { gtk_table_attach_defaults(GTK_TABLE(w->w), w->priv.tone.bass.widgets[0].w, 0, num_cols, row, row+1); } else { for(i = 0; i < w->priv.tone.bass.num; i++) { gtk_table_attach_defaults(GTK_TABLE(w->w), w->priv.tone.bass.widgets[i].w, i, i+1, row, row+1); } row++; gtk_table_attach(GTK_TABLE(w->w), w->priv.tone.bass.lock_button, 0, num_cols, row, row+1, GTK_FILL, GTK_FILL, 0, 0); } row++; } gtk_widget_show(w->w); w->upper = 1; } static void init_volume(control_widget_t * w, alsa_mixer_group_t * c) { int i; GtkWidget * label; int capture_width; int playback_width; int num_rows; if(c->playback_switch) { init_array(&w->priv.volume.playback_switches, c->playback_switch, NULL, 0); } if(c->playback_volume) { init_array(&w->priv.volume.playback_sliders, c->playback_volume, NULL, 1); } if(c->capture_volume) { init_array(&w->priv.volume.capture_sliders, c->capture_volume, NULL, 1); } if(c->capture_switch) { init_array(&w->priv.volume.capture_switches, c->capture_switch, NULL, 0); } /* Pack the objects */ capture_width = w->priv.volume.capture_sliders.num > w->priv.volume.capture_switches.num ? w->priv.volume.capture_sliders.num : w->priv.volume.capture_switches.num; playback_width = w->priv.volume.playback_sliders.num > w->priv.volume.playback_switches.num ? w->priv.volume.playback_sliders.num : w->priv.volume.playback_switches.num; num_rows = 4; if((w->priv.volume.playback_sliders.num > 1) && (w->priv.volume.capture_sliders.num > 1)) num_rows++; w->w = gtk_table_new(4, capture_width + playback_width, 0); w->label = bg_strdup(w->label, c->label); label = gtk_label_new(w->label); gtk_widget_show(label); gtk_table_attach(GTK_TABLE(w->w), label, 0, capture_width + playback_width, 0, 1, GTK_FILL, GTK_FILL, 0, 0); /* Save label */ if(capture_width) { label = gtk_label_new(TR("Rec")); gtk_widget_show(label); gtk_table_attach(GTK_TABLE(w->w), label, 0, capture_width, 1, 2, GTK_FILL, GTK_FILL, 0, 0); /* Capture Switches */ if(w->priv.volume.capture_switches.num == 1) { gtk_table_attach(GTK_TABLE(w->w), w->priv.volume.capture_switches.widgets[0].w, 0, capture_width, 2, 3, GTK_FILL, GTK_FILL, 0, 0); } else { for(i = 0; i < w->priv.volume.capture_switches.num; i++) { gtk_table_attach(GTK_TABLE(w->w), w->priv.volume.capture_switches.widgets[i].w, i, i + 1, 2, 3, GTK_FILL, GTK_FILL, 0, 0); } } /* Capture Sliders */ for(i = 0; i < w->priv.volume.capture_sliders.num; i++) { gtk_table_attach_defaults(GTK_TABLE(w->w), w->priv.volume.capture_sliders.widgets[i].w, i, i + 1, 3, 4); } if(w->priv.volume.capture_sliders.num > 1) { gtk_table_attach(GTK_TABLE(w->w), w->priv.volume.capture_sliders.lock_button, 0, w->priv.volume.capture_sliders.num, 4, 5, GTK_FILL, GTK_FILL, 0, 0); } } if(playback_width) { label = gtk_label_new(TR("Play")); gtk_widget_show(label); gtk_table_attach(GTK_TABLE(w->w), label, capture_width, capture_width + playback_width, 1, 2, GTK_FILL, GTK_FILL, 0, 0); /* Playback Switches */ if(w->priv.volume.playback_switches.num == 1) { gtk_table_attach(GTK_TABLE(w->w), w->priv.volume.playback_switches.widgets[0].w, capture_width, capture_width + playback_width, 2, 3, GTK_FILL, GTK_FILL, 0, 0); } else for(i = 0; i < w->priv.volume.playback_switches.num; i++) { gtk_table_attach(GTK_TABLE(w->w), w->priv.volume.playback_switches.widgets[i].w, capture_width + i, capture_width + i + 1, 2, 3, GTK_FILL, GTK_FILL, 0, 0); } /* Playback Sliders */ for(i = 0; i < w->priv.volume.playback_sliders.num; i++) { gtk_table_attach_defaults(GTK_TABLE(w->w), w->priv.volume.playback_sliders.widgets[i].w, capture_width + i, capture_width + i + 1, 3, 4); } if(w->priv.volume.playback_sliders.num > 1) { gtk_table_attach(GTK_TABLE(w->w), w->priv.volume.playback_sliders.lock_button, capture_width, capture_width+ w->priv.volume.playback_sliders.num, 4, 5, GTK_FILL, GTK_FILL, 0, 0); } } gtk_widget_show(w->w); w->upper = 1; } static int hctl_singlebool_callback(snd_hctl_elem_t *elem, unsigned int mask) { control_widget_t * c; int value; if(mask & SND_CTL_EVENT_MASK_VALUE) { c = (control_widget_t*)snd_hctl_elem_get_callback_private(elem); snd_hctl_elem_read(elem, c->priv.singlebool.control->val); value = snd_ctl_elem_value_get_boolean(c->priv.singlebool.control->val, 0); widget_block(&c->priv.singlebool.checkbutton); gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(c->priv.singlebool.checkbutton.w), value); widget_unblock(&c->priv.singlebool.checkbutton); } return 0; } static void singlebool_callback(GtkWidget * w, gpointer data) { int value; control_widget_t * c = (control_widget_t *)data; value = (int)(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(c->priv.singlebool.checkbutton.w))); snd_ctl_elem_value_set_boolean(c->priv.singlebool.control->val, 0, value); /* Write value */ snd_hctl_elem_write(c->priv.singlebool.control->hctl, c->priv.singlebool.control->val); } static void init_singlebool(control_widget_t * w, alsa_mixer_group_t * c, snd_ctl_elem_info_t * info) { w->priv.singlebool.checkbutton.w = gtk_toggle_button_new_with_label(c->label); gtk_widget_show(w->priv.singlebool.checkbutton.w); w->priv.singlebool.checkbutton.id = g_signal_connect(G_OBJECT(w->priv.singlebool.checkbutton.w), "toggled", G_CALLBACK(singlebool_callback), w); w->priv.singlebool.checkbutton.handler_widget = w->priv.singlebool.checkbutton.w; w->priv.singlebool.control = c->ctl; w->w = w->priv.singlebool.checkbutton.w; snd_hctl_elem_set_callback(c->ctl->hctl, hctl_singlebool_callback); snd_hctl_elem_set_callback_private(c->ctl->hctl, w); hctl_singlebool_callback(c->ctl->hctl, SND_CTL_EVENT_MASK_VALUE); w->priv.singlebool.control = c->ctl; } static void init_integer(control_widget_t * w, alsa_mixer_group_t * c, snd_ctl_elem_info_t * info) { int i; GtkWidget * label; init_array(&w->priv.integer.sliders, c->ctl, info, 0); w->w = gtk_table_new(2, w->priv.integer.sliders.num, 0); w->label = bg_strdup(w->label, c->label); label = gtk_label_new(w->label); gtk_widget_show(label); gtk_table_attach(GTK_TABLE(w->w), label, 0, w->priv.integer.sliders.num, 0, 1, GTK_FILL, GTK_FILL, 0, 0); for(i = 0; i < w->priv.integer.sliders.num; i++) { gtk_table_attach_defaults(GTK_TABLE(w->w), w->priv.integer.sliders.widgets[i].w, i, i+1, 1, 2); } gtk_widget_show(w->w); w->upper = 1; } static void init_bool(control_widget_t * w, alsa_mixer_group_t * c, snd_ctl_elem_info_t * info) { int i; GtkWidget * label; init_array(&w->priv.bool.buttons, c->ctl, info, 0); w->w = gtk_table_new(w->priv.bool.buttons.num + 1, 1, 0); w->label = bg_strdup(w->label, c->label); label = gtk_label_new(w->label); gtk_widget_show(label); gtk_table_attach(GTK_TABLE(w->w), label, 0, 1, 0, 1, GTK_FILL, GTK_FILL, 0, 0); init_array(&w->priv.bool.buttons, c->ctl, info, 0); for(i = 0; i < w->priv.bool.buttons.num; i++) { gtk_table_attach(GTK_TABLE(w->w), w->priv.bool.buttons.widgets[i].w, 0, 1, i+1, i+2, GTK_FILL, GTK_FILL, 0, 0); } gtk_widget_show(w->w); w->upper = 1; } static void init_enumerated(control_widget_t * w, alsa_mixer_group_t * c, snd_ctl_elem_info_t * info) { GtkWidget * label; int i; init_array(&w->priv.enumerated.combos, c->ctl, info, 0); w->w = gtk_table_new(w->priv.enumerated.combos.num + 1, 1, 0); w->label = bg_strdup(w->label, c->label); label = gtk_label_new(w->label); gtk_widget_show(label); gtk_table_attach(GTK_TABLE(w->w), label, 0, 1, 0, 1, GTK_FILL, GTK_FILL, 0, 0); for(i = 0; i < w->priv.enumerated.combos.num; i++) { gtk_table_attach(GTK_TABLE(w->w), w->priv.enumerated.combos.widgets[i].w, 0, 1, i+1, i+2, GTK_FILL, GTK_FILL, 0, 0); } gtk_widget_show(w->w); w->upper = 1; } static void init_singleenumerated(control_widget_t * w, alsa_mixer_group_t * c, snd_ctl_elem_info_t * info) { GtkWidget * label; init_array(&w->priv.enumerated.combos, c->ctl, info, 0); w->w = gtk_table_new(1, 2, 0); label = gtk_label_new(c->label); gtk_widget_show(label); gtk_table_attach(GTK_TABLE(w->w), label, 0, 1, 0, 1, GTK_FILL, GTK_FILL, 0, 0); gtk_table_attach_defaults(GTK_TABLE(w->w), w->priv.enumerated.combos.widgets[0].w, 1, 2, 0, 1); gtk_widget_show(w->w); } static gboolean button_press_callback(GtkWidget * w, GdkEventButton * evt, gpointer data) { control_widget_t * wid; wid = (control_widget_t*)data; /* No menu of we are in an own window */ if(wid->own_window) return FALSE; if(evt->button == 3) { if(about_window) gtk_widget_set_sensitive(wid->menu.about, 0); else gtk_widget_set_sensitive(wid->menu.about, 1); gtk_menu_popup(GTK_MENU(wid->menu.menu), NULL, NULL, NULL, NULL, 3, evt->time); return TRUE; } return FALSE; } static void make_moveable(control_widget_t * w) { GtkWidget * event_box; init_menu(w); event_box = gtk_event_box_new(); gtk_widget_set_events(event_box, GDK_BUTTON_PRESS_MASK); g_signal_connect(G_OBJECT(event_box), "button-press-event", G_CALLBACK(button_press_callback), (gpointer)w); gtk_container_add(GTK_CONTAINER(event_box), w->w); gtk_widget_show(event_box); w->w = event_box; } control_widget_t * control_widget_create(alsa_mixer_group_t * c, bg_cfg_section_t * section, card_widget_t * card) { snd_ctl_elem_info_t * info; control_widget_t * ret = NULL; snd_ctl_elem_type_t type; /* Check for volume controls */ if((c->playback_volume) || (c->capture_volume) || (c->playback_switch && c->capture_switch)) { ret = calloc(1, sizeof(*ret)); init_volume(ret, c); ret->type = TYPE_VOLUME; } else if(c->playback_switch && !c->capture_switch) { c->ctl = c->playback_switch; c->playback_switch = NULL; } else if(!c->playback_switch && c->capture_switch) { c->ctl = c->capture_switch; c->capture_switch = NULL; } else if(c->tone_bass || c->tone_treble) { ret = calloc(1, sizeof(*ret)); init_tone(ret, c); ret->type = TYPE_TONE; } if(!ret) { snd_ctl_elem_info_malloc(&info); snd_hctl_elem_info(c->ctl->hctl, info); type = snd_ctl_elem_info_get_type(info); switch(type) { case SND_CTL_ELEM_TYPE_BOOLEAN: if(snd_ctl_elem_info_get_count(info) > 1) { ret = calloc(1, sizeof(*ret)); init_bool(ret, c, info); ret->type = TYPE_BOOL; } else { ret = calloc(1, sizeof(*ret)); init_singlebool(ret, c, info); ret->type = TYPE_SINGLEBOOL; } break; case SND_CTL_ELEM_TYPE_INTEGER: if(snd_ctl_elem_info_get_min(info) >= snd_ctl_elem_info_get_max(info)) { break; } ret = calloc(1, sizeof(*ret)); init_integer(ret, c, info); ret->type = TYPE_INTEGER; break; case SND_CTL_ELEM_TYPE_ENUMERATED: if(snd_ctl_elem_info_get_count(info) > 1) { ret = calloc(1, sizeof(*ret)); init_enumerated(ret, c, info); } else { ret = calloc(1, sizeof(*ret)); init_singleenumerated(ret, c, info); } ret->type = TYPE_ENUM; break; case SND_CTL_ELEM_TYPE_INTEGER64: if(snd_ctl_elem_info_get_min64(info) >= snd_ctl_elem_info_get_max64(info)) { break; } ret = calloc(1, sizeof(*ret)); init_integer(ret, c, info); ret->type = TYPE_INTEGER64; break; case SND_CTL_ELEM_TYPE_NONE: case SND_CTL_ELEM_TYPE_BYTES: case SND_CTL_ELEM_TYPE_IEC958: bg_log(BG_LOG_WARNING, LOG_DOMAIN, "Type %s not handled for %s", snd_ctl_elem_type_name(type), c->label); break; } snd_ctl_elem_info_free(info); } if(ret) { ret->section = section; ret->card = card; /* Check, if we are movable */ if(ret->upper) make_moveable(ret); } return ret; } int control_widget_is_upper(control_widget_t * w) { return w->upper; } void control_widget_destroy(control_widget_t * w) { if(w->label) free(w->label); free(w); } GtkWidget * control_widget_get_widget(control_widget_t * w) { return w->w; } static const bg_parameter_info_t playback_lock_param = { .name = "playback_locked", .type = BG_PARAMETER_CHECKBUTTON, .val_default = { .val_i = 1 } }; static const bg_parameter_info_t capture_lock_param = { .name = "capture_locked", .type = BG_PARAMETER_CHECKBUTTON, .val_default = { .val_i = 1 } }; static const bg_parameter_info_t bass_lock_param = { .name = "bass_locked", .type = BG_PARAMETER_CHECKBUTTON, .val_default = { .val_i = 1 } }; static const bg_parameter_info_t treble_lock_param = { .name = "treble_locked", .type = BG_PARAMETER_CHECKBUTTON, .val_default = { .val_i = 1 } }; static const bg_parameter_info_t upper_params[] = { { .name = "hidden", .type = BG_PARAMETER_INT, .val_default = { .val_i = 0 } }, { .name = "index", .type = BG_PARAMETER_INT, .val_default = { .val_i = -1 } }, { .name = "own_window", .type = BG_PARAMETER_CHECKBUTTON, .val_default = { .val_i = 0 } }, { .name = "x", .type = BG_PARAMETER_INT, .val_default = { .val_i = 100 } }, { .name = "y", .type = BG_PARAMETER_INT, .val_default = { .val_i = 100 } }, { .name = "width", .type = BG_PARAMETER_INT, .val_default = { .val_i = 20 } }, { .name = "height", .type = BG_PARAMETER_INT, .val_default = { .val_i = 100 } }, }; static void create_parameters(control_widget_t * w) { int i, j; int num_parameters = 0; if(w->upper) /* Index */ { num_parameters+=7; } if(w->type == TYPE_VOLUME) { if(w->priv.volume.capture_sliders.lock_button) num_parameters++; if(w->priv.volume.playback_sliders.lock_button) num_parameters++; } if(w->type == TYPE_TONE) { if(w->priv.tone.bass.lock_button) num_parameters++; if(w->priv.tone.treble.lock_button) num_parameters++; } w->parameters = calloc(num_parameters+1, sizeof(*w->parameters)); i = 0; if(w->upper) { for(j = 0; j < 7; j++) { bg_parameter_info_copy(&w->parameters[i], &upper_params[j]); i++; } } if(w->type == TYPE_VOLUME) { if(w->priv.volume.capture_sliders.lock_button) { bg_parameter_info_copy(&w->parameters[i], &capture_lock_param); i++; } if(w->priv.volume.playback_sliders.lock_button) { bg_parameter_info_copy(&w->parameters[i], &playback_lock_param); i++; } } if(w->type == TYPE_TONE) { if(w->priv.tone.bass.lock_button) { bg_parameter_info_copy(&w->parameters[i], &bass_lock_param); i++; } if(w->priv.tone.treble.lock_button) { bg_parameter_info_copy(&w->parameters[i], &treble_lock_param); i++; } } } void control_widget_set_parameter(void * data, const char * name, const bg_parameter_value_t * v) { control_widget_t * w; w = (control_widget_t*)data; if(!name) return; if(!strcmp(name, "playback_locked")) { gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(w->priv.volume.playback_sliders.lock_button), v->val_i); } if(!strcmp(name, "capture_locked")) { gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(w->priv.volume.capture_sliders.lock_button), v->val_i); } if(!strcmp(name, "bass_locked")) { gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(w->priv.tone.bass.lock_button), v->val_i); } if(!strcmp(name, "treble_locked")) { gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(w->priv.tone.treble.lock_button), v->val_i); } if(!strcmp(name, "index")) { control_widget_set_index(w, v->val_i); } if(!strcmp(name, "own_window")) { w->own_window = v->val_i; } if(!strcmp(name, "x")) { w->x = v->val_i; } if(!strcmp(name, "y")) { w->y = v->val_i; } if(!strcmp(name, "width")) { w->width = v->val_i; } if(!strcmp(name, "height")) { w->height = v->val_i; } if(!strcmp(name, "hidden")) { // w->hidden = v->val_i; control_widget_set_hidden(w, v->val_i); } } int control_widget_get_parameter(void * data, const char * name, bg_parameter_value_t * v) { control_widget_t * w; w = (control_widget_t*)data; if(!strcmp(name, "playback_locked")) { v->val_i = w->priv.volume.playback_sliders.locked; return 1; } if(!strcmp(name, "capture_locked")) { v->val_i = w->priv.volume.capture_sliders.locked; return 1; } if(!strcmp(name, "bass_locked")) { v->val_i = w->priv.tone.bass.locked; return 1; } if(!strcmp(name, "treble_locked")) { v->val_i = w->priv.tone.treble.locked; return 1; } if(!strcmp(name, "index")) { v->val_i = w->index; return 1; } if(!strcmp(name, "own_window")) { v->val_i = w->own_window; } if(!strcmp(name, "x")) { v->val_i = w->x; } if(!strcmp(name, "y")) { v->val_i = w->y; } if(!strcmp(name, "width")) { v->val_i = w->width; } if(!strcmp(name, "height")) { v->val_i = w->height; } if(!strcmp(name, "hidden")) { v->val_i = w->hidden; } return 0; } void control_widget_read_config(control_widget_t * w) { if(!w->parameters) create_parameters(w); bg_cfg_section_apply(w->section, w->parameters, control_widget_set_parameter, w); } void control_widget_write_config(control_widget_t * w) { if(!w->parameters) create_parameters(w); bg_cfg_section_get(w->section, w->parameters, control_widget_get_parameter, w); } int control_widget_get_own_window(control_widget_t * w) { return w->own_window; } void control_widget_set_own_window(control_widget_t * w, int own_window) { w->own_window = own_window; } void control_widget_get_coords(control_widget_t * w, int * x, int * y, int * width, int * height) { *x = w->x; *y = w->y; *width = w->width; *height = w->height; } void control_widget_set_coords(control_widget_t * w, int x, int y, int width, int height) { w->x = x; w->y = y; w->width = width; w->height = height; } void control_widget_set_hidden(control_widget_t * w, int hidden) { w->hidden = hidden; if(hidden) gtk_widget_hide(w->w); else gtk_widget_show(w->w); } int control_widget_get_hidden(control_widget_t * w) { return w->hidden; } const char * control_widget_get_label(control_widget_t * w) { return w->label; } gmerlin-1.2.0~dfsg/apps/alsamixer/g_mixer.c0000644000175000017500000001332111764363402020625 0ustar alessioalessio/***************************************************************** * gmerlin - a general purpose multimedia framework and applications * * Copyright (c) 2001 - 2011 Members of the Gmerlin project * gmerlin-general@lists.sourceforge.net * http://gmerlin.sourceforge.net * * 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 of the License, 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 this program. If not, see . * *****************************************************************/ #include "gui.h" #include struct mixer_window_s { GtkWidget * main_win; // GtkWidget * aux_win; int num_cards; card_widget_t ** cards; bg_cfg_registry_t * cfg_reg; int x, y, width, height; }; static const bg_parameter_info_t parameters[] = { { .name = "x", .long_name = "X", .type = BG_PARAMETER_INT, .flags = BG_PARAMETER_HIDE_DIALOG, .val_default = { .val_i = 100 }, }, { .name = "y", .long_name = "Y", .type = BG_PARAMETER_INT, .flags = BG_PARAMETER_HIDE_DIALOG, .val_default = { .val_i = 100 }, }, { .name = "width", .long_name = "Width", .type = BG_PARAMETER_INT, .flags = BG_PARAMETER_HIDE_DIALOG, .val_default = { .val_i = 300 }, }, { .name = "height", .long_name = "Height", .type = BG_PARAMETER_INT, .flags = BG_PARAMETER_HIDE_DIALOG, .val_default = { .val_i = 200 }, }, { /* End of parameters */ } }; static void set_parameter(void * data, const char * name, const bg_parameter_value_t * val) { mixer_window_t * w; w = (mixer_window_t*)data; if(!name) { return; } if(!strcmp(name, "x")) { w->x = val->val_i; } else if(!strcmp(name, "y")) { w->y = val->val_i; } else if(!strcmp(name, "width")) { w->width = val->val_i; } else if(!strcmp(name, "height")) { w->height = val->val_i; } } static int get_parameter(void * data, const char * name, bg_parameter_value_t * val) { mixer_window_t * w; w = (mixer_window_t*)data; if(!name) { return 1; } if(!strcmp(name, "x")) { val->val_i = w->x; return 1; } else if(!strcmp(name, "y")) { val->val_i = w->y; return 1; } else if(!strcmp(name, "width")) { val->val_i = w->width; return 1; } else if(!strcmp(name, "height")) { val->val_i = w->height; return 1; } return 0; } static gboolean delete_callback(GtkWidget * wid, GdkEventAny * evt, gpointer data) { int i; mixer_window_t * w; bg_cfg_section_t * section; w = (mixer_window_t*)data; section = bg_cfg_registry_find_section(w->cfg_reg, "General"); gtk_window_get_position(GTK_WINDOW(w->main_win), &w->x, &w->y); gtk_window_get_size(GTK_WINDOW(w->main_win), &w->width, &w->height); bg_cfg_section_get(section, parameters, get_parameter, w); for(i = 0; i < w->num_cards; i++) card_widget_get_window_coords(w->cards[i]); gtk_main_quit(); return TRUE; } static void map_callback(GtkWidget * wid, gpointer data) { mixer_window_t * w; w = (mixer_window_t*)data; gtk_window_resize(GTK_WINDOW(w->main_win), w->width, w->height); gtk_window_move(GTK_WINDOW(w->main_win), w->x, w->y); } mixer_window_t * mixer_window_create(alsa_mixer_t * mixer, bg_cfg_registry_t * cfg_reg) { int i; GtkWidget * notebook; GtkWidget * label; bg_cfg_section_t * section; mixer_window_t * ret; ret = calloc(1, sizeof(*ret)); ret->cfg_reg = cfg_reg; ret->main_win = bg_gtk_window_new(GTK_WINDOW_TOPLEVEL); gtk_window_set_title(GTK_WINDOW(ret->main_win), "Gmerlin Alsamixer"); g_signal_connect(G_OBJECT(ret->main_win), "delete-event", G_CALLBACK(delete_callback), ret); g_signal_connect(G_OBJECT(ret->main_win), "map", G_CALLBACK(map_callback), ret); ret->cards = calloc(mixer->num_cards, sizeof(*(ret->cards))); notebook = gtk_notebook_new(); ret->num_cards = mixer->num_cards; for(i = 0; i < mixer->num_cards; i++) { if(mixer->cards[i]->num_groups) { section = bg_cfg_registry_find_section(ret->cfg_reg, mixer->cards[i]->name); label = gtk_label_new(mixer->cards[i]->name); gtk_widget_show(label); ret->cards[i] = card_widget_create(mixer->cards[i], section); gtk_notebook_append_page(GTK_NOTEBOOK(notebook), card_widget_get_widget(ret->cards[i]), label); } } gtk_widget_show(notebook); gtk_container_add(GTK_CONTAINER(ret->main_win), notebook); section = bg_cfg_registry_find_section(ret->cfg_reg, "General"); bg_cfg_section_apply(section, parameters, set_parameter, ret); return ret; } void mixer_window_destroy(mixer_window_t * w) { int i; for(i = 0; i < w->num_cards; i++) card_widget_destroy(w->cards[i]); free(w); } void mixer_window_run(mixer_window_t * w) { gtk_widget_show(w->main_win); gtk_main(); } gmerlin-1.2.0~dfsg/apps/alsamixer/gmerlin-alsamixer.desktop0000644000175000017500000000030611764363402024041 0ustar alessioalessio[Desktop Entry] Name=Gmerlin mixer Name[de]=Gmerlin mixer Comment=Alsa mixer Comment[de]=Alsa mixer Exec=gmerlin_alsamixer Icon=gmerlin-alsamixer Type=Application Categories=AudioVideo;Audio;Mixer; gmerlin-1.2.0~dfsg/apps/alsamixer/Makefile.in0000644000175000017500000005324011764363422021102 0ustar alessioalessio# Makefile.in generated by automake 1.11.1 from Makefile.am. # @configure_input@ # Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, # 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation, # Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ VPATH = @srcdir@ pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ bin_PROGRAMS = gmerlin_alsamixer$(EXEEXT) subdir = apps/alsamixer DIST_COMMON = $(noinst_HEADERS) $(srcdir)/Makefile.am \ $(srcdir)/Makefile.in ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/m4/check_funcs.m4 \ $(top_srcdir)/m4/gavl_simd.m4 $(top_srcdir)/m4/gettext.m4 \ $(top_srcdir)/m4/iconv.m4 $(top_srcdir)/m4/lib-ld.m4 \ $(top_srcdir)/m4/lib-link.m4 $(top_srcdir)/m4/lib-prefix.m4 \ $(top_srcdir)/m4/lqt_opt_cflags.m4 $(top_srcdir)/m4/nls.m4 \ $(top_srcdir)/m4/po.m4 $(top_srcdir)/m4/progtest.m4 \ $(top_srcdir)/acinclude.m4 $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/include/config.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = am__installdirs = "$(DESTDIR)$(bindir)" "$(DESTDIR)$(Desktopdir)" PROGRAMS = $(bin_PROGRAMS) am_gmerlin_alsamixer_OBJECTS = card.$(OBJEXT) main.$(OBJEXT) \ mixer.$(OBJEXT) g_control.$(OBJEXT) g_card.$(OBJEXT) \ g_mixer.$(OBJEXT) gmerlin_alsamixer_OBJECTS = $(am_gmerlin_alsamixer_OBJECTS) gmerlin_alsamixer_DEPENDENCIES = $(top_builddir)/lib/libgmerlin.la \ $(top_builddir)/lib/gtk/libgmerlin_gtk.la DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)/include depcomp = $(SHELL) $(top_srcdir)/depcomp am__depfiles_maybe = depfiles am__mv = mv -f COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) LTCOMPILE = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \ --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) CCLD = $(CC) LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \ --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \ $(LDFLAGS) -o $@ SOURCES = $(gmerlin_alsamixer_SOURCES) DIST_SOURCES = $(gmerlin_alsamixer_SOURCES) am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; am__vpath_adj = case $$p in \ $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ *) f=$$p;; \ esac; am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; am__install_max = 40 am__nobase_strip_setup = \ srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` am__nobase_strip = \ for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" am__nobase_list = $(am__nobase_strip_setup); \ for p in $$list; do echo "$$p $$p"; done | \ sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ if (++n[$$2] == $(am__install_max)) \ { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ END { for (dir in files) print dir, files[dir] }' am__base_list = \ sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' DATA = $(Desktop_DATA) HEADERS = $(noinst_HEADERS) ETAGS = etags CTAGS = ctags DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ ALSA_CFLAGS = @ALSA_CFLAGS@ ALSA_LIBS = @ALSA_LIBS@ ALSA_REQUIRED = @ALSA_REQUIRED@ AMTAR = @AMTAR@ AR = @AR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ BG_VERSION = @BG_VERSION@ BG_VERSION_MAJOR = @BG_VERSION_MAJOR@ BG_VERSION_MICRO = @BG_VERSION_MICRO@ BG_VERSION_MINOR = @BG_VERSION_MINOR@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CDDB_CFLAGS = @CDDB_CFLAGS@ CDDB_LIBS = @CDDB_LIBS@ CDIO_CDDA_CFLAGS = @CDIO_CDDA_CFLAGS@ CDIO_CDDA_LIBS = @CDIO_CDDA_LIBS@ CDIO_CFLAGS = @CDIO_CFLAGS@ CDIO_LIBS = @CDIO_LIBS@ CDIO_PARANOIA_CFLAGS = @CDIO_PARANOIA_CFLAGS@ CDIO_PARANOIA_LIBS = @CDIO_PARANOIA_LIBS@ CDIO_REQUIRED = @CDIO_REQUIRED@ CFLAGS = @CFLAGS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CYGPATH_W = @CYGPATH_W@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DOXYGEN = @DOXYGEN@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ ESD_CFLAGS = @ESD_CFLAGS@ ESD_CONFIG = @ESD_CONFIG@ ESD_LIBS = @ESD_LIBS@ ESD_REQUIRED = @ESD_REQUIRED@ EXEEXT = @EXEEXT@ FGREP = @FGREP@ FONTCONFIG_CFLAGS = @FONTCONFIG_CFLAGS@ FONTCONFIG_LIBS = @FONTCONFIG_LIBS@ FREETYPE_CFLAGS = @FREETYPE_CFLAGS@ FREETYPE_LIBS = @FREETYPE_LIBS@ GAVL_CFLAGS = @GAVL_CFLAGS@ GAVL_LIBS = @GAVL_LIBS@ GAVL_REQUIRED = @GAVL_REQUIRED@ GLX_CFLAGS = @GLX_CFLAGS@ GLX_LIBS = @GLX_LIBS@ GL_CFLAGS = @GL_CFLAGS@ GL_LIBS = @GL_LIBS@ GMERLIN_DEP_LIBS = @GMERLIN_DEP_LIBS@ GMERLIN_PLUGIN_LDFLAGS = @GMERLIN_PLUGIN_LDFLAGS@ GMSGFMT = @GMSGFMT@ GMSGFMT_015 = @GMSGFMT_015@ GREP = @GREP@ GTK_CFLAGS = @GTK_CFLAGS@ GTK_LIBS = @GTK_LIBS@ GTK_REQUIRED = @GTK_REQUIRED@ ICONV_LIBS = @ICONV_LIBS@ INCLUDES = -I$(top_srcdir)/include INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ INTLLIBS = @INTLLIBS@ INTL_MACOSX_LIBS = @INTL_MACOSX_LIBS@ JACK_CFLAGS = @JACK_CFLAGS@ JACK_LIBS = @JACK_LIBS@ JACK_REQUIRED = @JACK_REQUIRED@ JPEG_CFLAGS = @JPEG_CFLAGS@ JPEG_LIBS = @JPEG_LIBS@ JPEG_REQUIRED = @JPEG_REQUIRED@ LD = @LD@ LDFLAGS = @LDFLAGS@ LIBCDDB_REQUIRED = @LIBCDDB_REQUIRED@ LIBEXIF_CFLAGS = @LIBEXIF_CFLAGS@ LIBEXIF_LIBS = @LIBEXIF_LIBS@ LIBICONV = @LIBICONV@ LIBINTL = @LIBINTL@ LIBM = @LIBM@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIPO = @LIPO@ LN_S = @LN_S@ LQT_CFLAGS = @LQT_CFLAGS@ LQT_LIBS = @LQT_LIBS@ LQT_REQUIRED = @LQT_REQUIRED@ LTLIBICONV = @LTLIBICONV@ LTLIBINTL = @LTLIBINTL@ LTLIBOBJS = @LTLIBOBJS@ LTVERSION_AGE = @LTVERSION_AGE@ LTVERSION_CURRENT = @LTVERSION_CURRENT@ LTVERSION_REVISION = @LTVERSION_REVISION@ LV_CFLAGS = @LV_CFLAGS@ LV_LIBS = @LV_LIBS@ LV_REQUIRED = @LV_REQUIRED@ MAKEINFO = @MAKEINFO@ MKDIR_P = @MKDIR_P@ MODULE_LIBADD = @MODULE_LIBADD@ MSGFMT = @MSGFMT@ MSGFMT_015 = @MSGFMT_015@ MSGMERGE = @MSGMERGE@ MUSICBRAINZ_CFLAGS = @MUSICBRAINZ_CFLAGS@ MUSICBRAINZ_LIBS = @MUSICBRAINZ_LIBS@ MUSICBRAINZ_REQUIRED = @MUSICBRAINZ_REQUIRED@ NM = @NM@ NMEDIT = @NMEDIT@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OTOOL = @OTOOL@ OTOOL64 = @OTOOL64@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PKG_CONFIG = @PKG_CONFIG@ PNG_CFLAGS = @PNG_CFLAGS@ PNG_LIBS = @PNG_LIBS@ PNG_REQUIRED = @PNG_REQUIRED@ POSUB = @POSUB@ PULSEAUDIO_CFLAGS = @PULSEAUDIO_CFLAGS@ PULSEAUDIO_LIBS = @PULSEAUDIO_LIBS@ PULSEAUDIO_REQUIRED = @PULSEAUDIO_REQUIRED@ RANLIB = @RANLIB@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ SQLITE3_LIBS = @SQLITE3_LIBS@ STRIP = @STRIP@ TEXINFO = @TEXINFO@ TIFF_CFLAGS = @TIFF_CFLAGS@ TIFF_LIBS = @TIFF_LIBS@ TIFF_REQUIRED = @TIFF_REQUIRED@ TOP_SRCDIR = @TOP_SRCDIR@ USE_NLS = @USE_NLS@ V4LCONVERT_CFLAGS = @V4LCONVERT_CFLAGS@ V4LCONVERT_LIBS = @V4LCONVERT_LIBS@ V4LCONVERT_REQUIRED = @V4LCONVERT_REQUIRED@ VERSION = @VERSION@ XDPMS_LIBS = @XDPMS_LIBS@ XFIXES_LIBS = @XFIXES_LIBS@ XGETTEXT = @XGETTEXT@ XGETTEXT_015 = @XGETTEXT_015@ XINERAMA_LIBS = @XINERAMA_LIBS@ XMKMF = @XMKMF@ XML2_CFLAGS = @XML2_CFLAGS@ XML2_LIBS = @XML2_LIBS@ XML2_REQUIRED = @XML2_REQUIRED@ XTEST_LIBS = @XTEST_LIBS@ XV_LIBS = @XV_LIBS@ X_CFLAGS = @X_CFLAGS@ X_LIBS = @X_LIBS@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_CC = @ac_ct_CC@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_vendor = @build_vendor@ builddir = @builddir@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ lt_ECHO = @lt_ECHO@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ plugindir = $(pkglibdir)/plugins AM_CFLAGS = \ @XML2_CFLAGS@ \ @GTK_CFLAGS@ \ @ALSA_CFLAGS@ \ -DLOCALE_DIR=\"$(localedir)\" \ -DPLUGIN_DIR=\"$(plugindir)\" \ -DDOC_DIR=\"$(docdir)\" \ -DDATA_DIR=\"$(pkgdatadir)\" Desktopdir = $(datadir)/applications Desktop_DATA = gmerlin-alsamixer.desktop gmerlin_alsamixer_SOURCES = card.c main.c mixer.c g_control.c g_card.c g_mixer.c gmerlin_alsamixer_LDADD = $(top_builddir)/lib/libgmerlin.la $(top_builddir)/lib/gtk/libgmerlin_gtk.la @ALSA_LIBS@ -lpthread noinst_HEADERS = alsamixer.h gui.h EXTRA_DIST = gmerlin-alsamixer.desktop all: all-am .SUFFIXES: .SUFFIXES: .c .lo .o .obj $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ && { if test -f $@; then exit 0; else break; fi; }; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu apps/alsamixer/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --gnu apps/alsamixer/Makefile .PRECIOUS: Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): install-binPROGRAMS: $(bin_PROGRAMS) @$(NORMAL_INSTALL) test -z "$(bindir)" || $(MKDIR_P) "$(DESTDIR)$(bindir)" @list='$(bin_PROGRAMS)'; test -n "$(bindir)" || list=; \ for p in $$list; do echo "$$p $$p"; done | \ sed 's/$(EXEEXT)$$//' | \ while read p p1; do if test -f $$p || test -f $$p1; \ then echo "$$p"; echo "$$p"; else :; fi; \ done | \ sed -e 'p;s,.*/,,;n;h' -e 's|.*|.|' \ -e 'p;x;s,.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/' | \ sed 'N;N;N;s,\n, ,g' | \ $(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1 } \ { d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \ if ($$2 == $$4) files[d] = files[d] " " $$1; \ else { print "f", $$3 "/" $$4, $$1; } } \ END { for (d in files) print "f", d, files[d] }' | \ while read type dir files; do \ if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \ test -z "$$files" || { \ echo " $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files '$(DESTDIR)$(bindir)$$dir'"; \ $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files "$(DESTDIR)$(bindir)$$dir" || exit $$?; \ } \ ; done uninstall-binPROGRAMS: @$(NORMAL_UNINSTALL) @list='$(bin_PROGRAMS)'; test -n "$(bindir)" || list=; \ files=`for p in $$list; do echo "$$p"; done | \ sed -e 'h;s,^.*/,,;s/$(EXEEXT)$$//;$(transform)' \ -e 's/$$/$(EXEEXT)/' `; \ test -n "$$list" || exit 0; \ echo " ( cd '$(DESTDIR)$(bindir)' && rm -f" $$files ")"; \ cd "$(DESTDIR)$(bindir)" && rm -f $$files clean-binPROGRAMS: @list='$(bin_PROGRAMS)'; test -n "$$list" || exit 0; \ echo " rm -f" $$list; \ rm -f $$list || exit $$?; \ test -n "$(EXEEXT)" || exit 0; \ list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ echo " rm -f" $$list; \ rm -f $$list gmerlin_alsamixer$(EXEEXT): $(gmerlin_alsamixer_OBJECTS) $(gmerlin_alsamixer_DEPENDENCIES) @rm -f gmerlin_alsamixer$(EXEEXT) $(LINK) $(gmerlin_alsamixer_OBJECTS) $(gmerlin_alsamixer_LDADD) $(LIBS) mostlyclean-compile: -rm -f *.$(OBJEXT) distclean-compile: -rm -f *.tab.c @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/card.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/g_card.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/g_control.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/g_mixer.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/main.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mixer.Po@am__quote@ .c.o: @am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(COMPILE) -c $< .c.obj: @am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(COMPILE) -c `$(CYGPATH_W) '$<'` .c.lo: @am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(LTCOMPILE) -c -o $@ $< mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs install-DesktopDATA: $(Desktop_DATA) @$(NORMAL_INSTALL) test -z "$(Desktopdir)" || $(MKDIR_P) "$(DESTDIR)$(Desktopdir)" @list='$(Desktop_DATA)'; test -n "$(Desktopdir)" || list=; \ for p in $$list; do \ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ echo "$$d$$p"; \ done | $(am__base_list) | \ while read files; do \ echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(Desktopdir)'"; \ $(INSTALL_DATA) $$files "$(DESTDIR)$(Desktopdir)" || exit $$?; \ done uninstall-DesktopDATA: @$(NORMAL_UNINSTALL) @list='$(Desktop_DATA)'; test -n "$(Desktopdir)" || list=; \ files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ test -n "$$files" || exit 0; \ echo " ( cd '$(DESTDIR)$(Desktopdir)' && rm -f" $$files ")"; \ cd "$(DESTDIR)$(Desktopdir)" && rm -f $$files ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | \ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in files) print i; }; }'`; \ mkid -fID $$unique tags: TAGS TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ $(TAGS_FILES) $(LISP) set x; \ here=`pwd`; \ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | \ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in files) print i; }; }'`; \ shift; \ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ test -n "$$unique" || unique=$$empty_fix; \ if test $$# -gt 0; then \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ "$$@" $$unique; \ else \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ $$unique; \ fi; \ fi ctags: CTAGS CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ $(TAGS_FILES) $(LISP) list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | \ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in files) print i; }; }'`; \ test -z "$(CTAGS_ARGS)$$unique" \ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ $$unique GTAGS: here=`$(am__cd) $(top_builddir) && pwd` \ && $(am__cd) $(top_srcdir) \ && gtags -i $(GTAGS_ARGS) "$$here" distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags distdir: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done check-am: all-am check: check-am all-am: Makefile $(PROGRAMS) $(DATA) $(HEADERS) installdirs: for dir in "$(DESTDIR)$(bindir)" "$(DESTDIR)$(Desktopdir)"; do \ test -z "$$dir" || $(MKDIR_P) "$$dir"; \ done install: install-am install-exec: install-exec-am install-data: install-data-am uninstall: uninstall-am install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-am install-strip: $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ `test -z '$(STRIP)' || \ echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install mostlyclean-generic: clean-generic: distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." clean: clean-am clean-am: clean-binPROGRAMS clean-generic clean-libtool mostlyclean-am distclean: distclean-am -rm -rf ./$(DEPDIR) -rm -f Makefile distclean-am: clean-am distclean-compile distclean-generic \ distclean-tags dvi: dvi-am dvi-am: html: html-am html-am: info: info-am info-am: install-data-am: install-DesktopDATA install-dvi: install-dvi-am install-dvi-am: install-exec-am: install-binPROGRAMS install-html: install-html-am install-html-am: install-info: install-info-am install-info-am: install-man: install-pdf: install-pdf-am install-pdf-am: install-ps: install-ps-am install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-am -rm -rf ./$(DEPDIR) -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-compile mostlyclean-generic \ mostlyclean-libtool pdf: pdf-am pdf-am: ps: ps-am ps-am: uninstall-am: uninstall-DesktopDATA uninstall-binPROGRAMS .MAKE: install-am install-strip .PHONY: CTAGS GTAGS all all-am check check-am clean clean-binPROGRAMS \ clean-generic clean-libtool ctags distclean distclean-compile \ distclean-generic distclean-libtool distclean-tags distdir dvi \ dvi-am html html-am info info-am install install-DesktopDATA \ install-am install-binPROGRAMS install-data install-data-am \ install-dvi install-dvi-am install-exec install-exec-am \ install-html install-html-am install-info install-info-am \ install-man install-pdf install-pdf-am install-ps \ install-ps-am install-strip installcheck installcheck-am \ installdirs maintainer-clean maintainer-clean-generic \ mostlyclean mostlyclean-compile mostlyclean-generic \ mostlyclean-libtool pdf pdf-am ps ps-am tags uninstall \ uninstall-DesktopDATA uninstall-am uninstall-binPROGRAMS # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: gmerlin-1.2.0~dfsg/apps/thumbnailer/0000755000175000017500000000000011764363443017361 5ustar alessioalessiogmerlin-1.2.0~dfsg/apps/thumbnailer/Makefile.am0000644000175000017500000000050011764363403021404 0ustar alessioalessioplugindir=$(pkglibdir)/plugins AM_CFLAGS = \ -DLOCALE_DIR=\"$(localedir)\" \ -DPLUGIN_DIR=\"$(plugindir)\" \ -DDOC_DIR=\"$(docdir)\" \ -DDATA_DIR=\"$(pkgdatadir)\" INCLUDES = -I$(top_srcdir)/include bin_PROGRAMS = gmerlin-video-thumbnailer gmerlin_video_thumbnailer_LDADD = $(top_builddir)/lib/libgmerlin.la -ldl gmerlin-1.2.0~dfsg/apps/thumbnailer/Makefile.in0000644000175000017500000004606111764363423021433 0ustar alessioalessio# Makefile.in generated by automake 1.11.1 from Makefile.am. # @configure_input@ # Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, # 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation, # Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ VPATH = @srcdir@ pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ bin_PROGRAMS = gmerlin-video-thumbnailer$(EXEEXT) subdir = apps/thumbnailer DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/m4/check_funcs.m4 \ $(top_srcdir)/m4/gavl_simd.m4 $(top_srcdir)/m4/gettext.m4 \ $(top_srcdir)/m4/iconv.m4 $(top_srcdir)/m4/lib-ld.m4 \ $(top_srcdir)/m4/lib-link.m4 $(top_srcdir)/m4/lib-prefix.m4 \ $(top_srcdir)/m4/lqt_opt_cflags.m4 $(top_srcdir)/m4/nls.m4 \ $(top_srcdir)/m4/po.m4 $(top_srcdir)/m4/progtest.m4 \ $(top_srcdir)/acinclude.m4 $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/include/config.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = am__installdirs = "$(DESTDIR)$(bindir)" PROGRAMS = $(bin_PROGRAMS) gmerlin_video_thumbnailer_SOURCES = gmerlin-video-thumbnailer.c gmerlin_video_thumbnailer_OBJECTS = \ gmerlin-video-thumbnailer.$(OBJEXT) gmerlin_video_thumbnailer_DEPENDENCIES = \ $(top_builddir)/lib/libgmerlin.la DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)/include depcomp = $(SHELL) $(top_srcdir)/depcomp am__depfiles_maybe = depfiles am__mv = mv -f COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) LTCOMPILE = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \ --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) CCLD = $(CC) LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \ --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \ $(LDFLAGS) -o $@ SOURCES = gmerlin-video-thumbnailer.c DIST_SOURCES = gmerlin-video-thumbnailer.c ETAGS = etags CTAGS = ctags DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ ALSA_CFLAGS = @ALSA_CFLAGS@ ALSA_LIBS = @ALSA_LIBS@ ALSA_REQUIRED = @ALSA_REQUIRED@ AMTAR = @AMTAR@ AR = @AR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ BG_VERSION = @BG_VERSION@ BG_VERSION_MAJOR = @BG_VERSION_MAJOR@ BG_VERSION_MICRO = @BG_VERSION_MICRO@ BG_VERSION_MINOR = @BG_VERSION_MINOR@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CDDB_CFLAGS = @CDDB_CFLAGS@ CDDB_LIBS = @CDDB_LIBS@ CDIO_CDDA_CFLAGS = @CDIO_CDDA_CFLAGS@ CDIO_CDDA_LIBS = @CDIO_CDDA_LIBS@ CDIO_CFLAGS = @CDIO_CFLAGS@ CDIO_LIBS = @CDIO_LIBS@ CDIO_PARANOIA_CFLAGS = @CDIO_PARANOIA_CFLAGS@ CDIO_PARANOIA_LIBS = @CDIO_PARANOIA_LIBS@ CDIO_REQUIRED = @CDIO_REQUIRED@ CFLAGS = @CFLAGS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CYGPATH_W = @CYGPATH_W@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DOXYGEN = @DOXYGEN@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ ESD_CFLAGS = @ESD_CFLAGS@ ESD_CONFIG = @ESD_CONFIG@ ESD_LIBS = @ESD_LIBS@ ESD_REQUIRED = @ESD_REQUIRED@ EXEEXT = @EXEEXT@ FGREP = @FGREP@ FONTCONFIG_CFLAGS = @FONTCONFIG_CFLAGS@ FONTCONFIG_LIBS = @FONTCONFIG_LIBS@ FREETYPE_CFLAGS = @FREETYPE_CFLAGS@ FREETYPE_LIBS = @FREETYPE_LIBS@ GAVL_CFLAGS = @GAVL_CFLAGS@ GAVL_LIBS = @GAVL_LIBS@ GAVL_REQUIRED = @GAVL_REQUIRED@ GLX_CFLAGS = @GLX_CFLAGS@ GLX_LIBS = @GLX_LIBS@ GL_CFLAGS = @GL_CFLAGS@ GL_LIBS = @GL_LIBS@ GMERLIN_DEP_LIBS = @GMERLIN_DEP_LIBS@ GMERLIN_PLUGIN_LDFLAGS = @GMERLIN_PLUGIN_LDFLAGS@ GMSGFMT = @GMSGFMT@ GMSGFMT_015 = @GMSGFMT_015@ GREP = @GREP@ GTK_CFLAGS = @GTK_CFLAGS@ GTK_LIBS = @GTK_LIBS@ GTK_REQUIRED = @GTK_REQUIRED@ ICONV_LIBS = @ICONV_LIBS@ INCLUDES = -I$(top_srcdir)/include INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ INTLLIBS = @INTLLIBS@ INTL_MACOSX_LIBS = @INTL_MACOSX_LIBS@ JACK_CFLAGS = @JACK_CFLAGS@ JACK_LIBS = @JACK_LIBS@ JACK_REQUIRED = @JACK_REQUIRED@ JPEG_CFLAGS = @JPEG_CFLAGS@ JPEG_LIBS = @JPEG_LIBS@ JPEG_REQUIRED = @JPEG_REQUIRED@ LD = @LD@ LDFLAGS = @LDFLAGS@ LIBCDDB_REQUIRED = @LIBCDDB_REQUIRED@ LIBEXIF_CFLAGS = @LIBEXIF_CFLAGS@ LIBEXIF_LIBS = @LIBEXIF_LIBS@ LIBICONV = @LIBICONV@ LIBINTL = @LIBINTL@ LIBM = @LIBM@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIPO = @LIPO@ LN_S = @LN_S@ LQT_CFLAGS = @LQT_CFLAGS@ LQT_LIBS = @LQT_LIBS@ LQT_REQUIRED = @LQT_REQUIRED@ LTLIBICONV = @LTLIBICONV@ LTLIBINTL = @LTLIBINTL@ LTLIBOBJS = @LTLIBOBJS@ LTVERSION_AGE = @LTVERSION_AGE@ LTVERSION_CURRENT = @LTVERSION_CURRENT@ LTVERSION_REVISION = @LTVERSION_REVISION@ LV_CFLAGS = @LV_CFLAGS@ LV_LIBS = @LV_LIBS@ LV_REQUIRED = @LV_REQUIRED@ MAKEINFO = @MAKEINFO@ MKDIR_P = @MKDIR_P@ MODULE_LIBADD = @MODULE_LIBADD@ MSGFMT = @MSGFMT@ MSGFMT_015 = @MSGFMT_015@ MSGMERGE = @MSGMERGE@ MUSICBRAINZ_CFLAGS = @MUSICBRAINZ_CFLAGS@ MUSICBRAINZ_LIBS = @MUSICBRAINZ_LIBS@ MUSICBRAINZ_REQUIRED = @MUSICBRAINZ_REQUIRED@ NM = @NM@ NMEDIT = @NMEDIT@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OTOOL = @OTOOL@ OTOOL64 = @OTOOL64@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PKG_CONFIG = @PKG_CONFIG@ PNG_CFLAGS = @PNG_CFLAGS@ PNG_LIBS = @PNG_LIBS@ PNG_REQUIRED = @PNG_REQUIRED@ POSUB = @POSUB@ PULSEAUDIO_CFLAGS = @PULSEAUDIO_CFLAGS@ PULSEAUDIO_LIBS = @PULSEAUDIO_LIBS@ PULSEAUDIO_REQUIRED = @PULSEAUDIO_REQUIRED@ RANLIB = @RANLIB@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ SQLITE3_LIBS = @SQLITE3_LIBS@ STRIP = @STRIP@ TEXINFO = @TEXINFO@ TIFF_CFLAGS = @TIFF_CFLAGS@ TIFF_LIBS = @TIFF_LIBS@ TIFF_REQUIRED = @TIFF_REQUIRED@ TOP_SRCDIR = @TOP_SRCDIR@ USE_NLS = @USE_NLS@ V4LCONVERT_CFLAGS = @V4LCONVERT_CFLAGS@ V4LCONVERT_LIBS = @V4LCONVERT_LIBS@ V4LCONVERT_REQUIRED = @V4LCONVERT_REQUIRED@ VERSION = @VERSION@ XDPMS_LIBS = @XDPMS_LIBS@ XFIXES_LIBS = @XFIXES_LIBS@ XGETTEXT = @XGETTEXT@ XGETTEXT_015 = @XGETTEXT_015@ XINERAMA_LIBS = @XINERAMA_LIBS@ XMKMF = @XMKMF@ XML2_CFLAGS = @XML2_CFLAGS@ XML2_LIBS = @XML2_LIBS@ XML2_REQUIRED = @XML2_REQUIRED@ XTEST_LIBS = @XTEST_LIBS@ XV_LIBS = @XV_LIBS@ X_CFLAGS = @X_CFLAGS@ X_LIBS = @X_LIBS@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_CC = @ac_ct_CC@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_vendor = @build_vendor@ builddir = @builddir@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ lt_ECHO = @lt_ECHO@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ plugindir = $(pkglibdir)/plugins AM_CFLAGS = \ -DLOCALE_DIR=\"$(localedir)\" \ -DPLUGIN_DIR=\"$(plugindir)\" \ -DDOC_DIR=\"$(docdir)\" \ -DDATA_DIR=\"$(pkgdatadir)\" gmerlin_video_thumbnailer_LDADD = $(top_builddir)/lib/libgmerlin.la -ldl all: all-am .SUFFIXES: .SUFFIXES: .c .lo .o .obj $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ && { if test -f $@; then exit 0; else break; fi; }; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu apps/thumbnailer/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --gnu apps/thumbnailer/Makefile .PRECIOUS: Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): install-binPROGRAMS: $(bin_PROGRAMS) @$(NORMAL_INSTALL) test -z "$(bindir)" || $(MKDIR_P) "$(DESTDIR)$(bindir)" @list='$(bin_PROGRAMS)'; test -n "$(bindir)" || list=; \ for p in $$list; do echo "$$p $$p"; done | \ sed 's/$(EXEEXT)$$//' | \ while read p p1; do if test -f $$p || test -f $$p1; \ then echo "$$p"; echo "$$p"; else :; fi; \ done | \ sed -e 'p;s,.*/,,;n;h' -e 's|.*|.|' \ -e 'p;x;s,.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/' | \ sed 'N;N;N;s,\n, ,g' | \ $(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1 } \ { d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \ if ($$2 == $$4) files[d] = files[d] " " $$1; \ else { print "f", $$3 "/" $$4, $$1; } } \ END { for (d in files) print "f", d, files[d] }' | \ while read type dir files; do \ if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \ test -z "$$files" || { \ echo " $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files '$(DESTDIR)$(bindir)$$dir'"; \ $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files "$(DESTDIR)$(bindir)$$dir" || exit $$?; \ } \ ; done uninstall-binPROGRAMS: @$(NORMAL_UNINSTALL) @list='$(bin_PROGRAMS)'; test -n "$(bindir)" || list=; \ files=`for p in $$list; do echo "$$p"; done | \ sed -e 'h;s,^.*/,,;s/$(EXEEXT)$$//;$(transform)' \ -e 's/$$/$(EXEEXT)/' `; \ test -n "$$list" || exit 0; \ echo " ( cd '$(DESTDIR)$(bindir)' && rm -f" $$files ")"; \ cd "$(DESTDIR)$(bindir)" && rm -f $$files clean-binPROGRAMS: @list='$(bin_PROGRAMS)'; test -n "$$list" || exit 0; \ echo " rm -f" $$list; \ rm -f $$list || exit $$?; \ test -n "$(EXEEXT)" || exit 0; \ list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ echo " rm -f" $$list; \ rm -f $$list gmerlin-video-thumbnailer$(EXEEXT): $(gmerlin_video_thumbnailer_OBJECTS) $(gmerlin_video_thumbnailer_DEPENDENCIES) @rm -f gmerlin-video-thumbnailer$(EXEEXT) $(LINK) $(gmerlin_video_thumbnailer_OBJECTS) $(gmerlin_video_thumbnailer_LDADD) $(LIBS) mostlyclean-compile: -rm -f *.$(OBJEXT) distclean-compile: -rm -f *.tab.c @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gmerlin-video-thumbnailer.Po@am__quote@ .c.o: @am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(COMPILE) -c $< .c.obj: @am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(COMPILE) -c `$(CYGPATH_W) '$<'` .c.lo: @am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(LTCOMPILE) -c -o $@ $< mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | \ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in files) print i; }; }'`; \ mkid -fID $$unique tags: TAGS TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ $(TAGS_FILES) $(LISP) set x; \ here=`pwd`; \ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | \ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in files) print i; }; }'`; \ shift; \ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ test -n "$$unique" || unique=$$empty_fix; \ if test $$# -gt 0; then \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ "$$@" $$unique; \ else \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ $$unique; \ fi; \ fi ctags: CTAGS CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ $(TAGS_FILES) $(LISP) list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | \ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in files) print i; }; }'`; \ test -z "$(CTAGS_ARGS)$$unique" \ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ $$unique GTAGS: here=`$(am__cd) $(top_builddir) && pwd` \ && $(am__cd) $(top_srcdir) \ && gtags -i $(GTAGS_ARGS) "$$here" distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags distdir: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done check-am: all-am check: check-am all-am: Makefile $(PROGRAMS) installdirs: for dir in "$(DESTDIR)$(bindir)"; do \ test -z "$$dir" || $(MKDIR_P) "$$dir"; \ done install: install-am install-exec: install-exec-am install-data: install-data-am uninstall: uninstall-am install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-am install-strip: $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ `test -z '$(STRIP)' || \ echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install mostlyclean-generic: clean-generic: distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." clean: clean-am clean-am: clean-binPROGRAMS clean-generic clean-libtool mostlyclean-am distclean: distclean-am -rm -rf ./$(DEPDIR) -rm -f Makefile distclean-am: clean-am distclean-compile distclean-generic \ distclean-tags dvi: dvi-am dvi-am: html: html-am html-am: info: info-am info-am: install-data-am: install-dvi: install-dvi-am install-dvi-am: install-exec-am: install-binPROGRAMS install-html: install-html-am install-html-am: install-info: install-info-am install-info-am: install-man: install-pdf: install-pdf-am install-pdf-am: install-ps: install-ps-am install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-am -rm -rf ./$(DEPDIR) -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-compile mostlyclean-generic \ mostlyclean-libtool pdf: pdf-am pdf-am: ps: ps-am ps-am: uninstall-am: uninstall-binPROGRAMS .MAKE: install-am install-strip .PHONY: CTAGS GTAGS all all-am check check-am clean clean-binPROGRAMS \ clean-generic clean-libtool ctags distclean distclean-compile \ distclean-generic distclean-libtool distclean-tags distdir dvi \ dvi-am html html-am info info-am install install-am \ install-binPROGRAMS install-data install-data-am install-dvi \ install-dvi-am install-exec install-exec-am install-html \ install-html-am install-info install-info-am install-man \ install-pdf install-pdf-am install-ps install-ps-am \ install-strip installcheck installcheck-am installdirs \ maintainer-clean maintainer-clean-generic mostlyclean \ mostlyclean-compile mostlyclean-generic mostlyclean-libtool \ pdf pdf-am ps ps-am tags uninstall uninstall-am \ uninstall-binPROGRAMS # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: gmerlin-1.2.0~dfsg/apps/thumbnailer/gmerlin-video-thumbnailer.c0000644000175000017500000002657211764363403024606 0ustar alessioalessio/***************************************************************** * gmerlin - a general purpose multimedia framework and applications * * Copyright (c) 2001 - 2011 Members of the Gmerlin project * gmerlin-general@lists.sourceforge.net * http://gmerlin.sourceforge.net * * 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 of the License, 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 this program. If not, see . * *****************************************************************/ #include #include /* stat() */ #include /* stat() */ #include /* stat() */ #include #include #include #include #include #include #define LOG_DOMAIN "thumbnailer" static int thumb_size = 128; static gavl_time_t seek_time = GAVL_TIME_UNDEFINED; static float seek_percentage = 10.0; static void opt_size(void * data, int * argc, char *** _argv, int arg) { if(arg >= *argc) { bg_log(BG_LOG_ERROR, LOG_DOMAIN, "Option -s requires an argument"); exit(-1); } thumb_size = atoi((*_argv)[arg]); bg_cmdline_remove_arg(argc, _argv, arg); } static void opt_time(void * data, int * argc, char *** _argv, int arg) { char * str; if(arg >= *argc) { bg_log(BG_LOG_ERROR, LOG_DOMAIN, "Option -t requires an argument"); exit(-1); } str = (*_argv)[arg]; if(str[strlen(str)-1] == '%') seek_percentage = strtod(str, NULL); else seek_time = gavl_seconds_to_time(strtod(str, NULL)); bg_cmdline_remove_arg(argc, _argv, arg); } static bg_cmdline_arg_t global_options[] = { { .arg = "-s", .help_arg = "", .help_string = "Maximum width or height", .callback = opt_size, }, { .arg = "-t", .help_arg = " are in the range 0.0..1.0,, (default: %.3f,%.3f,%.3f),,, (default: %.3f,%.3f,%.3f,%.3f), (default: %.3f,%.3f)@item Environment variables @item Files ASCIIAUXAVIAVI (Opendml)AboutAbout Gmerlin visualizerAbout...Accessories...ActionActionsAdd %sAdd to the incoming albumAdd to the incoming album and play itAdd URLS to album %sAdd URLsAdd albums to %sAdd deviceAdd device...Add effect to input dataAdd filesAdd files to album %sAdd gain (dB)Add newAdd new (first only)Add new chapterAdd new keyAdd subdirectories as subalbumsAdd...AlbumAlbum %s already openAlbum nameAlbum...Albums...All channels interleavedAll open albumsAllow connections from other machinesAlphaAlpha -> AlphaAlpha -> BlueAlpha -> CbAlpha -> CrAlpha -> GreenAlpha -> LuminanceAlpha -> RedAlpha modeAlpha offsetAlsaAlsa initialization failedAlsa output plugin with support for channel configurations up to 5.1Alsa recorderAlwaysAlways perform chroma resampling if chroma subsampling factors or chroma placements are different. Usually, this is only done for qualities above 3.AngleAppend URLs to the task listAppend files to the task listAppend removable media to the task listApply gain for red, green and blue. RGB formats are processed directly, Y'CbCr formats are processed by the colormatrix.ArtistAspect ratio changedAttach subtitle stream to this video stream. For blending, this video stream will get the subtitles. For encoding, take frame dimensions and framerate from this video stream as they are sometimes needed by subtitle encoders.AudioAudio #%dAudio #%d: %sAudio CD generator/burnerAudio CD optionsAudio CD player/ripperAudio CD track %02dAudio CodecsAudio FiltersAudio defaultsAudio encoderAudio filterAudio filtersAudio optionsAudio outputAudio recorderAudio sample counter: %sAudio stream %d input format: %sAudio stream %d output format: %sAudio stream %d/%dAudio stream %d: Transcoded %s samplesAudio streams %dAudio...Audio/Video encoderAudio: %sAuthenticationAuthorAuthor: %s %sAutoAuto SelectAuto delayAuto detectAuto resize windowAuto speedAutomatic captureAutomatically capture in the specified capture intervalBMP readerBMP writerBUG!!! convert_func == 0x0BackgroundBackground colorBackground color to use, when alpha mode above is "Blend background color".Backlight compensationBackward search hit top, continuing at bottomBackward search: No tracks foundBassBilinearBin fileBinaryBitsBits per channelBits per sampleBlendBlend background colorBlend onto videoBlock thresholdBlueBlue -> AlphaBlue -> BlueBlue -> GreenBlue -> RedBlue gainBlue offsetBlurBlur filter based on gavl. Supports triangular, box and gauss blur.Border colorBorder widthBottomBottom borderBottom field firstBottom leftBottom left corner in normalized image coordinatesBottom rightBottom right corner in normalized image coordinatesBrightnessBrowse...Buffer timeBurn optionsBurn timecodes into video framesCD Writer (%s)CD-ROM Drive (%s)CIF (352 × 288)CIF (352x288)Cache of the plugin registry (shared by all applicatons)Cache sizeCan't read File typeCannot bind inet socket: %sCannot connect to daemonCannot create directory %s: %s, using defaultCannot create inet server socketCannot create socketCannot create unix server socketCannot create unix socketCannot detect image dimensionsCannot find mikmod executableCannot find plugin %sCannot get duration of file %sCannot launch gmerlin processCannot launch transcoder processCannot load frei0r plugin: %sCannot open %sCannot open %s: %sCannot open %s: no plugin foundCannot open device %s: %sCannot open file "%s" for writingCannot open file %sCannot open file %s: %sCannot open output file: %sCannot put socket into listening modeCannot read File typeCannot read heightCannot read maxvalCannot read widthCannot resolve address of %s: %sCannot save %s: %sCannot seek to start pointCannot select track, skippingCannot set blocking modeCannot set nonblocking modeCannot set sampleformat for %sCannot stat %s: %sCaptureCapture intervalCapture interval (in seconds)CardCard controlsCbCb -> AlphaCb -> CbCb -> CrCb -> LuminanceCb offsetCddbCdparanoiaCenterCenter of the lensCenter/LFE DeviceChange encoder plugins for selected tracksChange encoders...Changed recording plugin to %sChannel ModeChannels: %d Channel order %s Samplerate: %d Samples per frame: %d Interleave Mode: %s Sample format: %sChannels: %d Channel order: %s Samplerate: %d Samples per frame: %d Interleave Mode: %s Sample format: %sChapter %dChapter %d [%s]Chapters...Choose Transformation method. Each method can be configured in it's section.Choose interpolation method. Auto means to choose based on the conversion quality. Nearest is fastest, Bicubic is slowest.Choose leftChoose rightChoose scaling method. Auto means to choose based on the conversion quality. Nearest is fastest, Sinc with Lanczos window is slowest.Chroma samplingClean up after postprocessingClean up all encoded files, which were postprocessedClient connection closedCloseClose album and eject discClosing album %sCodecCollapse allColor for debug messagesColor for error messagesColor for info messagesColor for warning messagesColor of the image borders.ColorbalanceColourCommandCommand "%s" not unserstood by serverCommandline Multimedia player CommandsCommands...CommentComment which will be written in front of every fileCompressionCompression levelConfigureConfigure selected trackConfigure test Configure...Connecting failedConnecting failed: %sConnecting unix socket failedConnection timed outConnection to Pulseaudio failed: %sConnection to server closed due to errorConnection to server established, display size: %dx%dContrastControl hue, saturation, contrast and brightness. For Y'CbCr, it uses routines based on the vf_eq and vf_hue filters from the MPlayer project. For RGB formats, it uses the colormatrix.Controls for %sConversion QualityCopyCopy allCopy current track to favouritesCopy selectedCopy selected tracks to clipboardCopy selected tracks to favouritesCopy to favouritesCopyrightCopyright (C) 2001-2007 Members of the gmerlin project Correcting volume by %.2f dBCould not bind socketCould not connect to server at %s:%dCould not find any Alsa mixers. Check your setup! Could not get GL VisualCould not get server welcome lineCould not resolve adress for: %sCould not send hello messageCouldn't open album file %sCrCr -> AlphaCr -> CbCr -> CrCr -> LuminanceCr offsetCreate video with alpha channel even if the input format has no alpha channel. Use this to generate the alpha channel from other channels using the colormatrix.Created directory %sCreated process: %s [%d]Creating process failed: %sCreative MultichannelCropCrop & ScaleCrop and scale video images. Has lots of standard video formats as presets. Can also do chroma placement correction and simple deinterlacingCrop bottomCrop leftCrop rightCrop topCubic B-SplineCubic Catmull-RomCubic Mitchell-NetravaliCue fileCurrent albumCutCut selected tracks to clipboardCut this many pixels from the bottom border of the source images.Cut this many pixels from the left border of the source images.Cut this many pixels from the right border of the source images.Cut this many pixels from the top border of the source images.DV PALDVD Drive (%s)DVD Writer (%s)Daemon runningDebug foregroundDecimateDecrease volumeDefaultDefault ColorspaceDefault FramerateDefault formatDefault heightDefault plugin parameters are read from there. Use gmerlin_plugincfg to change them.Default port for the remote controlDefault widthDefault: %sDeflateDeflate compression levelDeinterlaceDeinterlace modeDeinterlace with various algorithmsDeinterlacerDeleteDelete albumDelete chapterDelete incomplete output filesDelete keyDelete selected tracksDelete the encoded files if you hit the stop button. This option will automatically be disabled, when the track is an URLDepth %d not supportedDesired image height, the visualization plugin might override this for no apparent reasonDesired image with, the visualization plugin might override this for no apparent reasonDeviceDevice %s doesn't support %d channel soundDevice %s supports no %d-channel soundDevice to use as burner. Type "cdrdao scanbus" at the commandline for available devices. Leave this empty to use the default /dev/cdrecorder.Diamater of the lens (1 is image size)DiameterDidn't get max sample valueDidn't get min sample valueDiffDirectoryDisable Screensaver for fullscreen playbackDisable Screensaver for normal playbackDisable all data verification and correction features.Disable extra paranoiaDisable paranoiaDisables intra-read data verification; only overlap checking atread boundaries is performed. It can wedge if errors occur in the attempted overlap area. Not recommended.DisplayDisplay audio/video descriptionsDisplay audio/video formatsDisplay modeDisplay timeDisplay timecodesDisplay track name and timeDistance from the bottom text border to the image borderDistance from the left text border to the image borderDistance from the right text border to the image borderDistance from the top text border to the image borderDither modeDither mode. Auto means to use the quality level. Subsequent options are ordered by increasing quality (i.e. decreasing speed).Do RLE compressionDo monitorDo nothingDon't advanceDoubleDouble precisionDoubleclick on a track firstDrive:DriverDriver to use. Check the cdrdao manual page and the cdrdao README for available drivers/options. Leave this empty to attempt autodetection.Drives...Drop Drop bottom fieldDrop one field and change the pixel aspect ratio such that a subsequent hardware scaler will scale the image to the original heightDrop one field and scale the image to the original heightDrop top fieldDropping samplesDuration (milliseconds)EDL decoderEDL only works with seekable sourcesEdit chapterEdit chaptersEdit chapters...Edit keyEdit...Eject after burningEjecting disc failedEjecting disk failedEjecting disk failed: %sEnable 2-pass encodingEnable 4.0 SurroundEnable 4.1 SurroundEnable 5.0 SurroundEnable 5.1 SurroundEnable LCDprocEnable MonitorEnable OSDEnable monitoring of the webcam imageEnable postprocessingEnable visualizationsEncode audio into video fileEncode overlay subtitles into video fileEncode text subtitles into video fileEncode this stream in 2 passes, i.e. analyze it first and do the final transcoding in the second pass. This enables higher quality within the given bitrate constraints but roughly doubles the video encoding time.Encoder based on libquicktime (http://libquicktime.sourceforge.net) Writes Quicktime, AVI (optionally ODML), MP4, M4A and 3GPP. Supported codecs range from high quality uncompressed formats for professional applications to consumer level formats like H.264/AVC, AAC, MP3, Divx compatible etc. Also supported are chapters and text subtitlesEncodersEncoding audio failedEncoding postprocessorEncoding subtitles failedEncoding video failedEnd timeEnd time if before start timeEnter a custom device to use for playback. Leave empty to use the settings aboveEnter a custom device to use for recording. Leave empty to use the settings aboveEnter username and password forEnvironment variables EqualizerError foregroundEsounD input driverEsounD output driverExact matchExitingExpand allExport as EDLExports overlay subtitles into the format used by spumux (http://dvdauthor.sourceforge.net)Extension is appended by the plugin %t Inserts time %d Inserts date %n Inserts Frame number with digitsExtensionsFavouritesFileFile is no BMPFile is no pnmFile is no pnm (%.1s%.1s%.1s)Filename baseFiles Files...Filter with 1 inputFiltersFilters...Find tracksFind...Finished process [%d] return value: %dFixed channel setupFixed samplerateFlicker compensationFlip horizontallyFlip imageFlip verticallyFlip video images horizontally and/or verticallyFloatFloat RGBFloat RGBAFloating pointFluorescent lightingFontForce a sampleformat to be used for processing. None means to take the input format.Force alphaForce deinterlacingForce deinterlacing if you want progressive output and the input format pretends to be progressive also.Force hardware scalingForce languageForce pixelformatForce sampleformatForce the given language even if the input has the language set differently.Force volume fade at the end of moduleForces a pixelformat as input for the next filter. Its mainly used for testing.ForegroundForeground colorForgetFormatFormat for track namesFormat specifier for tracknames from metadata %p: Artist %a: Album %g: Genre %t: Track name %n: Track number with digits %y: Year %c: CommentForward search hit bottom, continuing at topForward search: No tracks foundFrame counterFrame durationFrame duration for user defined output framerate (Framerate = timescale / frame duration).Frame size: %d x %d Image size: %d x %d Pixel size: %d x %d Pixel format: %s Frame size: %d x %d Image size: %d x %d Pixel size: %d x %d Pixel format: %s Framenumber digitsFramenumber offsetFramerateFramerate: %f fps [%d / %d]%s Framerate: %f fps [%d / %d]%s Framerate: %.2f fpsFrom SourceFront CFront CLFront CRFront LFront RFront channelsFront to rear modeFullscreen modeGTK multimedia transcoder GUIGainGain (in dB) to apply to the audio samples before it is sent to the visualization pluginGain control (-1 = Auto)Gap between tracksGaussGaussian preblurGeneralGeneral OptionsGeneric affineGeneric colormatrix (RGBA). You pass the coefficients in RGB(A) coordinates, but the processing will work in Y'CbCr(A) as well.Generic colormatrix (Y'CbCrA). You pass the coefficients in Y'CbCr(A) coordinates, but the processing will work in RGB(A) as well.GenreGet colors from skinGet the latest source version from http://gmerlin.sourceforge.net * * * If you installed gmerlin from a binary package, you might have limited featuresGlobal optionsGmerlin GUI PlayerGmerlin Media TreeGmerlin Plugin ConfiguratorGmerlin Track InfoGmerlin confiurationGmerlin playerGmerlin transcoderGmerlin visualizerGo to the specified chapter. Use '+' and '-' to go to the next or previous chapter respectivelyGot initial audio timestamp: %sGot metadata from CD-TextGot metadata from CDDB (%s)Got metadata from gmerlin cache (%s)Got metadata from musicbrainz (%s)Got redirector %s (%d/%d)Got visualization plugin %sGot window size: %d %dGoto current trackGrab keyGrabbing key (Code: %d, modifiers: %s) failedGreenGreen -> AlphaGreen -> BlueGreen -> GreenGreen -> RedGreen gainGreen offsetHD 1080p/i (1920x1080)HD 720p/i (1280x720)HQSVCDHeightHelpHelp...HighHorizontal justifyHorizontal radiusHost (empty: local)Host to connect to, default is localhostHostnameHueISO 9660 volume labelIf a track cannot be opened, switch to the next oneIf disabled, the output channel configuration is taken from the source. If enabled, the setup you specify below us used.If disabled, the output samplerate is taken from the source. If enabled, the samplerate you specify below us used.If disabled, track name will be taken from filenameIf you select auto, the depth will be chosen according to the input formatIgnoreIgnore linebreaksIgnoring command while playback is interruptedIllegal pixelformatIllegal pixelformat: %sImage bordersImage converter Image readerImage readersImage sizeImage video input pluginImage writerImage writersIn- or decrease player volume. is in dBIncomingIncomplete Multibyte sequenceIncrease volumeIndoorInfo foregroundInfo windowInfo...Initialized audio filter %sInitialized video converter, %d stepsInitialized video filter %sInitializing %s failed, check settingsInputInput LanguageInput ModeInput and output are the same fileInput formatInput pluginInput plugin based on libquicktimeInput plugin could not be loadedInput plugin: %sInput pluginsInstalling skin from %s failedInterlace mode: %sInterlace mode: %sInterleaved channel pairsInterpolate missingInterpolate missing timecodesInterpolation modeInterval (sec)Invalid Multibyte sequenceInvalid answer: %sInvalid number of bitsInvalid number of channelsInvalid plugin type for video outputInvalid selection range givenInvalid track number %dInvert RGBAInvert alphaInvert blueInvert greenInvert redInvert single color channels. RGB(A) formats are processed directly, Y'CbCr(A) formats are processed with the colormatrix.JPEGJPEG qualityJPEG readerJPEG writerJoined threadKeyboard daemon configurationKeyboard daemon not foundLCDprocLED off time (secs)LED on time (secs)LFELanguageLaunch help in a webwroswerLaunch new player if necessaryLeave fullscreen modeLeftLeft borderLens effectLet the aspect ratio appear the same as in the source, probably resulting in additional borders.LinearLoad profileLoad profile...Load task listLoad tasklist...Loaded %s (track %d of %d)Loading %sLoading %s (plugin: %s)Loading %s failedLoading plugin "%s" failedLocationLocation: %sLog messagesLog reports about skipped framesLog windowLook for hidden patterns in moduleLowLuminanceLuminance -> AlphaLuminance -> CbLuminance -> CrLuminance -> LuminanceLuminance offsetM4AMP4MPEG-1/JPEGMPEG-2MPlayer mpsubMaintain aspect ratioMake streamableMake the file streamable afterwards (uses twice the diskspace)Making streamable....Making streamable....doneManualManual blue gainManual red gainMatch caseMatch upper and lower caseMaximum RIFF sizeMaximum RIFF size (in MB) for OpenDML AVIs. The default (1GB) is reasonable and should only be changed by people who know what they do.Maximum number of connectionsMaximum number of consecutive skipped framesMaximum number of messages hold in the windowMaximum number of retries, 0 = infiniteMaximum retriesMaximum skipped framesMedia TreeMedia tree is saved here. The albums are saved as separate files in the same directory.MediumMessageMetadataMetadata: %sMethodMiscMixMix mode when downmixing Stereo to Mono.Mix mode when the output format has rear channels, but the source doesn't.MixedMixerModeModifiersMonitorMonoMono 16bitMono 8bitMore than one chapter track found, using first oneMove DownMove UpMove to bottomMove to topMultichannel ModeMultimedia keys...Multipass encoding not supported by encoder pluginMultiple devicesMusicbrainzMuteNTSC CVD (352 x 480)NTSC DV 16:9 (720 x 480)NTSC DV 4:3 (720 x 480)NTSC DVD D1 16:9 (720 x 480)NTSC DVD D1 4:3 (720 x 480)NTSC SVCD 16:9 (480 x 480)NTSC SVCD 4:3 (480 x 480)NTSC VCD (352 x 240)NameName: %s Label: %sName: %s Location: %s Track: %d/%d%s Plugin: %s Duration: %s Audio Streams: %d Video Streams: %d Subtitle Streams: %dName: %s Long name: %s Type: %s Flags: %s Priority: %d DLL Filename: %sName: %sName: %sNearestNeverNew albumNew client connectionNew from directory...New...Next chapterNext trackNo audioNo current track for copying to favouritesNo input plugin definedNo options availableNo options here, choose subcategoryNo output plugin definedNo pauseNo plugin found for image %sNo soundcards foundNo stream to encodeNo such track %dNo symbol "ladspa_descriptor" found: %sNo symbol the_plugin in %sNoneNone (Downmix)None (Progressive)Normal foregroundNormalizeNormalize audioNormalize for constant luminance.Normalized X offset. 1 corresponds to image with.Normalized Y offset. 1 corresponds to image height.Not adding %s: Unsupported filenameNot availableNot closing album %s (open_count > 0)Not interleavedNot running cdrdao (disabled by user)Not specifiedNumber of messagesOSDOSSOSS RecorderOSS output driverOffOld colorOmitting chapter %d: time (%f) > duration (%f)OpenOpen album for and play first track. Device must be a GML (e.g. dvd:///dev/hdd).Open album for . Device must be a GML (e.g. dvd:///dev/hdd).Opening %s with "%s" failedOpening album %sOpening audio device failed, fix settings and click restartOpening input plugin failedOpening monitor plugin failedOption -add requires an argument Option -addplay requires an argument Option -chapter requires an argument Option -host requires an argumentOption -open requires an argument Option -openplay requires an argument Option -port requires an argumentOption -seek_rel requires an argument Option -volume requires an argument Option -volume_rel requires an argument OptionsOptions...Order for sinc scalingOutdoorOutputOutput DirectoryOutput directoryOutput filesOutput formatOutput framecounterOutput framerate. For user defined framerate, enter the timescale and frame duration below (framerate = timescale / frame duration).Output namebaseOutput optionsOutput plugin could not be loadedOutput plugin...Overall gain for this filter. This is only valid if you add the effect to the input dataOverlay subtitle defaultsOverlay subtitle exporterPAL CVD (352 x 576)PAL DV 16:9 (720 x 576)PAL DV 4:3 (720 x 576)PAL DVD D1 16:9 (720 x 576)PAL DVD D1 4:3 (720 x 576)PAL SVCD 16:9 (480 x 576)PAL SVCD 4:3 (480 x 576)PAL VCD (352 x 288)PAM format not suportedPBMasciiPBMbinPGMasciiPGMascii_16PGMbinPGMbin_16PNG readerPNG writerPNM readerPPMasciiPPMascii_16PPMbin_16PWC GeneralPWC LEDPWC WhitebalancePackbitsParser for gmerlin EDLsPasswordPassword for proxyPastePaste tracks from clipboardPathPausePause playbackPerspectivePhillips webcam detectedPinchPinch/whirlPixelformatPixelformat: %sPlayPlay current trackPlaybackPlayer cleaned upPlayer now changingPlayer now playingPlayer now seekingPlaying audio stream %d Input format: %s Output format: %sPlaying video stream %d Input format: %s Output format: %sPluginPlugin %s doesn't support embedded windowsPlugin %s has no or wrong versionPlugin %s has zero priorityPlugin for audio CDs. Supports both playing with direct connection from the CD-drive to the souncard and ripping with cdparanoia. Metadata are obtained from Musicbrainz, freedb or CD-text. Metadata are cached in $HOME/.gmerlin/cdaudio_metadata.Plugin for exporting text subtitles. Supported formats are MPSub and SRTPlugin infoPlugin optionsPlugin...Plugin: PortPort to connect toPositionPostprocess onlyPostprocess...PostprocessingPostprocessing %sPre gap of each track in CD frames (1/75 seconds). Default is 150 (2 sec).Prefer EDLPreferences...Previous chapterPrevious trackPrint this help message and exitPrint this help message as a manual page and exitPrint this help message in texinfo format and exitPrint version info and exitPriorityProtocol mismatchProtocolsProxyProxy passwordProxy portProxy server (leave empty for direct connection)Proxy usernamePulseAudioPulseAudio capture. You can specify the source, where we'll get the audio.PulseAudio outputPurge directory (i.e. delete unused album files) at program exitPurge directory on exitPurging %sQCIF (176 × 144)QCIF (176x144)QSIF (160x112)QVGA (320 x 240)QVGA (320x240)QuadraticQualityQuestionQuicktimeQuicktime encoderQuitQuit gmerlinQuit programRGBRGB ColormatrixRadiusRead tga failedReader for BMP imagesReader for JPEG imagesReader for PBM/PGM/PPM imagesReader for PNG imagesReader for TGA imagesReader for TIFF imagesReading hello line failedReading welcome line failedRear CRear DeviceRear LRear RRear channelsRecRecordRecorderRecording and display pluginsRectangularRecursiveRedRed -> AlphaRed -> BlueRed -> GreenRed -> RedRed gainRed offsetRefreshReloaded keysRemixing to stereo for filter "%s"RemoteRemote controlRemote control command for the Gmerlin GUI Player Remote control command for the Gmerlin GUI transcoder Remote socket listening at port %dRemovable DeviceRemoveRemove allRemove redundantRemoving %sRename albumRename entryRename selected trackRename...Render optionsRenders via OpenGLRenders via gmerlinReopenRepeat modeReplace/remove/interpolate timecodesReport resultsResample chromaResample modeResample mode. Auto means to use the quality level. Subsequent options are ordered by increasing quality (i.e. decreasing speed).ResolutionRestart visualizationRestarting playback due to changed audio filtersRestarting playback due to changed audio optionsRestarting playback due to changed video filtersRestarting playback due to changed video optionsRightRight borderRotateRun cdrdaoSIF(352x240)SNDCTL_DSP_GETODELAY ioctl failedSQCIF (128 × 96)SVCDSampleformatSamplerateSamplerate %d not supported by device %s, using %dSamplerate %f kHz not supported by device %sSamplerate [Hz]SaturationSave as...Save profileSave profile...Save task listSave tasklist...Save user/password (can be dangerous!)Saving %s failedScaleScale modeScale orderScale qualityScaler (hardware)Scaler (software)Scan for devicesScancodeScanline doublerScanning %sScheduling %s for postprocessingScopeScope pluginSeconds can be fractional (i.e. with decimal point) Seek backwardSeek forwardSeek relative. is in seconds.Seek to startSeeked audio out of rangeSeeked beyond buffer.Seeked text subtitles out of rangeSeeked video out of rangeSelect a directorySelect a fileSelect action for this subtitle stream.Select error tracksSelected...Selecting track %d for %s failedSend finished files to playerSending command failedSending initialization string failedServerServer connection closedServer to connect to. Leave empty for default.SetSet end timeSet global options and track defaultsSet player volume. is in dB, 0.0 is maxSet start timeSet the buffer time (in milliseconds). Larger values improve playback performance on slow systems under load. Smaller values decrease the latency of the volume control.Set the buffer time (in milliseconds). Larger values improve recording performance on slow systems under load.Set the conversion quality for format conversions. Lower quality means more speed. Values above 3 enable slow high quality calculations.Set the if drop frame is used when adding new timecodesSet the integer framerate used when adding new timecodesSet the output image size. For a user defined size, you must specify the width and height as well as the pixel width and pixel height.Set the start frames used when adding new timecodesSet the start hours used when adding new timecodesSet the start minutes used when adding new timecodesSet the start seconds used when adding new timecodesSet the writing speed. 0 means autodetect.Setting up socket failed, this instance won't be reachable via remoteSettingsShapedSharpness (-1 = Auto)Show TooltipsShow debug messagesShow error messagesShow info messagesShow log windowShow toolbarShow tooltipsShow track infoShow warning messagesShuffle modeShutter speed (-1 = Auto)Side LSide RSigned 16 bitSigned 32 bitSigned 8 bitSimple temporal lowpassSimple volume controlSimple wrapper, which calls the mikmod programSimple writer for wave files, supports 8, 16, 24 and 32 bit PCMSimply double all scanlines. Very fast but low image qualitySimulateSimulate old color- and B/W moviesSinc bestSinc fastSinc mediumSinc with Lanczos windowSizeSkin browserSkins...Skip almost identical framesSkip error tracksSkip the 10 second pause before writing or simulating starts.Skip transcoding of this track and send the file directly to the postprocessor.Skipped %d framesSkipping cdrdao run (no tracks)Skipping postprocessing (no suitable files found)Software scalerSortSort and configure audio codecsSort and configure video codecsSourceSource to open. Use the PulseAudio manager for available Sources.Specifies how much a block may differ from the last non-skipped block. 0 means identical blocks, 1 means completely different blocks. Note that the meaning of "completely different" depends on the colorspace.Specifies how much a frame may differ from the last non-skipped frame. 0 means identical frames, 1 means completely different frames. Note that the meaning of "completely different" depends on the colorspace.Specifies how much blurring should be applied when downscaling. Smaller values can speed up scaling, but might result in strong aliasing.Specifies the antialiasing filter to be used when downscaling images.Specifies which field the deinterlacer should drop.Specify a start time below. This time will be slightly wrong if the input format doesn't support sample accurate seeking.Specify an end time below.Specify fontsize for OSD. The value you enter, is for an image width of 640. For other widths, the value will be scaledSpecify, how many different characters are cached for faster rendering. For European languages, this never needs to be larger than 255.SpeedStart timeStart transcodingStarted threadStarting input plugin failedState %02x -> %02x StereoStereo 16bitStereo 8bitStereo to mono modeStill image Still image framerateStop playbackStop transcodingStream %dStream %d [%s]StrengthString is an exact substringStyleSubdirectorySubdirectory, where this track will be written toSuboptions for %sSuboptions for %s=%sSubrip (.srt)Subtitle optionsSubtitle stream %d/%d [%s]Subtitle stream cannot be handledSubtitle streams %dSubtitlesSubtitles #%dSubtitles #%d: %sSubtitles...Subtitles: %sSupported options: Supported options: Supported strings: Switch deamon on and off. If you want to start the daemon with each start of X, add "gmerlin_kbd" to your startup programsSwitch to next trackSwitch to previous trackTGA readerTGA writerTIFF readerTIFF writerTOC fileTabbed modeTake pictureTake the display colors from the skin definitionTasklistTemplate for the output files. A mask "%n" inserts the frame number with digits (e.g. webcam-shot-%6n)Template for track name generation from metadata %p: Artist %a: Album %g: Genre %t: Track name %n: Track number (d = number of digits, 1-9) %y: Year %c: CommentTemporal lowpassText box (bottom)Text box (left)Text box (right)Text box (top)Text colorText subtitle defaultsText subtitle exporterText subtitle stream %d: Blending onto video stream %dText subtitle stream %d: Exporting to fileText subtitlesTextrendererThis forces a sampleformat as input for the next filter. Its mainly used for testing.This is a frontend for generating (S)VCD images with the vcdimager tools (http://www.vcdimager.org). Burning with cdrdao (http://cdrdao.sourceforge.net) is also possible.This is a frontend for generating audio CD images (optionally with CD-Text) for cdrdao (http://cdrdao.sourceforge.net). Optional burning is also supported.This is free software. You may redistribute copies of it under the terms of the GNU General Public License . There is NO WARRANTY.This is free software. You may redistribute copies of it under the terms of the GNU General Public License . There is NO WARRANTY. This option is used if the source has an alpha (=transparency) channel, but the output supports no transparency. Either, the transparency is ignored, or the background color you specify below is blended in.This parses the XML file and exports an EDL, which can be played with the builtin EDL decoder.This plugin encodes a video as a series of images. It uses the installed image writers.This plugin reads images as stills. It uses the installed image readers.This plugin reads series of images as a video. It uses the installed image readers.This will enable 2 pass transcoding. In the first pass, the peak volume is detected. In the second pass, the stream is transcoded with normalized volume.TimeTime to pass until the next track will be selected. 0 means infinite.TimeoutTimeout (in seconds) for connections to the CDDB serverTimescaleTimescale for user defined output framerate (Framerate = timescale / frame duration).TitleToggle muteToneTopTop borderTop field firstTop leftTop left corner in normalized image coordinatesTop rightTop right corner in normalized image coordinatesTotal playback timeTotal thresholdTrackTrack defaultsTrack has neither audio nor video, skippingTrack nameTrack optionsTrack: %dTrackname templateTranscodeTranscode as overlayTranscode as textTranscoderTranscoder configurationTranscoding %s [Track %d, Pass %d/%d]Transcoding %s [Track %d]TransformTransform the image with different methodsTransformation modeTrebleTree...TriangularTry to get CD metadata from CD-TextTunerTweak timecodesType %s not handled for %sURLURL:URLs...UndefinedUnexpected EOF, clearing frameUnknownUnknown channelUnknown errorUnknown sampleformat %dUnknown scale mode %s Unnamed discUnrecognized fileformatUnsigned 16 bitUnsigned 8 bitUnsupported bits per sample (%d) for UINTUnsupported compression for LOGL/LOGLUVUnsupported depth %d for IEEE floatUnsupported sampleformatUnsupported samples per pixelUrls...Use CD-TextUse CddbUse Center/LFE DeviceUse MusicbrainzUse Rear DeviceUse hardware scaling even if it involves more CPU intensive pixelformat conversionsUse interpolate mixingUse locally saved metadataUse metadata for track namesUse surround mixingUse the surround 4.0 (aka quadrophonic) deviceUse the surround 4.1 deviceUse the surround 5.0 deviceUse the surround 5.1 deviceUsed for configuration data. Delete this file if you think you goofed something up.User definedUser defined heightUser defined height in pixels. Only meaningful if you selected "User defined" for the image size.User defined pixel heightUser defined pixel height. Only meaningful if you selected "User defined" for the image size.User defined pixel widthUser defined pixel width. Only meaningful if you selected "User defined" for the image size.User defined widthUser defined width in pixels. Only meaningful if you selected "User defined" for the image size.User deviceUser name for proxy (leave empty for poxies, which don't require authentication)UserguideUsernameUsing statistics file: %sV4LV4L DeviceVCD 1.1VCD 2.0VCD image generator/burnerVCD optionsVGA (640 x 480)VGA (640x480)VIDIOCGMBUF failed: %sVIDIOCGPICT failed: %sVIDIOCGWIN failed: %sVIDIOCSPICT failed: %sVIDIOCSWIN failed: %s (invalaid picture dimensions?)Vertical justifyVertical radiusVideoVideo #%dVideo #%d: %sVideo CodecsVideo FiltersVideo defaultsVideo encoderVideo filterVideo filtersVideo frame counter: %sVideo optionsVideo outputVideo recorderVideo streamVideo stream %d input format: %sVideo stream %d output format: %sVideo stream %d/%dVideo stream %d: Transcoded %s framesVideo stream to blend ontoVideo streams %dVideo...Video: %sVisit homepageVisualizationVisualization process crashed, restart to try againVisualization...VisualizationsVisualize test VisualizerVisualizer configurationVolumeVolume controlWarning foregroundWave writerWhen showing still images, gmerlin repeats them periodically to make realtime filter tweaking work.Whenever we obtain CD metadata from the internet, we save them into $HOME/.gmerlin/cdaudio_metadata. If you got wrong metadata for a CD, disabling this option will retrieve the metadata again and overwrite the saved data.White balanceWhitenessWideningWidthWindowWindowed modeWindowsWindows...Write CD-TextWrite info chunkWriter for BMP imagesWriter for JPEG imagesWriter for PNG imagesWriter for TGA imagesWriter for TIFF imagesWriting imageWrote %sXX -> XX -> YX OffsetX11X11 display driver with support for XVideo, XImage and OpenGL. Shared memory (XShm) is used where available.Xml fileYY -> XY -> YY OffsetY'CbCr(A) ColormatrixYCrCbYUV 410 PlanarYUV 411 PlanarYUV 420 PlanarYUV 422 (UYVY)YUV 422 (YUY2)YUV 422 PlanarYUV 422 Planar (16 bit)YUV 444 PlanarYUV 444 Planar (16 bit)YUVA 4444YUVJ 420 PlanarYUVJ 422 PlanarYUVJ 444 PlanarZeroZero order holdZero peaks detected (silent file?). Disabling normalization.ZoomZoom factorZoom horizontallyZoom horizontally and/or verticallyZoom vertically[-co options] input_image output_image [1|0] (default: %d)[] [Options][options] [options] [gmls ...] [options] command [options] gml... bg_plugin_ref %s: %dbg_plugin_unref %s: %dbg_plugin_unref_nolock %s: %dcdio_close_tray failedcdio_close_tray failed: %scdrdao executable not foundcontrol digital audio info failed (%i): %scontrol hardware info failed (%i): %scontrol open failed (%i): %sdefault: %%.%df)default: %d)default: %s)dlopen failed for %s: %sdo_capture: No plugin loadedh:ladspa plugin Author: %s Copyright: %slibquicktime input pluginlibvisual pluginm:mikmod input pluginmmap failed: %sms:option[{suboptions}]read_frame faileds:snd_ctl_card_info failedsnd_ctl_card_info_malloc failedsnd_ctl_pcm_next_device failedsnd_hctl_elem_read failedsnd_hctl_elem_write failedsnd_hctl_load failedsnd_hctl_open failedsnd_pcm_hw_params failedsnd_pcm_hw_params_any failedsnd_pcm_hw_params_malloc failedsnd_pcm_hw_params_set_access failedsnd_pcm_hw_params_set_buffer_size failedsnd_pcm_hw_params_set_channels failed (Format has %d channels)snd_pcm_hw_params_set_format failedsnd_pcm_hw_params_set_period_size failedsnd_pcm_hw_params_set_rate_near failedsnd_pcm_open failed for device %s (%s)snd_pcm_prepare failedsnd_pcm_write returned %sspumux overlay exportervcdxgen failed: %svideo4linux recording plugin. Supports only video and no tuner decives.{[[HH:]MM:]SS} ({option[{suboptions}][:option[{suboptions}]...]}Project-Id-Version: gmerlin 0.3.6 Report-Msgid-Bugs-To: gmerlin-general@lists.sourceforge.net POT-Creation-Date: 2012-06-08 13:50+0200 PO-Revision-Date: 2009-12-19 00:17+0100 Last-Translator: Burkhard Plaum Language-Team: German MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Plural-Forms: nplurals=2; plural=(n != 1); Über: %s Author: %s Farbebenenplatzierung: %s Farbebenenplatzierung: %s Hilfe: %s Lizenz: %s Timecodeflags: Timecodeflags: Timecoderate: %d Timecoderate: %d Version: %s (Voreinstellung: %s)(konstant) (variabel)%s (Stunden)%s (Millisekunden)%s (Minuten)%s (Sekunden)%s kompatibel mit%s Meldungen.SH UMGEBUNGSVARIABLEN .SH DATEIEN 0 heißt kein Effekt, 1 heißt Maximum (= Standbild)15 bpp BGR15 bpp RGB16 bit16 bpp BGR16 bpp RGB16CIF (1408 × 1152)23.976 (in NTSC einbetette Filmrate)24 (Internationale standard Kinofilmrate)24 bpp BGR24 bpp RGB25 PAL [625/50] Videorate29.970 (NTSC Videorate)30 (NTSC drop-frame [525/60] Videorate)32 bit32 bpp BGR32 bpp RGB32 bpp RGBA3GP48 bpp RGB4CIF (704 × 576)50 (doppelte progressive PAL-Rate)59.940 (doppelte progressive NTSC-Rate)60 (doppelte drop-frame NTSC-Rate)64 bpp RGBA8 bit (, und sind im Bereich 0.0..1.0, und sind im Bereich 0.0..1.0,, (Voreinstellung: %.3f,%.3f,%.3f),,, (Voreinstellung: %.3f,%.3f,%.3f,%.3f), (Voreinstellung: %.3f,%.3f)@item Umgebungsvariablen @item Dateien ASCIIAUXAVIAVI (Opendml)ÜberÜber Gmerlin VisualisiererÜber...Zubehör...AktionAktionen%s hinzufügenFüge zum Eingangs-AlbumFüge zum Eingangs-Album und starte WiedergabeFüge URLs zum Album %s hinzuFüge URLs hinzuFüge Alben zu %s hinzuGerät hinzufügenFüge Gerät hinzu...Addiere Effekt zu den QuelldatenDateien hinzufügenFüge Dateien zum Album %s hinzuAdditionsverstärkungNeue hinzufügenNeue hinzufügen (nur ersten)Neues Kapitel hinzufügenTaste hinzufügenFüge Unterverzeichnisse als Unteralben hinzuHinzufügen...AlbumAlbum %s ist bereits offenAlbumnameAlbum...Alben...Alle Kanäle interleavedAlle offenen AlbenErlaube Verbindungen von anderen MaschinenTransparenzTransparenz -> TransparenzTransparenz -> BlauTransparenz -> CbTransparenz -> CrTransparenz -> GrünTransparenz -> LuminanzTransparenz -> RotTransparenzmodusTransparenz OffsetAlsaAlsa Initialisierung fehlgeschlagenAlsa Ausgabeplugin mit Unterstützung für Kanalkonfigurationen bis zu 5.1Alsa AufnahmeImmerMache immer Farbenebenen-Resampling, wenn die Farbplazierungen verschieden sind. Normalerweise wird dies nur für Qualitätsstufen über 3 gemacht.WinkelFüge URLs an die Aufgabenliste anFüge Dateien an die Aufgabenliste anFüge Wechselmedien an die Aufgabenliste anWähle Verstärkungen für Rot, Grün und Blau. RGB Formate werden direkt verarbeitet. Y'CbCr werden mit der Farbmatrix verarbeitet.KünstlerAspektverhältnis geändertHänge Untertitelstream an diesen Videostream an. Wenn der Stream auf das Video gemischt wird, ist dies der Videostream, der die Untertitel bekommt. Für das Enkodieren werden Bildwiederholrate und -größe von diesem Videostream genommen, da diese manchmal von Enkodern gebraucht werden.AudioAudio #%dAudio #%d: %sAudio CDs erzeugen/brennenAudio CD OptionenAudio CD Spieler/RipperAudio CD track %02dAudio CodecsAudiofilterAudio VoreinstellungenAudioenkoderAudiofilterAudio FilterAudio OptionenAudioausgabeAudiorecorderAudiosamplezähler: %sAudiostream %d, Quellformat: %sAudiostream %d, Ausgabeformat: %sAudiostream %d/%dAudiostream %d: %s Abtastwerte transkodiertAudio streams %dAudio...Audio-/VideoenkoderAudio: %sAuthentifizierungAutorAuthor: %s %sAutomatischAutomatischAutomatische VerzögerungAutomatischFenstergröße automatisch ändernAutomatische GeschwindigkeitAutomatisch aufnehmenSpeichere automatisch Aufnahmen im angegebenen IntervallBMP ImporteurBMP ExporteurBUG!!! convert_func == 0x0HintergrundHintergrundfarbeHintergrundfarbe, die verwendet wird, wenn der Transparenzmodus oben auf "Hintergrundfarbe einblenden" steht.HintergrundlichtausgleichRückwärtssuche hat Angang erreicht, mache am Ende weiterRückwärtssuche: Keine Tracks gefundenTiefenBilinearBin DateiBinärBitsBits pro KanalBits pro AbtastwertFelder mischenHintergrundfarbe einblendenMische aufs VideoBlockschwelleBlauBlau -> TransparenzBlau -> BlauBlau -> GrünBlau -> RedBlauverstärkungBlau OffsetWeichzeichnenWeichzeichner basierend auf gavl. Unterstützt Dreieck, Rechteck und Gauß.RandfarbeRandfarbeUntenUnterer RandUnteres Feld zuerstUnten linksUntere linke Ecke in normierten BildkoordinatenUnten rechtsUntere rechte Ecke in normierten BildkoordinatenHelligkeitDurchsuchen...PufferzeitBrennoptionenBrenne Timecodes in VideobilderCD Brenner (%s)CD-ROM Laufwerk (%s)CIF (352 × 288)CIF (352x288)Zwischenspeicher für die Plugin-Registry (von allen Programmen gemeinsam benutzt)CachegrößeKann Dateityp nicht lesenKann Socket nicht binden: %sKann nicht zum Dämon verbindenKann Verzeichnis %s nicht erstellen: %s, nehme VoreinstellungKann keinen Inet-Serversocket erzeugenKann Socket nicht erzeugenKann keinen UNIX-Serversocket erzeugenKann keinen UNIX-Socket erzeugenKann Bildgröße nicht ermittelnKann das mikmod programm nicht findenKann Plugin %s nicht findenKann Dauer der Datei %s nicht ermittelnKann keinen gmerlin Prozess startenKann Transkoderprozess nicht startenKann frei0r Plugin %s nicht ladenKann %s nicht öffnenKann %s nicht öffnen: %sKann %s nicht öffnen: Kein Plugin gefundenKann Gerät %s nicht öffnen: %sKann Datei "%s" nicht zum Schreiben öffnenKann Datei %s nicht öffnenKann Datei %s nicht öffnen: %sKann Ausgabedatei %s nicht öffnenKann Socket nicht in Lauschmodus schaltenKann Dateityp nicht lesenKann Höhe nicht lesenKann Maxval nicht lesenKann Breite nicht lesenKann Adresse von %s nicht auflösen: %sKann %s nicht speichern: %sKann nicht zum Startpunkt suchenKann Track nicht auswählen, überspringeKann nicht in Blockiermodus wechselnKann nicht in Nichtblockiermodus wechselnKann Zahlenformat für %s nicht setzenKann Dateistatus von %s nicht ermitteln: %sAufnahmeAufnahmeintervallAufnahmeintervall (in Sekunden)KarteEinstellungen für KarteCbCb -> TransparenzCb -> CbCb -> CrCb -> LuminanzCb OffsetCddbCdparanoiaMitteMitte der LinseGerät für Mitte/LFEÄndere Enkoderplugins für ausgewählte TracksWechsele Enkoder...Aufnahmeplugin geändert zu %sKanalmodusKanäle: %d Kanalreihenfolge: %s Abtastfrequenz: %d Abtastwerte pro Rahmen: %d Interleave Modus: %s Zahlenformat: %sKanäle: %d Kanalreihenfolge: %s Abtastfrequenz: %d Abtastwerte pro Rahmen: %d Interleave Modus: %s Zahlenformat: %sKapitel %dKapitel %d [%s]KapitelWähle Transformationsmethode. Jede Methode kann in einer eigenen Sektion konfiguriert werden.Wähle die Interpolationsmethode. Automatisch heißt Wahl aufgrund der Qualität. "Nächstes Pixel" ist am schnellsten, Bikubisch ist am langsamsten.Nehme LinksNehme RechtsWähle die Skaliermethode. Automatisch heißt Wahl aufgrund der Qualität. "Nächstes Pixel" ist am schnellsten, Sinc mit Lanczos Fenster ist am langsamsten.FarbabtastungAufräumen nach der WeiterverarbeitungLösche alle enkodierten Dateien, die weiterverarbeitet wurdenClientverbindung geschlossenSchließenSchließe Album und werfe Disk ausSchließe Album %sCodecAlles einklappenFarbe für DebugmeldungenFarbe für FehlermeldungenFarbe für InfomeldungenFarbe für WarnungenFarbe für die BildränderFarbbalanceFarbeBefehlBefehl "%s" vom Server nicht verstandenKommandozeilen-Multimediaplayer BefehleBefehle...KommentarKommentar (wird an jeden Dateianfang geschriebenKompressionKompressionslevelKonfigurierenKonfiguriere ausgewählten TrackKonfigurationstest Konfigurieren...Verbindung fehlgeschlagenVerbindung fehlgeschlagen: %sVerbindung vom UNIX-Socket fehlgeschlagenZeitüberschreitung beim VerbindenVerbindungsaufbau zu PulseAudio fehlgeschlagen: %sVerbindung zum Server aufgrund eines Fehlers geschlossenVerbindung zum Server hergestellt, Displaygröße: %dx%dKontrastKontrolliert Ton, Sättigung, Kontrast und Helligkeit. Für Y'CbCr benutzt es Routinen basierend auf die fv_eq un d vf_hue Filters vom MPlayer Projekt. Für RGB Formate wird die Farbmatrix benutzt.Einstellungen für %sUmrechnungsqualitätKopierenKopiere AllesKopiere aktuellen Track zu FavoritenKopiere AuswahlKopiere ausgewählte Tracks in die ZwischenablageKopiere ausgewählte Tracks zu FavoritenKopiere zu FavoritenCopyrightCopyright (C) 2001-2007 Mitglieder des gmerlin projekts Korrigiere Lautstärke um %.2f dBKann Socket nicht bindenKonnte keine Verbindung zum Server %s:%d aufbauenKonnte keine Alsa-Mischer finden. Überprüfe deine Einstellungen. Kein GL Visual erhaltenKonnte keine "welcome" Zeile bekommenKonnte Adresse nicht auflösen für %sKonnte keine "hello" Nachricht schickenKonnte Albumdatei %s nicht öffnenCrCr -> TransparenzCb -> CbCr -> CrCr -> LuminanzCr OffsetErgeuge ein Video mit Transparenzkanal, selbst wenn die Quelle keinen hat. Benutze diese Option um einen Transparenzkanal aus den anderen Kanälen mit der Farbmatrix zu erzeugen.Verzeichnis erstellt: %sProzess gestartet: %s [%d]Starten eines Prozesses fehlgeschlagen: %sCreative MultichannelZuschneidenZuschneiden und SkalierenBeschneide und Skaliere Videobilder. Hat viele Standardbildgrößen als Voreinstellungen. Kann auch Plazierung der Farbebenen korrigieren und einfaches Deinterlacing durchführen.Schneide untenSchneide linksSchneide rechtsSchneide obenKubisch B-SplineKubisch Catmull-RomKubisch Mitchell-NetravaliCue DateiAktuelles AlbumAuschneidenVerschiebe ausgewählte Tracks in die ZwischenablageSchneide so viele Pixel vom unteren Rand der Quellbilder.Schneide so viele Pixel vom linken Rand der Quellbilder.Schneide so viele Pixel vom rechten Rand der Quellbilder.Schneide so viele Pixel vom oberen Rand der Quellbilder.DV PALDVD Laufwerk (%s)DVD Brenner (%s)Dämon läuftDebug VordergrundDezimierenLeiserVoreingestelltVoreingestellter FarbraumVoreingestellte BildwiederholrateVoreingestelltes FormatVoreingestellte HöheVoreingestellte Pluginparameter werden von hier gelesen. Nehme gmerlin_plugincfg um die zu ändernVoreingestellter Port für die FernbedienungVoreingestellte BreiteVoreinstellung: %sDeflateDeflate KompressionslevelDeinterlaceDeinterlacemethodeDeinterlacer mit verschiedenen MethodenDeinterlacerLöschenLösche AlbumLösche KapitelLösche unvollständige AusgabedateienTaste löschenLösche ausgewählte TracksLösche enkodierte Dateien wenn Du den "Stop"-Button drückst. Diese Option wird automatisch deaktiviert, wenn der Track eine URL ist.Tiefe %d nicht unterstütztGewünschte Bildhöhe. Das Visualisierungsplugin kann dies ohne erkennbaren Grund überschreiben.Gewünschte Bildbreite. Das Visualisierungsplugin kann dies ohne erkennbaren Grund überschreiben.GerätGerät %s unterstützt kein %d-Kanal AudioGerät %s unterstützt keinen %d-kanal SoundGerät mit dem gebrannt werden soll, Gib "cdrdao scanbus" an der Kommandozeile ein um verfügbare Geräte anzuzeigen. Leerlassen um die Voreinstellung (/dev/cdrecorder) zu benutzenDurchmesser der Linse (1 entspricht Bildgröße)DurchmesserMaximaler Abtastwert nicht erhalten.Minimaler Abtastwert nicht erhalten.DifferenzVerzeichnisDeaktiviere Bildschirmschoner für Abspielen im VollbildmodusDeaktiviere Bildschirmschoner für normales AbspielenSchalte alle Datenverizizierungs- und Korrekturfeatures aus.Schalte extra Paranoia ausSchalte Paranoia aus.Schaltet Leseverifizierung während des Lesens aus, nur Überlappprüfungen an Lesegrenzen werden durchgeführt. Kann hängenbleiben wenn Fehler im Überlappbereich auftreten. Nicht empfohlen.DisplayZeige Audio- und Videobeschreibnungen anZeige Audio- und Videoformate anDisplay modusAnzeigedauerTimecodes einblendenZeige Name und Zeit anAbstand vom unteren Textrand zum BildrandAbstand vom linken Textrand zum BildrandAbstand vom rechten Textrand zum BildrandAbstand vom oberen Textrand zum BildrandDithermodusDithermodus. Automatisch wählt den Modus aufgrund der Qualität. Nachfolgende Optionen sind nach aufsteigender Qualität (absteigender Geschwindigkeit) geordnet.Verwende RLE KompressionMonitor aktivMache nichtsNicht weiterschaltenFließkomma (doppelt)Doppelte GenauigkeitErst auf einen Track doppelklickenLaufwerk:TreiberZu verwendender Treiber. Lies die Manualpage oder die cdrdao README für verfügbare Treiber und Optionen.Laufwerke...DropLasse unteres Feld wegLasse ein Feld wegfallen und verdoppele die Pixelhöhe, so daß ein nachfolgender Hardware Skalierer das Bild wieder auf die originale Höhe skalieren kann.Lasse ein Feld wegfallen und skaliere das Bild zur Originalhöhe.Lasse oberes Feld wegÜberspringe AbtastwerteDauer (Millisekunden)EDL decoderEDL funktioniert nur mit suchbaren QuellenBearbeite KapitelBearbeite KapitelKapitel bearbeitenTaste bearbeitenBearbeiten...Nach dem Brennen auswerfenDatenträger auswerfen fehlgeschlagenDisk Auswerfen fehlgeschlagenDisk Auswerfen fehlgeschlagen: %sAktiviere 2-Pass EnkodierungVerwende 4.0 SurroundVerwende 4.1 SurroundVerwende 5.0 SurroundVerwende 5.1 SurroundSchalte LCDproc einVerwende MonitorAktiviere OSDVerwende Monitoring des WebcambildesVerwende WeiterverarbeitungVerwende VisualisierungenSchreibe Audio in die VideodateiSchreibe Oberlayuntertitel in die VideodateiSchreibe Textuntertitel in die VideodateiEnkodiere diesen Stream in 2 Durchläufen, d.h. analysiere ihn erst und enkodiere ihn endgütlig im zweiten Durchlauf. Dies bringt bessere Qualität für eine gegebene Bitrate aber verdoppelt in etwa die Enkodierzeit.Enkoder basierend auf libquicktime (http://libquicktime.sourceforge.net). Schreibt Quicktime, AVI (optional OpenDML), MP4, M4A und 3GPP. Unterstützte Codecs reichen von hochqualitativem unkomprimierten Formaten für professionelle Anwendungen bis to Endverbraucherformaten wie H.264/AVC, AAC, MP3, Divx compatible usw. Ebenfalls unterstützt werden Kapitel und Text-Untertitel.EnkoderTon Enkodieren fehlgeschlagenWeiterverarbeitungUntertitel Enkodieren fehlgeschlagenBild Enkodieren fehlgeschlagenEndzeitEndzeit vor AnfangszeitGib ein benutzerdefiniertes Gerät zur Wiedergabe an. Oder leerlassen für obige Einstellungen.Gib ein benutzerdefiniertes Gerät zur Aufnahme an. Oder leerlassen für obige Einstellungen.Gib Benutzernamen und Passwort ein fürUmgebungsvariablen EqualizerVordergrund (Fehler)Esound AufnahmepluginEsounD AusgabepluginGenaue ÜbereinstimmungBeendeAlles ausklappenAls EDL exportierenExportiert Overlay Untertitel im Format von spumux (http://dvdauthor.sourceforge.net)Erweiterung wird vom Plugin angefügt. %t Fügt Zeit ein %d Fügt Datum ein %n Fügt Bildnummer mit Stellen einErweiterungenFavoritenDateiDatei ist keine BMP DateiDatei ist kein PNMDatei ist kein pnm (%.1s%.1s%.1s)Basis für DateinamenDateien Dateien...Filter mit einem EingangFilterFilter...Suche TracksSuche...Prozess [%d] beendet, Rückgabewert: %dFeste KanalkonfigurationFeste AbtastrateFlackerausgleichHorizontal spiegelnSpiegelnVertikal spiegelnSpiegele Videobilder horizontal und/oder vertikalFließkommaFließkomma RGBFließkomma RGBAFließkommaLeuchtstofflampeSchriftErzwinge Zahlenformat für die Verarbeitung. Kein(s) bedeutet nehme das Quellenformat.Erzwinge TransparenzErzwinge DeinterlacingErzwinge Deinterlacing wenn Du progressive Ausgabe willst und das Quellenformat behauptet, ebenfalls progressiv zu sein.Erzwinge HardwareskalierungErzwinge SprachePixelformat erzwingenErzwinge ZahlenformatErzwinge die angegebene Sprache, selbst wenn die Quelle was anderes behautpet.Erzwinge Ausblenden am ModulendeErzwingt ein Pixelformat als Eingabe für das nächste Filter. Wird überwiegend zum Testen benutzt.VordergrundVordergrundfarbeVergessenFormatFormat für TracknamenFormat für Erzeugung von Tracknamen aus Metadaten %p: Künstler %a: Album %g: Genre %t: Trackname %n: Tracknummer mit Stellen %y: Jahr %c: KommentarVorwärtssuche hat Ende erreicht. Mache am Anfang weiterVorwärtssuche: Keine Tracks gefundenBilderzählerBilddauerZeitskala für benutzerdefinierte Bildwiederholfrequenz (Bildwiederholfrequenz = Zeitskala / Bilddauer)Rahmengröße: %d x %d Bildgröße: %d x %d Pixelgröße: %d x %d Pixelformat: %s Rahmengröße: %d x %d Bildgröße: %d x %d Pixelgröße: %d x %d Pixelformat: %s Dezimalstellen für BildnummerOffset für BildnummerBildwiederholrateBildwiderholrate: %f fps [%d / %d]%s Bildwiderholrate: %f fps [%d / %d]%s Bildwiederholrate: %.2f fpsWie QuelleVorne CVorne CLVorne CRVorne LVorne RFrontkanäleVorne nach hinten modusVollbildGTK Multimediatranscoder GUIVerstärkungVerstärkung (in dB) für die Audio Abtastwerte, bevor sie zum Visualisierungsplugin geschickt werdenVerstärkung (-1 = Automatisch)Lücke zwischen TracksGaußGauß'scher VorweichzeichnerGenerellAllgemeine OptionenAllgemein affinAllgemeine Farbmatrix (RGBA). Du gibst die Koeffizienten in RGB(A) Koordinaten an, die Verarbeitung funktioniert aber auch in Y'CbCr(A).Allgemeine Farbmatrix (Y'CbCrA). Du gibst die Koeffizienten in Y'CbCr(A) Koordinaten an, die Verarbeitung funktioniert aber auch in RGB(A).GenreHole Farben vom SkinHole den neuesten Quellcode von http://gmerlin.sourceforge.net * * * Wenn Du gmerlin als Binärpaket installiert hast, könnten die Features eingeschränkt seinGlobale OptionenGmerlin GUI SpielerGmerlin Media TreeGmerlin PluginkonfigurationGmerlin Track InfoGmerlin KonfiurationGmerlin PlayerGmerlin TranscoderGmerlin VisualisiererGehe zu einem bestimmten Kapitel. Mit '+' oder '.' kommst Du zum nächsten bzw. vorherigen KapitelErster Audiozeitstempel erhalten: %sMetadaten von CD-Text erhaltenMetadaten von CDDB erhalten (%s)Metadaten vom Gmerlin cache erhalten (%s)Metadaten von Musicbrainz erhalten (%s)Weiterleitung erhalten %s (%d/%d)Visualisierungsplugin erhalten: %sFentstergröße erhalten: %d %dGehe zum nächsten TrackTaste auslesenExklusiver Zugriff auf Taste (Code: %d, Modifizierer: %s) fehlgeschlagenGrünGrün -> TransparenzGrün -> BlauGrün -> GrünGrün -> RotGrünvertsärkungGrün OffsetHD 1080p/i (1920x1080)HD 720p/i (1280x720)HQSVCDHöheHilfeHilfe...HochHorizontale AusrichtungHorizontaler RadiusRechner (leer: lokal)Rechner zum Verbinden. Voreinstellung ist localhostRechnernameTonISO 9660 DatenträgerbezeichnungWenn ein Track nicht geöffnet werden kann, springe zum nächsten.Wenn ausgeschaltet, wird die Kanalkonfiguration von der Quelle übernommen. Wenn eingeschaltet, wird die Konfiguration, die Du unten angibst, verwendet.Wenn ausgeschaltet, wird die Abtastrate für die Ausgabe von der Quelle übernommen. Wenn eingeschaltet, wird die Abtastrate, die Du unten angibst, genommen.Wenn deaktiviert, wird der Trackname aus dem Dateinamen erzeugtWenn Du "Auto" wählt, wird die Tiefe anhand des Quellenformats gewählt.IgnorierenIgnoriere ZeilenumbrücheIgnoriere Befehl während das Absplielen unterbrochen istIllegales PixelformatIllegales Pixelformat: %sBildrandBilder Konverter BildimporteurBilderimporteureBildgrößeBilder als VideoBildexporteurBild ExporteureErhöhe oder Verringere die Lautstärke. ist in dBEingangUnvollständige Multibyte-SequenzLauterDrinnenInfo VordergrundTrack informationInfo...Initialisierte Audiofilter %sInitialisierte Videokonverter (%d Schritte)Initialisierte Videofilter %sInitialisierung von %s fehlgeschlagen, überprüfe EinstellungenQuelleUrsprüngliche SpracheEinlesemodusQuelle und Ausgabe sind die gleiche DateiQuellenformatQuellenpluginQuellenplugin basierend auf libquicktimeQuellplugin konnte nicht geladen werdenQuellenplugin: %sQuellenpluginsInstallation des Skins von %s fehlgeschlagen.Interlacemodus: %sInterlacemodus: %sInterleavte KanalpaareInterpoliere fehlendeInterpoliere fehlende TimecodesInterpolationsmethodeIntervall (sek)Ungültige Multibyte-SequenzUngültige Antwort: %sUngültige Anzahl an BitsUngültige Anzahl an KanälenUngültiger Plugintyp für VideoausgabeUngültiger AuswahlbereichUngültige Tracknummer %dInvertiere RGBAInvertiere TransparenzInvertiere blauInvertiere grünInvertiere rotInvertiere einzelne Farbkanäle. RGB(A) Formate werden direkt verarbeitet. Y'CbCr(A) werden mit der Farbmatrix verarbeitet.JPEGJPEG QualitätJPEG ImporteurJPEG ExporteurThread beendetTastaturdämon KonfigurationTastaturdämon nicht gefundenLCDprocLED Auszeit (secs)LED Einzeit (secs)SubwooferSpracheStarte Hilfe im WebbrowserStarte neuen Player wenn nötigBeende VollbildLinksLinker RandLinseneffektLasse das Aspektverhältnis genauso erscheinen wie in der Quelle, möglicherweise mit zusätzlichen RändernLinearLade ProfilLade Profil...Lade AufgabenlisteLade Aufgabenliste...%s geladen (Track %d von %d)Lade %sLade %s (Plugin: %s)Laden von %s fehlgeschlagenLaden von Plugin "%s" fehlgeschlagenOrtOrt: %sMeldungenSende Berichte über weggelassene BilderMeldungenSuch nach versteckten Mustern im ModulNiedrigLuminanzLuminanz -> TransparenzLuminanz -> CbLuminanz -> CrLuminanz -> LuminanzLuminanz OffsetM4AMP4MPEG-1/JPEGMPEG-2MPlayer mpsubErhalte AspektverhältnisMake streamableMache die Datei streamfähig (benötigt doppelten Festplattenplatz)Mache streamfähig...Mache streamfähig...fertigManuellManuelle BlauverstärkungManuelle RotverstärkungGroß/Kleinschreibung beachtenGroß/Kleinschreibung beachtenMaximum RIFF sizeMaximale RIFF-Größe (in MB) für OpenDML AVIs. Die Voreinstellung (1GB) ist vernünftig und sollte nur von denen geändert werden, die wissen was sie tun.Maximale Zahl der VerbindungenMaximalzahl der hintereinander übersprungenen BilderMaximale Zahl der Meldungen die im Fenster gehalten werdenMaximale Zahl von Widerholungen, 0 heißt unendlich.Maximale WiederholungenMaximal übersprungene BilderMedia TreeMediatree wird hier gespeichert. Alben werden als separate Dateien im gleichen Verzeichnis gespeichertMittelMeldungMetadatenMetadaten: %sMethodeVermischtesMischenMischmethode zum Heruntermischen von Stereo auf Mono.Mischmodus wenn die Ausgabe Hinterkanäle hat, aber die Quelle nicht.GemischtMischpultModusModifiziererMonitorMonoMono 16bitMono 8bitMehr als ein Kapiteltrack gefunden, nehme ersten.Verschiebe nach untenVerschiebe hochVerschiebe ganz nach untenVerschiebe ganz nach obenMehrkanal ModusMultimedia Tasten...Multipassenkodierung wird vom Enkoderplugin nicht unterstütztMehrere GeräteMusicbrainzStummNTSC CVD (352 x 480)NTSC DV 16:9 (720 x 480)NTSC DV 4:3 (720 x 480)NTSC DVD D1 16:9 (720 x 480)NTSC DVD D1 4:3 (720 x 480)NTSC SVCD 16:9 (480 x 480)NTSC SVCD 4:3 (480 x 480)NTSC VCD (352 x 240)NameName: %s Bezeichnung: %sName: %s Ort: %s Track: %d/%d%s Plugin: %s Dauer: %s Audio Streams: %d Video Streams: %d Untertitel Streams: %dName: %s Langer name: %s Typ: %s Flags: %s Priorität: %d DLL Dateiname: %sName: %sName: %sNächstes PixelNieNeues AlbumNeue ClientverbindungNeu von Verzeichnis...Neu...Nächstes KapitelNächster TrackKein AudioKein aktueller Track zum Kopieren zu FavoritenKein Quellplugin definiertKeine Optionen verfügbarKeine Optionen hier, gehe zu UnterkategorieKein Ausgabeplugin definiertKeine PauseKein Plugin gefunden für Bild %sKeine Soundkarten gefundenKein Stream zum EnkodierenKein solcher Track %dKein Symbol "ladspa_descriptor" gefunden: %sKein Symbol "the_plugin" in %sKein(s)Keiner (Runtermischen)Keiner (progressiv)Vordergrund (normal)NormiereNormiere AudioNormiere für konstante HelligkeitNormierter X-Offset. 1 enspricht Bildbreite.Normierter Y-Offset. 1 enspricht Bildhöhe.Füge %s nicht hinzu: Nicht unterstützter DateinameNicht verfügbarWerde Album %s nicht schließen (open_count > 0)Nicht interleavedLasse cdrdao nicht laufen (vom Benutzer abgeschaltet)UnspezifiziertZahl der MeldungenOSDOSSOSS AufnahmeOSS AusgabetreiberAusAlte FarbenLasse Kapitel %d weg: Startzeit (%f) > Dauer (%f)ÖffnenÖffne Album für und spiele ersten Track. Gerät muß eine GML sein (z.B. dvd:///dev/hdd)Öffne Album für . Gerät muß eine GML sein (z.B. dvd:///dev/hdd).Öffnen von %s mit "%s" fehlgeschlagenÖffne Album %sÖffnen des Audiogerätes fehlgeschlegen. Korrigiere Einstellungen und Klicke "Neu starten"Öffnen des Quellplugins fehlgeschlagenÖffnen des Monitorplugins fehlgeschlagenOption -add erfordert ein Argument Option -addplay erfordert ein Argument Option -chapter erfordert ein Argument Option -host erfordert ein ArgumentOption -open erfordert ein Argument Option -openplay erfordert ein Argument Option -port erfordert ein ArgumentOption -seek_rel erfordert ein Argument Option -volume erfordert ein Argument Option -volume_rel erfordert ein Argument OptionenOptionen...Ordnung für sinc SkalierungDraußenAusgabeAusgabeverzeichnisAusgabeverzeichnisAusgabedateienAusgabeformatBilderzähler der AusgabeAusgegebene Bildwiederholfrequenz. Für benutzerdefinierte Bildwiederholfrequenz, gib unten die Zeitskala und Bilddauer an (Bildwiederholfrequenz = Zeitskala / Bilddauer)Ausgabe NamensbasisAusgabeoptionenAusgabeplugin konnte nicht geladen werdenAusgabeplugin...Gesamtverstärkung für dieses Filter. Dies ist nur gültig, wenn der Effekt addiert wird.Overlay Unrertitel VoreinstellungenExporteur für OverlayuntertitelPAL CVD (352 x 576)PAL DV 16:9 (720 x 576)PAL DV 4:3 (720 x 576)PAL DVD D1 16:9 (720 x 576)PAL DVD D1 4:3 (720 x 576)PAL SVCD 16:9 (480 x 576)PAL SVCD 4:3 (480 x 576)PAL VCD (352 x 288)PAM format nicht unterstütztPBMasciiPBMbinPGMasciiPGMascii_16PGMbinPGMbin_16PNG ImporteurPNG ExporteurPNM ImporteurPPMasciiPPMascii_16PPMbin_16PWC allgemeinPWC LEDPWC WeißabgleichPackbitsParser für gmerlin EDLsPasswortPassword für den ProxyEinfügenFüge Tracks von der Zwischenablage einPfadPauseUnterbreche WeidergabePerspectivePhillips Webcam gefundenQuetschenQuetschen/wirbelnPixelformatPixelformat: %sAbspielenSpiele aktuellen TrackWiedergabeSpieler aufgeräumtSpieler wechselt jetztSpieler spielt jetztSpieler sucht jetztSpiele Audiostream %d Quellenformat: %s Ausgabeformat: %sSpiele Videostream %d Quellenformat: %s Ausgabeformat: %sPluginPlugin %s unterstützt keine eingebetteten FensterPlugin %s hat keine oder eine falsche VersionPlugin %s hat Null als PrioritätPlugin für Musik-CDs. Unterstützt Abspielen mit Direktverbindung vom Laufwerk zur Soundkarte und Auslesen mit cdparanoia. Metadaten werden von Musicbrainz, freedb oder CD-Text geholt. Metadaten werden in $HOME/gmerlin/cdaudio_metadata zwischengespeichert.Plugin zum Exportieren von Text Untertiteln. Unterstützte Formate sind MPSub und SRTPlugininformationPluginoptionenPlugin...Plugin: PortPort zum VerbindenPositionNur WeiterverarbeitenWeiterverarbeitung...WeiterverarbeitungWeiterverarbeitung von %s"Pre gap" für jedes Stück in CD Rahmen (1/75 Sekunden). Voreinstellung ist 150 (2 Sekunden).EDl bevorzugenPräferenzen...Vorheriges KapitelVorheriger TrackGib diese Hilfe aus und beendeGib diese Hilfe als Manualpage aus und beendeGib diese Hilfe im texinfo-Format aus und beendeGib Version aus und beendePrioritätProtokolle stimmen nicht übereinProtokolleProxyProxy PasswortProxy portProxy server (leerlassen für Direktverbindung)Proxy BenutzernamePulseAudioPulseAudio Aufnahme. Du kannst die Quelle bestimmen, wo wir das Signal herbekommen.PulseAudio AusgabeReinige Verzeichnis (d.h. lösche unbenutzte Albumdateien) beim BeendenReinige Verzeichnis beim BeendenBereinige %sQCIF (176 × 144)QCIF (176x144)QSIF (160x112)QVGA (320 x 240)QVGA (320x240)QuadratischQualitätFrageQuicktimeQuicktime EnkoderBeendenGmerlin beendenBeende ProgrammRGBRGB FarbmatrixRadiusTGA lesen fehlgeschlagenImporteur für BMP BilderImporteur für JPEG-BilderImporteur für PBM/PGM/PPM BilderImporteur für PNG BilderImporteur für TGA bilderImporteur für TIFF BilderLesen der Begrüßungszeile fehlgeschlagenLesen der Bergrüßungszeile fehlgeschlagenHinten CGerät für hintenHinten LHinten RHinterkanäleAufnahmneAufnehmenAufnahmeAufnahme- und AnzeigepluginsRechteckRekursivRotRot -> TransparenzRot -> BlauRot -> GrünRot -> RotRotverstärkungRot OffsetNeu LadenTasten neu geladenMische zu Stereo für Filter %sFernbedienungFernbedienungFernbedienung für den Gmerlin GUI Player Fernbedienung für den GTK Multimediatranscoder Socket für Fernbedienung lauscht an Port %dWechseldatenträgerLöschenAlle löschenRedundante rausschmeißenLösche %sAlbum umbenennenEintrag umbenennenBenenne ausgewählten Track umUmbenennen...RenderoptionenRendert mit OpenGLRendert mit GmerlinNeu öffnenWiederholmodusErsetze/lösche/interpoliere TimecodesBerichte ErgebnisFarbebenen resamplen.ResamplemodusResamplemethode. Automatisch verwendet die Qualitätsstufe. Nachfolgende Optionen sind nach aufsteigender Qualität (absteigender Geschwindigkeit) geordnet.AuflösungVisualisierung neu startenStarte Abspielen neu wegen geänderter AudiofilterStarte Abspielen neu wegen geänderter AudioeinstellungenStarte Abspielen neu wegen geänderter VideofilterStarte Abspielen neu wegen geänderter VideoeinstellungenRechtsRechter RandDrehenLasse cdrdao laufenSIF(352x240)SNDCTL_DSP_GETODELAY ioctl fehlgeschlagenSQCIF (128 × 96)SVCDZahlenformatAbtastrateAbtastfrequenz %d wird vom Gerät %s nicht unterstützt, nehme %dAbtastrate %f kHz wird nicht unterstützt vom Gerät %sAbtastrate [Hz]SättigungSpeichern unter...Speichere ProfilSpeichere Profile...Speichere AufgabenlisteSpeichere Aufgabenliste...Speichere Benutzer/Passwort (kann gefährlich sein!)Speichern von %s fehlgeschlagenSkalierenSkaliermethodeSkalierordnungSkalierungsqualitätSkalieren (Hardware)Skalieren (Software)Suche nach GerätenScancodeZeilen verdoppelnDurchsuche %sPlane %s für Weiterverarbeitung einOsziOszi PluginSekunden können gebrochen sein (d.h. mit Dezimalpunkt) Rückwärts suchenVorwärts suchenSuche relativ. ist in SekundenZum Anfang suchenAudiosuche reichte außerhalb des BereichsHinter den Puffer gesucht.Textuntertitel-Suche reichte außerhalb des BereichsVideosuche reichte außerhalb des BereichsWähle ein VerzeichnisWähle eine DateiWähle Aktion für diesen UntertitelstreamWähle Fehlertracks ausAusgewählte...Auswahl des Tracks %d für %s fehlgeschlagenSchicke fertige Dateien zum PlayerBefehl schicken fehlgeschlagenSenden des Initialisierungsstrings fehlgeschlagenServerSerververbindung beendetServer zum Verbinden. Lass dies leer um die Voreinstellungen zu verwenden.ÜbernehmenSetzte EndzeitSetzte globale Optionen und Voreinstellungen für neu hinzugefügte TracksSetze Wiedergabelautstärke. ist in dB, 0.0 ist maximalSetze die StartzeitSetze die Pufferzeit (in Millisekunden). Größere Werte verbessern vie wiedergabe auf schwachen Systemen unter Last. Kleinere Werte verringern die Verzögerung des Lautstärkereglers.Setzt die Pufferzeit (in Millisekunden). Größere Werte verbessern die Aufnahmefähigkeiten aus langsamen Systemen unter LastSetze die Qualität für Formatumrechnungen. Niedrige Qualität heißt höhere Geschwindigkeit. Werte über 3 schalten langsame, hochqualitative Berechnungen ein."Drop frame" Flag für neu hinzugefügte TimecodesGanzzahlige Bildwiederholrate für neu hinzugefügte TimecodesWähle die ausgegebene Bildgröße. Für "Benutzerdefiniert" mußt Du die Breite, Höhe, Pixelbreite und Pixelhöhe unten angeben.Setze die Startframes der hinzugefügten TimecodesSetze die Startstunden der hinzugefügten TimecodesSetze die Startminuten der hinzugefügten TimecodesSetze die Startsekunden der hinzugefügten TimecodesSetzt die Schreibgeschwikdigkeit. 0 heißt automatisch.Initialisierung des Sockets fehlgeschlagen. Diese Instanz wird nicht mit der Fernbedienung erreichbar sein.EinstellungenGeformtSchärfe (-1 = Automatisch)Zeige TooltipsZeige DebugmeldungenZeige FehlerZeige InformationsmeldungenZeige MeldungenZeige WerkzeugleisteZeige TooltipsZeige TrackinformationenZeige WarnungenZufallswiedergabeVerschlußgeschwindigkeit (-1 = Automatisch)Seite LSeite R16 bit mit Vorzeichen32 bit mit Vorzeichen8 bit mit VorzeichenEinfacher zeitlicher TiefpassEinfache LautstärkeeinstellungEinfacger Wrapper der das mikmod Programm aufruft.Einfacher Exporteur für Wav-Dateien. Unterstützt 8, 16, 24 and 32 bit PCM.Verdopple alle Bildzeilen. Dies ist sehr schnell aber liefert schlechte Qualität.SimulierenSimuliere alte Farb- und SchwarzweißfilmeSinc (beste Qualität)Sinc (schnellste Berechnung)Sinc (mittel)sin(x)/x mit Lanczos FensterGrößeSkinbrowserSkins...Überspringe fast gleiche BilderÜberspringe fehlerhafte TracksÜberspringe die 10 Sekunden Pause bevor das Schreiben oder Simulieren beginnt.Überspringe Transkodieren dieses Tracks und schicke die Datei direkt zum Weiterverarbeiten%d Bilder übersprungenÜberspringe cdrdao Lauf (keine Stücke)Überspringe Weiterverabreitung (keine geeigneten Dateien defunden)SoftwareskaliererSortierenSortiere und konfiguriere Audio CodecsSortiere und konfiguriere Video CodecsQuelleZu Öffnende Quelle. Benutze den PulseAudio Manager um vorhandene Quellen anzeigen zu lassen.Gib an, um wieviel ein Block sich vom letzten nicht-weggelassenen Block unterscheiden darf. 0 heißt identische Blöcke, 1 heißt völlig verschiedene Blöcke. Beachte, daß die Bedeutung von "völlig verschieden" vom Farbraum abhängt.Gib an, um wieviel ein Bild sich vom letzten nicht-weggelassenen Bild unterscheiden darf. 0 heißt identische Bilder, 1 heißt völlig verschiedene Bilder. Beachte, daß die Bedeutung von \"völlig verschieden\" vom Farbraum abhängt.Spezifiziert, wie stark beim Herunterskalieren weichgezeichnet werden soll. Kleinere Werte können die Skalierung beschleunigen, können aber zu starkem Aliasing führen.Wählt das Antialiasingfilter, welches beim Herunterskalieren verwendet wird.Wählt, welches Feld der Deinterlacer weglassen soll.Gib unten eine Startzeit an. Diese Zeit wird geringfügig falsch sein, wenn die Quelle kein exaktes Suchen unterstützt.Gib unten eine Endzeit anGib die Schriftgröße für OSD an. Der Wert gilt für eine Bildbreite von 640. Für andere Breiten wird er skaliert.Gib an, wieviele verschiedene Zeichen zur schelleren Darstellung zwischengespeichert werden. Für europäische Sprachen muß dieser Wert nie größer als 255 sein.GeschwindigkeitStartzeitBeginne TranskodierungThread gestartedStarten des Quellplugins fehlgeschlagenStatus %02x -> %02x StereoStereo 16bitStereo 8bitStereo nach Mono ModeStandbild Wiederholrate für StandbilderBeende WiedergabeStoppe TranskodierungStream %dStream %d [%s]StärkeString ist ein exakter TeilstringStilUnterverzeichnisUnterverzeichnis, in das die Tracks geschrieben werdenUnteroptionen für %sUnteroptionen %s=%sSubrip (.srt)UntertiteloptionenUntertitelstream %d/%d [%s]Untertitelstream kann nicht verarbeitet werdenUntertitelstream %dUntertitelUntertitel #%dUntertitel #%d: %sUntertitel...Untertitel: %sUnterstützte Optionen: Unterstützte Optionen: Unterstützte Kennzeichner:Schalte den Dämon ein und aus. Wenn Du den Dämon bei jedem Start von X starten willst, füge "gmerlin_kbd" zu den Startprogrammen hinzuNächster TrackVorheriger TrackTGA ImporteurTGA ExporteurTIFF ImporteurTIFF ExporteurInhaltsverzeichnis-DateiTabbed ModusSchnappschußHole die Farben des Displays aus der Beschreibung des SkinsAufgabenlisteSchablone für die Ausgabedateien. Eine Maske "%n" fügt die Bildnummer mit Stellen ein (z.B. webcam-shot-%6n)Maske zum Ergeugen der Tracknamen von Metadaten %p: Künstler %a: Album %g: Genre %t: Trackname %n: Tracknummer (d = Anzahl der Stellen, 1-9) %y: Jahr %c: KommentarZeitlicher TiefpassText box (unten)Text box (links)Text box (rechts)Text Box (open)TextfarbeText Untertitel VoreinstellungenExporteur für TextuntertitelText-Untertitelstream %d: Mische auf Videostream %dText-Untertitelstream %d: Exportiere in DateiText UntertitelTextrendererErzwinge ein Zahlenformat als Eingabe für das nächste Filter. Überwiegend zum Testen benutzt.Die ist ein Frontend zum Zrzeugen von (S)VCD Abbildern für die vcdimager tools " "(http://www.vcdimager.org). Brennen mit cdrdao (http://cdrdao.sourceforge." "net) ist auch möglich.Dies ist ein Frontend zum Erzeugen von Audio-CD Abbildern (optional mit CD-Text) für cdrdao (http://cdrdao.sourceforge.net). Optionales Brennen wird ebenfalls unterstützt.Dies ist freie Software, die unter den Bedingungen der GNU General Public License weitergegeben werden kann. Es gibt KEINE HAFTUNG.Dies ist freie Software, die unter den Bedingungen der GNU General Public License weitergegeben werden kann. Es gibt KEINE HAFTUNG. Diese Option wird verwendet, wenn die Quelle einen Alpha-(=Transparenz)-Kanal hat und die Ausgabe keine Transparenz unterstützt. Entweder wird die Transparenz ignoriert, oder eine Hintergrundfarbe, die Du unten angibst, wird eingeblendet.Dieses Plugin liest eine XML Datei und exportiert eine EDL, die vom eingebauten EDL Dekoder gespielt werden kann.Dieses Plugin exportiert Video als Bilderserie. Es benutzt die installierten BildexportpluginsDieses Plugin liest Standbilder. Es benutzt die installierten Bildimporteure.Dieses Plugin liest eine Reihe Bilder als Video. Es benutzt die installierten Bildimporteure.Dies wird 2-pass Enkodieren aktivieren. Im ersten Durchgang wird die Spitzenlautstärke ermittelt. Im zweiten Durchgang wird der Stream mit normierter Lautstärke transkodiert.ZeitZeit, die vergeht, bis der nächste Track gewählt wird. 0 heißt unendlich.MaximalzeitMaximale Verbindungszeit (in Sekunden) für CDDB ServerZeitskalaZeitskala für benutzerdefinierte Bildwiederholfrequenz (Bildwiederholfrequenz = Zeitskala / Bilddauer)TitelStummschaltenKlangObenOberer RandOberes Feld zuerstOben linksObere linke Ecke in normierten BildkoordinatenOben rechtsObere rechte Ecke in normierten BildkoordinatenGesamtspielzeitGesamtschwelleTrackTrack VoreinstellungenTrack hat weder Audio noch Video, überspringe ihn.TracknameTrackoptionenTrack: %dTrackname MaskeTranskodierenTranskodiere als OverlayTranskodiere als TextTranskoderTranskoderkonfigurationTranskodiere %s [Track %d, Durchgang %d/%d]Transkodiere %s [Track %d]TransformationTransformiere das Bild mit verschiedenen MethodenTransformationsmodusHöhenBaum...DreieckVersuche, CD Metadaten von CD-Text zu erhaltenTunerÄndere TimecodesTyp %s wird nicht behandelt für %sURLURL:URLs...UndefiniertUnerwartetes Dateiende, lösche BildUnbekanntUnbekannter KanalUnbekanner FehlerUnbekanntes Zahlenformat: %dUnbekannter Skaliermodus: %s Namenlose DiskUnbekanntens DateiformatVorzeichenlos 16 bitVorzeichenlos 8 bitNicht unterstützte Bits pro Abtastwert (%d) für UINTNicht unterstützte Kompression für LOGL/LOGLUVNicht unterstützte Tiefe %d für IEEE Fließkomma.Nicht unterstütztes ZahlenformatNicht unterstützte Abtastwerte pro PixelUrls...Benutze CD-TextBenutze CddbBenutze Gerät für Mitte/LFEBenutze MusicbrainzBenutze Gerät für hintenBenutze Hardwareskalierung auch wenn es mehr rechenaufwendige Pixelformat-Umwandlungen erfordertInterpolierendes MischenBenutze lokal gespeicherte MetadatenBenutze Metadaten für TracknamenBenutze Surround-MixingBenutze das Surround 4.0 (oder Quadrophonische) GerätBenutze das Surround 4.1 GerätBenutze das Surround 5.0 GerätBenutze das Surround 5.1 GerätWird für Konfigurationsdaten benutzt. Lösche diese Datein, wenn Du meinst was zerschossen zu haben.BenutzerdefiniertBenutzerdefinierte HöheBenutzerdefinierte Höhe in Pixels. Nur von Bedeutung, wenn "Benutzerdefiniert" für die Bildgröße gewählt wurde.Benutzerdefinierte PixelhöheBenutzerdefinierte Pixelhöhe. Nur von Bedeutung, wenn "Benutzerdefiniert" für die Bildgröße gewählt wurde.Benutzerdefinierte PixelbreiteBenutzerdefinierte Pixelbreite. Nur von Bedeutung, wenn "Benutzerdefiniert" für die Bildgröße gewählt wurde.Benutzerdefinierte BreiteBenutzerdefinierte Breite in Pixels. Nur von Bedeutung, wenn "Benutzerdefiniert" für die Bildgröße gewählt wurde.Benutzerdefiniertes GerätBenutzername für den Proxy. Leerlassen, wenn der Proxy keine Authentifizierung erfordert.BenutzerhandbuchBenutzernameBenutze Statistikdatei: %sV4LV4L GerätVCD 1.1VCD 2.0VCD Abbilder erzeugen/brennenVCD OptionenVGA (640 x 480)VGA (640x480)VIDIOCGMBUF fehlgeschlagen: %sVIDIOCGPICT fehlgeschlagen: %sVIDIOCGWIN fehlgeschlagen: %sVIDIOCSPICT fehlgeschlagen: %sVIDIOCSWIN fehlgeschlagen: %s (Ungültige Bildgröße?)Vertikale AusrichtungVertikaler RadiusVideoVideo #%dVideo #%d: %sVideo CodecsVideofilterVideo VoreinstellungenVideoenkoderVideofilterVideo FilterBilderzähler: %sVideo OptionenVideoausgabeVideoaufnahmeVideostreamVideostream %d, Quellformat: %sVideostream %d, Ausgabeformat: %sVideostream %d/%dVideostream %d: %s Bilder transkodiertVideostream zum draufmischenVideo streams %dVideo...Video: %sBesuche HomepageVisualisierungVisualisierungsprozess abgestürzt, starte neu um es noch einmal zu versuchenVisualisierung...VisualisierungenVisualisierungstest VisualisiererVisualisierer-KonfigurationLautstärkeLautstärkeeinstellungWarnung VordergrundWave ExporteurWenn Standbilder gezeigt werden, wiederholt Gmerlin sie periodisch. Dies ermöglicht Herumspielen an den Filtereinstellungen in Echtzeit. Immer wenn wir CD Metadaten aus dem Internet bekommen, speichern wir diese in $HOME/.gmerlin/cdaudio_metadata. Wenn Du falsche Metadaten für eine CD bekommen hast, kannst Du diese Option abschalten und die Metadaten werden erneut geholt und die gespeicherten überschrieben.WeißabgleichWeißheitVerbreiterungBreiteFensterFenstermodusFensterFenster...Schreibe CD-TextSchreibe Info ChunkExporteur für BMP BilderExporteur für JPEG BilderExporteur für PNG BilderExporteur für TGA BilderExporteur für TIFF BilderSchreibe Abbild%s geschriebenXX -> XX -> YX OffsetX11X11 Ausgabetreiber mit Unterstützung für XVideo, XImage und OpenGL. Shared Memory (XShm) wird, wenn möglich, verwendet.Xml DateiYY -> XY -> YY OffsetY'CbCr(A) FarbmatrixYCrCbYUV 410 PlanarYUV 411 PlanarYUV 420 PlanarYUV 422 (UYVY)YUV 422 (YUY2)YUV 422 PlanarYUV 422 Planar (16 bit)YUV 444 PlanarYUV 444 Planar (16 bit)YUVA 4444YUVJ 420 PlanarYUVJ 422 PlanarYUVJ 444 PlanarNull0. Ordnung haltenNull Spitzenwerte detektiert (stumme Datei?). Deaktiviere NormierungZoomVergrößerungsfaktorZoome horizontalZoome horizontal und/oder vertikalZoome vertikal[-co options] quellbild ausgabebild [1|0] (Voreinstellung: %d)[] [Optionen][Optionen] [Optionen] [gmls...] [Optionen] Befehl [Optionen] gml... bg_plugin_ref %s: %dbg_plugin_unref %s: %dbg_plugin_unref_nolock %s: %dcdio_close_tray fehlgeschlagencdio_close_tray fehlgeschlagen: %scdrdao Programm nicht gefundencontrol digital audio info fehlgeschlagen (%i): %scontrol hardware info fehlgeschlagen (%i): %scontrol open fehlgeschlagen (%i): %sVoreinstellung: %%.%df)Voreinstellung: %d)Voreinstellung: %s)dlopen fehlgeschlagen für %s: %sdo_capture: Kein Plugin geladenh:ladspa plugin Author: %s Copyright: %sLibquicktime Quellenpluginlibvisual Pluginm:Mikmod Quellpluginmmap fehlgeschlagen: %sms:option[{unteroptionen}]read_frame fehlgeschlagens:snd_ctl_card_info fehlgeschlagensnd_ctl_card_info_malloc fehlgeschlagensnd_ctl_pcm_next_device fehlgeschlagensnd_hctl_elem_read fehlgeschlagensnd_hctl_elem_write fehlgeschlagensnd_hctl_load failed fehlgeschlagensnd_hctl_open fehlgeschlagensnd_pcm_hw_params fehlgeschlagensnd_pcm_hw_params_any fehlgeschlagensnd_pcm_hw_params_malloc fehlgeschlagensnd_pcm_hw_params_set_access fehlgeschlagensnd_pcm_hw_params_set_buffer_size fehlgeschlagensnd_pcm_hw_params_set_channels fehlgeschlagen (Format hat %d Kanäle)snd_pcm_hw_params_set_format fehlgeschlagensnd_pcm_hw_params_set_period_size fehlgeschlagensnd_pcm_hw_params_set_rate_near fehlgeschlagensnd_pcm_open fehlgeschlagen für Gerät %s (%s)snd_pcm_prepare fehlgeschlagensnd_pcm_write gab %s zurückSpumux Overlay Exporteurvcdxgen fehlgeschlagen: %svideo4linux Aufnahmeplugin. Unterstützt nur Video und keine Tunergeräte.{[[HH:]MM:]SS} ({option[{unteroptionen}][:option[{unteroptionen}]...]}gmerlin-1.2.0~dfsg/po/remove-potcdate.sin0000644000175000017500000000066011764363410020327 0ustar alessioalessio# Sed script that remove the POT-Creation-Date line in the header entry # from a POT file. # # The distinction between the first and the following occurrences of the # pattern is achieved by looking at the hold space. /^"POT-Creation-Date: .*"$/{ x # Test if the hold space is empty. s/P/P/ ta # Yes it was empty. First occurrence. Remove the line. g d bb :a # The hold space was nonempty. Following occurrences. Do nothing. x :b } gmerlin-1.2.0~dfsg/po/stamp-po0000644000175000017500000000001211764363441016174 0ustar alessioalessiotimestamp gmerlin-1.2.0~dfsg/po/en@quot.header0000644000175000017500000000226311764363410017304 0ustar alessioalessio# All this catalog "translates" are quotation characters. # The msgids must be ASCII and therefore cannot contain real quotation # characters, only substitutes like grave accent (0x60), apostrophe (0x27) # and double quote (0x22). These substitutes look strange; see # http://www.cl.cam.ac.uk/~mgk25/ucs/quotes.html # # This catalog translates grave accent (0x60) and apostrophe (0x27) to # left single quotation mark (U+2018) and right single quotation mark (U+2019). # It also translates pairs of apostrophe (0x27) to # left single quotation mark (U+2018) and right single quotation mark (U+2019) # and pairs of quotation mark (0x22) to # left double quotation mark (U+201C) and right double quotation mark (U+201D). # # When output to an UTF-8 terminal, the quotation characters appear perfectly. # When output to an ISO-8859-1 terminal, the single quotation marks are # transliterated to apostrophes (by iconv in glibc 2.2 or newer) or to # grave/acute accent (by libiconv), and the double quotation marks are # transliterated to 0x22. # When output to an ASCII terminal, the single quotation marks are # transliterated to apostrophes, and the double quotation marks are # transliterated to 0x22. # gmerlin-1.2.0~dfsg/po/Makevars0000644000175000017500000000355511764363410016220 0ustar alessioalessio# Makefile variables for PO directory in any package using GNU gettext. # Usually the message domain is the same as the package name. DOMAIN = $(PACKAGE) # These two variables depend on the location of this directory. subdir = po top_builddir = .. # These options get passed to xgettext. XGETTEXT_OPTIONS = --keyword="bg_log:3" --keyword=TR --keyword=TRS --keyword=TRU --from-code="UTF-8" # This is the copyright holder that gets inserted into the header of the # $(DOMAIN).pot file. Set this to the copyright holder of the surrounding # package. (Note that the msgstr strings, extracted from the package's # sources, belong to the copyright holder of the package.) Translators are # expected to transfer the copyright for their translations to this person # or entity, or to disclaim their copyright. The empty string stands for # the public domain; in this case the translators are expected to disclaim # their copyright. COPYRIGHT_HOLDER = Members of the gmerlin project # This is the email address or URL to which the translators shall report # bugs in the untranslated strings: # - Strings which are not entire sentences, see the maintainer guidelines # in the GNU gettext documentation, section 'Preparing Strings'. # - Strings which use unclear terms or require additional context to be # understood. # - Strings which make invalid assumptions about notation of date, time or # money. # - Pluralisation problems. # - Incorrect English spelling. # - Incorrect formatting. # It can be your email address, or a mailing list address where translators # can write to without being subscribed, or the URL of a web page through # which the translators can contact you. MSGID_BUGS_ADDRESS = gmerlin-general@lists.sourceforge.net # This is the list of locale categories, beyond LC_MESSAGES, for which the # message catalogs shall be used. It is usually empty. EXTRA_LOCALE_CATEGORIES = gmerlin-1.2.0~dfsg/po/quot.sed0000644000175000017500000000023111764363410016175 0ustar alessioalessios/"\([^"]*\)"/“\1”/g s/`\([^`']*\)'/‘\1’/g s/ '\([^`']*\)' / ‘\1’ /g s/ '\([^`']*\)'$/ ‘\1’/g s/^'\([^`']*\)' /‘\1’ /g s/“”/""/g gmerlin-1.2.0~dfsg/po/en@boldquot.header0000644000175000017500000000247111764363410020146 0ustar alessioalessio# All this catalog "translates" are quotation characters. # The msgids must be ASCII and therefore cannot contain real quotation # characters, only substitutes like grave accent (0x60), apostrophe (0x27) # and double quote (0x22). These substitutes look strange; see # http://www.cl.cam.ac.uk/~mgk25/ucs/quotes.html # # This catalog translates grave accent (0x60) and apostrophe (0x27) to # left single quotation mark (U+2018) and right single quotation mark (U+2019). # It also translates pairs of apostrophe (0x27) to # left single quotation mark (U+2018) and right single quotation mark (U+2019) # and pairs of quotation mark (0x22) to # left double quotation mark (U+201C) and right double quotation mark (U+201D). # # When output to an UTF-8 terminal, the quotation characters appear perfectly. # When output to an ISO-8859-1 terminal, the single quotation marks are # transliterated to apostrophes (by iconv in glibc 2.2 or newer) or to # grave/acute accent (by libiconv), and the double quotation marks are # transliterated to 0x22. # When output to an ASCII terminal, the single quotation marks are # transliterated to apostrophes, and the double quotation marks are # transliterated to 0x22. # # This catalog furthermore displays the text between the quotation marks in # bold face, assuming the VT100/XTerm escape sequences. # gmerlin-1.2.0~dfsg/po/de.po0000644000175000017500000070103211764363441015453 0ustar alessioalessio# German translations for gmerlin package. # Copyright (C) 2007 Members of the gmerlin project # This file is distributed under the same license as the gmerlin package. # Burkhard Plaum , 2007. # msgid "" msgstr "" "Project-Id-Version: gmerlin 0.3.6\n" "Report-Msgid-Bugs-To: gmerlin-general@lists.sourceforge.net\n" "POT-Creation-Date: 2012-06-08 13:50+0200\n" "PO-Revision-Date: 2009-12-19 00:17+0100\n" "Last-Translator: Burkhard Plaum \n" "Language-Team: German \n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" #: plugins/jack/oa_jack.c:256 plugins/jack/i_jack.c:189 #, fuzzy msgid "Jack" msgstr "Track" #: plugins/jack/oa_jack.c:257 #, fuzzy msgid "Jack output plugin" msgstr "Ausgabeplugin..." #: plugins/jack/i_jack.c:58 #, fuzzy, c-format msgid "Dropping %d samples" msgstr "Überspringe Abtastwerte" #: plugins/jack/i_jack.c:190 #, fuzzy msgid "Jack recorder" msgstr "Alsa Aufnahme" #: plugins/jack/jack_common.c:32 #, fuzzy msgid "Connect ports" msgstr "Zeitüberschreitung beim Verbinden" #: plugins/jack/jack_common.c:35 #, fuzzy msgid "Autoconnect ports" msgstr "Port zum Verbinden" #: plugins/jack/jack_common.c:184 #, fuzzy, c-format msgid "Connecting %s with %s failed" msgstr "Öffnen von %s mit \"%s\" fehlgeschlagen" #: plugins/pulseaudio/oa_pulse.c:86 plugins/pulseaudio/i_pulse.c:155 msgid "PulseAudio" msgstr "PulseAudio" #: plugins/pulseaudio/oa_pulse.c:87 msgid "PulseAudio output" msgstr "PulseAudio Ausgabe" #: plugins/pulseaudio/pulseaudio_common.c:186 #, c-format msgid "Connection to Pulseaudio failed: %s" msgstr "Verbindungsaufbau zu PulseAudio fehlgeschlagen: %s" #: plugins/pulseaudio/i_pulse.c:70 plugins/oss/i_oss.c:57 #: plugins/alsa/i_alsa.c:49 lib/mediafiledevice.c:100 msgid "Channel Mode" msgstr "Kanalmodus" #: plugins/pulseaudio/i_pulse.c:74 plugins/oss/i_oss.c:61 #: plugins/alsa/i_alsa.c:53 lib/mediafiledevice.c:104 msgid "Mono" msgstr "Mono" #: plugins/pulseaudio/i_pulse.c:74 plugins/oss/i_oss.c:61 #: plugins/alsa/i_alsa.c:53 lib/mediafiledevice.c:104 msgid "Stereo" msgstr "Stereo" #: plugins/pulseaudio/i_pulse.c:78 plugins/oss/i_oss.c:65 #: plugins/alsa/i_alsa.c:57 msgid "Bits" msgstr "Bits" #: plugins/pulseaudio/i_pulse.c:85 plugins/oss/i_oss.c:72 #: plugins/alsa/i_alsa.c:64 lib/mediafiledevice.c:108 msgid "Samplerate [Hz]" msgstr "Abtastrate [Hz]" #: plugins/pulseaudio/i_pulse.c:93 plugins/cdaudio/i_cdaudio.c:588 #: plugins/cdaudio/i_cdaudio.c:630 msgid "Server" msgstr "Server" #: plugins/pulseaudio/i_pulse.c:95 msgid "Server to connect to. Leave empty for default." msgstr "" "Server zum Verbinden. Lass dies leer um die Voreinstellungen zu verwenden." #: plugins/pulseaudio/i_pulse.c:99 msgid "Source" msgstr "Quelle" #: plugins/pulseaudio/i_pulse.c:101 msgid "Source to open. Use the PulseAudio manager for available Sources." msgstr "" "Zu Öffnende Quelle. Benutze den PulseAudio Manager um vorhandene Quellen " "anzeigen zu lassen." #: plugins/pulseaudio/i_pulse.c:156 msgid "" "PulseAudio capture. You can specify the source, where we'll get the audio." msgstr "" "PulseAudio Aufnahme. Du kannst die Quelle bestimmen, wo wir das Signal " "herbekommen." #: plugins/subwriters/e_subtext.c:75 #, fuzzy msgid "Ignoring empty subtitle" msgstr "Ignoriere Zeilenumbrüche" #: plugins/subwriters/e_subtext.c:265 plugins/image/iw_pnm.c:194 #: plugins/postprocessors/e_pp_vcdimager.c:110 plugins/lqt/e_lqt.c:703 msgid "Format" msgstr "Format" #: plugins/subwriters/e_subtext.c:269 msgid "Subrip (.srt)" msgstr "Subrip (.srt)" #: plugins/subwriters/e_subtext.c:269 msgid "MPlayer mpsub" msgstr "MPlayer mpsub" #: plugins/subwriters/e_subtext.c:308 lib/gtk/plugininfo.c:161 msgid "Text subtitle exporter" msgstr "Exporteur für Textuntertitel" #: plugins/subwriters/e_subtext.c:309 msgid "" "Plugin for exporting text subtitles. Supported formats are MPSub and SRT" msgstr "" "Plugin zum Exportieren von Text Untertiteln. Unterstützte Formate sind MPSub " "und SRT" #: plugins/esd/i_esd.c:58 plugins/esd/oa_esd.c:47 msgid "Host (empty: local)" msgstr "Rechner (leer: lokal)" #: plugins/esd/i_esd.c:63 msgid "Input Mode" msgstr "Einlesemodus" #: plugins/esd/i_esd.c:67 apps/recorder/recorder_window.c:622 msgid "Record" msgstr "Aufnehmen" #: plugins/esd/i_esd.c:67 apps/camelot/webcam_window.c:584 #: apps/recorder/recorder_window.c:759 msgid "Monitor" msgstr "Monitor" #: plugins/esd/i_esd.c:172 msgid "Cannot connect to daemon" msgstr "Kann nicht zum Dämon verbinden" #: plugins/esd/i_esd.c:235 plugins/esd/i_esd.c:236 msgid "EsounD input driver" msgstr "Esound Aufnahmeplugin" #: plugins/esd/oa_esd.c:172 plugins/esd/oa_esd.c:173 msgid "EsounD output driver" msgstr "EsounD Ausgabeplugin" #: plugins/v4l/pwc.c:70 msgid "PWC General" msgstr "PWC allgemein" #: plugins/v4l/pwc.c:75 include/gmerlin/bggavl.h:186 #: include/gmerlin/bggavl.h:204 lib/visualize.c:356 msgid "Framerate" msgstr "Bildwiederholrate" #: plugins/v4l/pwc.c:83 plugins/tiff/iw_tiff.c:188 msgid "Compression" msgstr "Kompression" #: plugins/v4l/pwc.c:87 plugins/videofilters/fv_deinterlace.c:146 #: plugins/tiff/iw_tiff.c:191 include/gmerlin/bggavl.h:229 #: include/gmerlin/bggavl.h:324 include/gmerlin/bggavl.h:633 #: include/gmerlin/bggavl.h:657 msgid "None" msgstr "Kein(s)" #: plugins/v4l/pwc.c:88 msgid "Low" msgstr "Niedrig" #: plugins/v4l/pwc.c:89 msgid "Medium" msgstr "Mittel" #: plugins/v4l/pwc.c:90 msgid "High" msgstr "Hoch" #: plugins/v4l/pwc.c:100 msgid "Gain control (-1 = Auto)" msgstr "Verstärkung (-1 = Automatisch)" #: plugins/v4l/pwc.c:109 msgid "Shutter speed (-1 = Auto)" msgstr "Verschlußgeschwindigkeit (-1 = Automatisch)" #: plugins/v4l/pwc.c:118 msgid "Sharpness (-1 = Auto)" msgstr "Schärfe (-1 = Automatisch)" #: plugins/v4l/pwc.c:127 msgid "Backlight compensation" msgstr "Hintergrundlichtausgleich" #: plugins/v4l/pwc.c:134 msgid "Flicker compensation" msgstr "Flackerausgleich" #: plugins/v4l/pwc.c:141 msgid "PWC Whitebalance" msgstr "PWC Weißabgleich" #: plugins/v4l/pwc.c:146 msgid "White balance" msgstr "Weißabgleich" #: plugins/v4l/pwc.c:156 msgid "Indoor" msgstr "Drinnen" #: plugins/v4l/pwc.c:157 msgid "Outdoor" msgstr "Draußen" #: plugins/v4l/pwc.c:158 msgid "Fluorescent lighting" msgstr "Leuchtstofflampe" #: plugins/v4l/pwc.c:159 msgid "Manual" msgstr "Manuell" #: plugins/v4l/pwc.c:160 plugins/videofilters/fv_cropscale.c:431 #: plugins/cdaudio/cdparanoia.c:195 include/gmerlin/bggavl.h:289 #: include/gmerlin/bggavl.h:308 include/gmerlin/bggavl.h:323 #: include/gmerlin/bggavl.h:657 include/gmerlin/bggavl.h:670 #: lib/x11/x11_window.c:1195 msgid "Auto" msgstr "Automatisch" #: plugins/v4l/pwc.c:165 msgid "Manual red gain" msgstr "Manuelle Rotverstärkung" #: plugins/v4l/pwc.c:174 msgid "Manual blue gain" msgstr "Manuelle Blauverstärkung" #: plugins/v4l/pwc.c:183 msgid "Auto speed" msgstr "Automatische Geschwindigkeit" #: plugins/v4l/pwc.c:192 msgid "Auto delay" msgstr "Automatische Verzögerung" #: plugins/v4l/pwc.c:201 msgid "PWC LED" msgstr "PWC LED" #: plugins/v4l/pwc.c:206 msgid "LED on time (secs)" msgstr "LED Einzeit (secs)" #: plugins/v4l/pwc.c:215 msgid "LED off time (secs)" msgstr "LED Auszeit (secs)" #: plugins/v4l/i_v4l.c:206 #, c-format msgid "Cannot open device %s: %s" msgstr "Kann Gerät %s nicht öffnen: %s" #: plugins/v4l/i_v4l.c:215 msgid "Phillips webcam detected" msgstr "Phillips Webcam gefunden" #: plugins/v4l/i_v4l.c:221 apps/camelot/vloopback.c:541 #, c-format msgid "VIDIOCGPICT failed: %s" msgstr "VIDIOCGPICT fehlgeschlagen: %s" #: plugins/v4l/i_v4l.c:245 apps/camelot/vloopback.c:551 #, c-format msgid "VIDIOCSPICT failed: %s" msgstr "VIDIOCSPICT fehlgeschlagen: %s" #: plugins/v4l/i_v4l.c:255 #, c-format msgid "VIDIOCGWIN failed: %s" msgstr "VIDIOCGWIN fehlgeschlagen: %s" #: plugins/v4l/i_v4l.c:268 #, c-format msgid "VIDIOCSWIN failed: %s (invalaid picture dimensions?)" msgstr "VIDIOCSWIN fehlgeschlagen: %s (Ungültige Bildgröße?)" #: plugins/v4l/i_v4l.c:298 #, c-format msgid "VIDIOCGMBUF failed: %s" msgstr "VIDIOCGMBUF fehlgeschlagen: %s" #: plugins/v4l/i_v4l.c:306 plugins/v4l2/ov_v4l2.c:298 #, c-format msgid "mmap failed: %s" msgstr "mmap fehlgeschlagen: %s" #: plugins/v4l/i_v4l.c:406 plugins/oss/i_oss.c:51 plugins/oss/oa_oss.c:67 #: plugins/postprocessors/cdrdao_common.h:37 plugins/v4l2/i_v4l2.c:711 #: plugins/v4l2/ov_v4l2.c:100 apps/camelot/vloopback.c:730 #: lib/gtk/treewidget.c:1119 msgid "Device" msgstr "Gerät" #: plugins/v4l/i_v4l.c:411 msgid "V4L Device" msgstr "V4L Gerät" #: plugins/v4l/i_v4l.c:417 plugins/v4l/i_v4l.c:422 plugins/v4l2/i_v4l2.c:729 #: plugins/v4l2/i_v4l2.c:734 apps/camelot/vloopback.c:746 msgid "Resolution" msgstr "Auflösung" #: plugins/v4l/i_v4l.c:433 plugins/v4l2/i_v4l2.c:745 #: apps/camelot/vloopback.c:757 msgid "QSIF (160x112)" msgstr "QSIF (160x112)" #: plugins/v4l/i_v4l.c:434 plugins/v4l2/i_v4l2.c:746 #: apps/camelot/vloopback.c:758 msgid "QCIF (176x144)" msgstr "QCIF (176x144)" #: plugins/v4l/i_v4l.c:435 plugins/v4l2/i_v4l2.c:747 #: apps/camelot/vloopback.c:759 msgid "QVGA (320x240)" msgstr "QVGA (320x240)" #: plugins/v4l/i_v4l.c:436 plugins/v4l2/i_v4l2.c:748 #: apps/camelot/vloopback.c:760 msgid "SIF(352x240)" msgstr "SIF(352x240)" #: plugins/v4l/i_v4l.c:437 plugins/v4l2/i_v4l2.c:749 #: apps/camelot/vloopback.c:761 msgid "CIF (352x288)" msgstr "CIF (352x288)" #: plugins/v4l/i_v4l.c:438 plugins/v4l2/i_v4l2.c:750 #: apps/camelot/vloopback.c:762 msgid "VGA (640x480)" msgstr "VGA (640x480)" #: plugins/v4l/i_v4l.c:439 plugins/videofilters/fv_cropscale.c:227 #: plugins/v4l2/i_v4l2.c:751 include/gmerlin/bggavl.h:171 #: include/gmerlin/bggavl.h:464 apps/camelot/vloopback.c:763 msgid "User defined" msgstr "Benutzerdefiniert" #: plugins/v4l/i_v4l.c:444 plugins/videofilters/fv_cropscale.c:259 #: plugins/v4l2/i_v4l2.c:756 include/gmerlin/bggavl.h:390 #: apps/camelot/vloopback.c:769 msgid "User defined width" msgstr "Benutzerdefinierte Breite" #: plugins/v4l/i_v4l.c:452 plugins/videofilters/fv_cropscale.c:270 #: plugins/v4l2/i_v4l2.c:764 include/gmerlin/bggavl.h:401 #: apps/camelot/vloopback.c:778 msgid "User defined height" msgstr "Benutzerdefinierte Höhe" #: plugins/v4l/i_v4l.c:460 msgid "Settings" msgstr "Einstellungen" #: plugins/v4l/i_v4l.c:465 plugins/videofilters/fv_equalizer.c:426 msgid "Brightness" msgstr "Helligkeit" #: plugins/v4l/i_v4l.c:474 plugins/videofilters/fv_equalizer.c:456 msgid "Hue" msgstr "Ton" #: plugins/v4l/i_v4l.c:483 msgid "Colour" msgstr "Farbe" #: plugins/v4l/i_v4l.c:492 plugins/videofilters/fv_equalizer.c:436 msgid "Contrast" msgstr "Kontrast" #: plugins/v4l/i_v4l.c:501 msgid "Whiteness" msgstr "Weißheit" #: plugins/v4l/i_v4l.c:697 msgid "V4L" msgstr "V4L" #: plugins/v4l/i_v4l.c:698 msgid "video4linux recording plugin. Supports only video and no tuner decives." msgstr "" "video4linux Aufnahmeplugin. Unterstützt nur Video und keine Tunergeräte." #: plugins/image/ir_tga.c:103 msgid "Read tga failed" msgstr "TGA lesen fehlgeschlagen" #: plugins/image/ir_tga.c:228 msgid "TGA reader" msgstr "TGA Importeur" #: plugins/image/ir_tga.c:229 msgid "Reader for TGA images" msgstr "Importeur für TGA bilder" #: plugins/image/ir_bmp.c:234 plugins/image/ir_pnm.c:108 lib/singlepic.c:1030 #, c-format msgid "Cannot open file %s: %s" msgstr "Kann Datei %s nicht öffnen: %s" #: plugins/image/ir_bmp.c:244 msgid "Cannot read File type" msgstr "Kann Dateityp nicht lesen" #: plugins/image/ir_bmp.c:249 msgid "File is no BMP" msgstr "Datei ist keine BMP Datei" #: plugins/image/ir_bmp.c:290 msgid "Cannot detect image dimensions" msgstr "Kann Bildgröße nicht ermitteln" #: plugins/image/ir_bmp.c:298 #, c-format msgid "Depth %d not supported" msgstr "Tiefe %d nicht unterstützt" #: plugins/image/ir_bmp.c:760 msgid "BMP reader" msgstr "BMP Importeur" #: plugins/image/ir_bmp.c:761 msgid "Reader for BMP images" msgstr "Importeur für BMP Bilder" #: plugins/image/iw_tga.c:140 plugins/image/iw_tga.c:143 #, c-format msgid "Cannot save %s: %s" msgstr "Kann %s nicht speichern: %s" #: plugins/image/iw_tga.c:160 msgid "Do RLE compression" msgstr "Verwende RLE Kompression" #: plugins/image/iw_tga.c:192 msgid "TGA writer" msgstr "TGA Exporteur" #: plugins/image/iw_tga.c:193 msgid "Writer for TGA images" msgstr "Exporteur für TGA Bilder" #: plugins/image/ir_pnm.c:127 msgid "Can't read File type" msgstr "Kann Dateityp nicht lesen" #: plugins/image/ir_pnm.c:142 msgid "File is no pnm" msgstr "Datei ist kein PNM" #: plugins/image/ir_pnm.c:168 plugins/image/ir_pnm.c:241 #, c-format msgid "File is no pnm (%.1s%.1s%.1s)" msgstr "Datei ist kein pnm (%.1s%.1s%.1s)" #: plugins/image/ir_pnm.c:185 msgid "Cannot read width" msgstr "Kann Breite nicht lesen" #: plugins/image/ir_pnm.c:198 msgid "Cannot read height" msgstr "Kann Höhe nicht lesen" #: plugins/image/ir_pnm.c:211 msgid "Cannot read maxval" msgstr "Kann Maxval nicht lesen" #: plugins/image/ir_pnm.c:235 msgid "PAM format not suported" msgstr "PAM format nicht unterstützt" #: plugins/image/ir_pnm.c:310 msgid "PBMascii" msgstr "PBMascii" #: plugins/image/ir_pnm.c:344 msgid "PBMbin" msgstr "PBMbin" #: plugins/image/ir_pnm.c:382 msgid "PGMascii" msgstr "PGMascii" #: plugins/image/ir_pnm.c:409 msgid "PGMascii_16" msgstr "PGMascii_16" #: plugins/image/ir_pnm.c:438 msgid "PGMbin" msgstr "PGMbin" #: plugins/image/ir_pnm.c:461 msgid "PGMbin_16" msgstr "PGMbin_16" #: plugins/image/ir_pnm.c:486 msgid "PPMascii" msgstr "PPMascii" #: plugins/image/ir_pnm.c:529 msgid "PPMascii_16" msgstr "PPMascii_16" #: plugins/image/ir_pnm.c:607 msgid "PPMbin_16" msgstr "PPMbin_16" #: plugins/image/ir_pnm.c:655 msgid "PNM reader" msgstr "PNM Importeur" #: plugins/image/ir_pnm.c:656 msgid "Reader for PBM/PGM/PPM images" msgstr "Importeur für PBM/PGM/PPM Bilder" #: plugins/image/iw_bmp.c:129 plugins/image/iw_pnm.c:115 #: plugins/oss/i_oss.c:202 plugins/oss/oa_oss.c:144 plugins/oss/oa_oss.c:154 #: plugins/oss/oa_oss.c:164 plugins/png/pngwriter.c:56 #: plugins/tiff/iw_tiff.c:98 plugins/jpeg/iw_jpeg.c:115 #, c-format msgid "Cannot open %s: %s" msgstr "Kann %s nicht öffnen: %s" #: plugins/image/iw_bmp.c:229 msgid "BMP writer" msgstr "BMP Exporteur" #: plugins/image/iw_bmp.c:230 msgid "Writer for BMP images" msgstr "Exporteur für BMP Bilder" #: plugins/image/iw_pnm.c:197 msgid "Binary" msgstr "Binär" #: plugins/image/iw_pnm.c:197 msgid "ASCII" msgstr "ASCII" #: plugins/image/iw_pnm.c:203 lib/metadata.c:101 msgid "Comment" msgstr "Kommentar" #: plugins/image/iw_pnm.c:207 msgid "Comment which will be written in front of every file" msgstr "Kommentar (wird an jeden Dateianfang geschrieben" #: plugins/image/iw_pnm.c:243 #, fuzzy msgid "PPM/PGM writer" msgstr "PPM Exporteur" #: plugins/image/iw_pnm.c:244 #, fuzzy msgid "Writer for PPM/PGM images" msgstr "Exporteur für PPM Bilder" #: plugins/x11/ov_x11.c:551 #, c-format msgid "Got window size: %d %d" msgstr "Fentstergröße erhalten: %d %d" #: plugins/x11/ov_x11.c:919 plugins/x11/i_x11.c:96 msgid "X11" msgstr "X11" #: plugins/x11/ov_x11.c:920 msgid "" "X11 display driver with support for XVideo, XImage and OpenGL. Shared memory " "(XShm) is used where available." msgstr "" "X11 Ausgabetreiber mit Unterstützung für XVideo, XImage und OpenGL. Shared " "Memory (XShm) wird, wenn möglich, verwendet." #: plugins/x11/i_x11.c:97 msgid "X11 grabber" msgstr "" #: plugins/oss/i_oss.c:174 msgid "Invalid number of bits" msgstr "Ungültige Anzahl an Bits" #: plugins/oss/i_oss.c:189 msgid "Invalid number of channels" msgstr "Ungültige Anzahl an Kanälen" #: plugins/oss/i_oss.c:212 plugins/oss/oa_oss.c:178 plugins/oss/oa_oss.c:190 #: plugins/oss/oa_oss.c:202 #, c-format msgid "Cannot set sampleformat for %s" msgstr "Kann Zahlenformat für %s nicht setzen" #: plugins/oss/i_oss.c:220 plugins/oss/oa_oss.c:215 #, c-format msgid "Device %s doesn't support %d channel sound" msgstr "Gerät %s unterstützt kein %d-Kanal Audio" #: plugins/oss/i_oss.c:229 plugins/oss/oa_oss.c:253 plugins/oss/oa_oss.c:265 #: plugins/oss/oa_oss.c:278 #, c-format msgid "Samplerate %f kHz not supported by device %s" msgstr "Abtastrate %f kHz wird nicht unterstützt vom Gerät %s" #: plugins/oss/i_oss.c:282 plugins/oss/oa_oss.c:569 msgid "OSS" msgstr "OSS" #: plugins/oss/i_oss.c:283 msgid "OSS Recorder" msgstr "OSS Aufnahme" #: plugins/oss/oa_oss.c:53 msgid "Multichannel Mode" msgstr "Mehrkanal Modus" #: plugins/oss/oa_oss.c:60 msgid "None (Downmix)" msgstr "Keiner (Runtermischen)" #: plugins/oss/oa_oss.c:61 msgid "Multiple devices" msgstr "Mehrere Geräte" #: plugins/oss/oa_oss.c:62 msgid "Creative Multichannel" msgstr "Creative Multichannel" #: plugins/oss/oa_oss.c:73 msgid "Use Rear Device" msgstr "Benutze Gerät für hinten" #: plugins/oss/oa_oss.c:79 msgid "Rear Device" msgstr "Gerät für hinten" #: plugins/oss/oa_oss.c:85 msgid "Use Center/LFE Device" msgstr "Benutze Gerät für Mitte/LFE" #: plugins/oss/oa_oss.c:91 msgid "Center/LFE Device" msgstr "Gerät für Mitte/LFE" #: plugins/oss/oa_oss.c:227 plugins/oss/oa_oss.c:240 #, c-format msgid "Device %s supports no %d-channel sound" msgstr "Gerät %s unterstützt keinen %d-kanal Sound" #: plugins/oss/oa_oss.c:462 plugins/oss/oa_oss.c:469 plugins/oss/oa_oss.c:477 #, fuzzy, c-format msgid "Write failed: %s" msgstr "mmap fehlgeschlagen: %s" #: plugins/oss/oa_oss.c:509 msgid "SNDCTL_DSP_GETODELAY ioctl failed" msgstr "SNDCTL_DSP_GETODELAY ioctl fehlgeschlagen" #: plugins/oss/oa_oss.c:570 msgid "OSS output driver" msgstr "OSS Ausgabetreiber" #: plugins/visualization/vis_scope.c:705 msgid "Scope" msgstr "Oszi" #: plugins/visualization/vis_scope.c:706 msgid "Scope plugin" msgstr "Oszi Plugin" #: plugins/audiofilters/fa_sampleformat.c:70 include/gmerlin/bggavl.h:640 msgid "Sampleformat" msgstr "Zahlenformat" #: plugins/audiofilters/fa_sampleformat.c:200 include/gmerlin/bggavl.h:628 msgid "Force sampleformat" msgstr "Erzwinge Zahlenformat" #: plugins/audiofilters/fa_sampleformat.c:201 msgid "" "This forces a sampleformat as input for the next filter. Its mainly used for " "testing." msgstr "" "Erzwinge ein Zahlenformat als Eingabe für das nächste Filter. Überwiegend " "zum Testen benutzt." #: plugins/audiofilters/fa_volume.c:68 msgid "Volume" msgstr "Lautstärke" #: plugins/audiofilters/fa_volume.c:156 msgid "Volume control" msgstr "Lautstärkeeinstellung" #: plugins/audiofilters/fa_volume.c:157 msgid "Simple volume control" msgstr "Einfache Lautstärkeeinstellung" #: plugins/alsa/i_alsa.c:72 plugins/alsa/oa_alsa.c:95 msgid "Buffer time" msgstr "Pufferzeit" #: plugins/alsa/i_alsa.c:77 msgid "" "Set the buffer time (in milliseconds). Larger values improve recording " "performance on slow systems under load." msgstr "" "Setzt die Pufferzeit (in Millisekunden). Größere Werte verbessern die " "Aufnahmefähigkeiten aus langsamen Systemen unter Last" #: plugins/alsa/i_alsa.c:82 plugins/alsa/oa_alsa.c:88 msgid "User device" msgstr "Benutzerdefiniertes Gerät" #: plugins/alsa/i_alsa.c:84 msgid "" "Enter a custom device to use for recording. Leave empty to use the settings " "above" msgstr "" "Gib ein benutzerdefiniertes Gerät zur Aufnahme an. Oder leerlassen für obige " "Einstellungen." #: plugins/alsa/i_alsa.c:271 msgid "Dropping samples" msgstr "Überspringe Abtastwerte" #: plugins/alsa/i_alsa.c:275 msgid "snd_pcm_prepare failed" msgstr "snd_pcm_prepare fehlgeschlagen" #: plugins/alsa/i_alsa.c:282 msgid "Unknown error" msgstr "Unbekanner Fehler" #: plugins/alsa/i_alsa.c:343 plugins/alsa/oa_alsa.c:472 msgid "Alsa" msgstr "Alsa" #: plugins/alsa/i_alsa.c:344 msgid "Alsa recorder" msgstr "Alsa Aufnahme" #: plugins/alsa/oa_alsa.c:60 msgid "Enable 4.0 Surround" msgstr "Verwende 4.0 Surround" #: plugins/alsa/oa_alsa.c:63 msgid "Use the surround 4.0 (aka quadrophonic) device" msgstr "Benutze das Surround 4.0 (oder Quadrophonische) Gerät" #: plugins/alsa/oa_alsa.c:67 msgid "Enable 4.1 Surround" msgstr "Verwende 4.1 Surround" #: plugins/alsa/oa_alsa.c:70 msgid "Use the surround 4.1 device" msgstr "Benutze das Surround 4.1 Gerät" #: plugins/alsa/oa_alsa.c:74 msgid "Enable 5.0 Surround" msgstr "Verwende 5.0 Surround" #: plugins/alsa/oa_alsa.c:77 msgid "Use the surround 5.0 device" msgstr "Benutze das Surround 5.0 Gerät" #: plugins/alsa/oa_alsa.c:81 msgid "Enable 5.1 Surround" msgstr "Verwende 5.1 Surround" #: plugins/alsa/oa_alsa.c:84 msgid "Use the surround 5.1 device" msgstr "Benutze das Surround 5.1 Gerät" #: plugins/alsa/oa_alsa.c:90 msgid "" "Enter a custom device to use for playback. Leave empty to use the settings " "above" msgstr "" "Gib ein benutzerdefiniertes Gerät zur Wiedergabe an. Oder leerlassen für " "obige Einstellungen." #: plugins/alsa/oa_alsa.c:100 msgid "" "Set the buffer time (in milliseconds). Larger values improve playback " "performance on slow systems under load. Smaller values decrease the latency " "of the volume control." msgstr "" "Setze die Pufferzeit (in Millisekunden). Größere Werte verbessern vie " "wiedergabe auf schwachen Systemen unter Last. Kleinere Werte verringern die " "Verzögerung des Lautstärkereglers." #: plugins/alsa/oa_alsa.c:387 #, c-format msgid "snd_pcm_write returned %s" msgstr "snd_pcm_write gab %s zurück" #: plugins/alsa/oa_alsa.c:473 msgid "Alsa output plugin with support for channel configurations up to 5.1" msgstr "" "Alsa Ausgabeplugin mit Unterstützung für Kanalkonfigurationen bis zu 5.1" #: plugins/alsa/alsa_common.c:62 #, c-format msgid "snd_pcm_open failed for device %s (%s)" msgstr "snd_pcm_open fehlgeschlagen für Gerät %s (%s)" #: plugins/alsa/alsa_common.c:73 msgid "snd_pcm_hw_params_malloc failed" msgstr "snd_pcm_hw_params_malloc fehlgeschlagen" #: plugins/alsa/alsa_common.c:78 msgid "snd_pcm_hw_params_any failed" msgstr "snd_pcm_hw_params_any fehlgeschlagen" #: plugins/alsa/alsa_common.c:87 msgid "snd_pcm_hw_params_set_access failed" msgstr "snd_pcm_hw_params_set_access fehlgeschlagen" #: plugins/alsa/alsa_common.c:106 plugins/alsa/alsa_common.c:120 #: plugins/alsa/alsa_common.c:145 plugins/alsa/alsa_common.c:184 msgid "snd_pcm_hw_params_set_format failed" msgstr "snd_pcm_hw_params_set_format fehlgeschlagen" #: plugins/alsa/alsa_common.c:218 plugins/alsa/alsa_common.c:232 #, c-format msgid "snd_pcm_hw_params_set_channels failed (Format has %d channels)" msgstr "snd_pcm_hw_params_set_channels fehlgeschlagen (Format hat %d Kanäle)" #: plugins/alsa/alsa_common.c:249 msgid "snd_pcm_hw_params_set_rate_near failed" msgstr "snd_pcm_hw_params_set_rate_near fehlgeschlagen" #: plugins/alsa/alsa_common.c:255 #, c-format msgid "Samplerate %d not supported by device %s, using %d" msgstr "Abtastfrequenz %d wird vom Gerät %s nicht unterstützt, nehme %d" #: plugins/alsa/alsa_common.c:286 msgid "snd_pcm_hw_params_set_period_size failed" msgstr "snd_pcm_hw_params_set_period_size fehlgeschlagen" #: plugins/alsa/alsa_common.c:295 msgid "snd_pcm_hw_params_set_buffer_size failed" msgstr "snd_pcm_hw_params_set_buffer_size fehlgeschlagen" #: plugins/alsa/alsa_common.c:307 msgid "snd_pcm_hw_params failed" msgstr "snd_pcm_hw_params fehlgeschlagen" #: plugins/alsa/alsa_common.c:318 msgid "Alsa initialization failed" msgstr "Alsa Initialisierung fehlgeschlagen" #: plugins/alsa/alsa_common.c:381 msgid "Card" msgstr "Karte" #: plugins/alsa/alsa_common.c:389 msgid "No soundcards found" msgstr "Keine Soundkarten gefunden" #: plugins/alsa/alsa_common.c:396 msgid "Default" msgstr "Voreingestellt" #: plugins/alsa/alsa_common.c:405 #, c-format msgid "control open failed (%i): %s" msgstr "control open fehlgeschlagen (%i): %s" #: plugins/alsa/alsa_common.c:412 #, c-format msgid "control hardware info failed (%i): %s" msgstr "control hardware info fehlgeschlagen (%i): %s" #: plugins/alsa/alsa_common.c:425 msgid "snd_ctl_pcm_next_device failed" msgstr "snd_ctl_pcm_next_device fehlgeschlagen" #: plugins/alsa/alsa_common.c:441 #, c-format msgid "control digital audio info failed (%i): %s" msgstr "control digital audio info fehlgeschlagen (%i): %s" # Lasse cdrdao nicht laufen (vom Benutzer abgeschaltet #: plugins/postprocessors/cdrdao_common.c:111 msgid "Not running cdrdao (disabled by user)" msgstr "Lasse cdrdao nicht laufen (vom Benutzer abgeschaltet)" #: plugins/postprocessors/cdrdao_common.c:116 msgid "cdrdao executable not found" msgstr "cdrdao Programm nicht gefunden" #: plugins/postprocessors/cdrdao_common.c:181 #: plugins/postprocessors/cdrdao_common.c:186 #: plugins/postprocessors/cdrdao_common.c:194 #: plugins/postprocessors/cdrdao_common.c:209 #: plugins/postprocessors/cdrdao_common.c:212 #: plugins/postprocessors/e_pp_vcdimager.c:225 #, c-format msgid "%s" msgstr "" #: plugins/postprocessors/cdrdao_common.h:26 msgid "Burn options" msgstr "Brennoptionen" #: plugins/postprocessors/cdrdao_common.h:31 msgid "Run cdrdao" msgstr "Lasse cdrdao laufen" #: plugins/postprocessors/cdrdao_common.h:40 msgid "" "Device to use as burner. Type \"cdrdao scanbus\" at the commandline for " "available devices. Leave this empty to use the default /dev/cdrecorder." msgstr "" "Gerät mit dem gebrannt werden soll, Gib \"cdrdao scanbus\" an der " "Kommandozeile ein um verfügbare Geräte anzuzeigen. Leerlassen um die " "Voreinstellung (/dev/cdrecorder) zu benutzen" #: plugins/postprocessors/cdrdao_common.h:44 msgid "Driver" msgstr "Treiber" #: plugins/postprocessors/cdrdao_common.h:47 msgid "" "Driver to use. Check the cdrdao manual page and the cdrdao README for " "available drivers/options. Leave this empty to attempt autodetection." msgstr "" "Zu verwendender Treiber. Lies die Manualpage oder die cdrdao README für " "verfügbare Treiber und Optionen." #: plugins/postprocessors/cdrdao_common.h:51 msgid "Eject after burning" msgstr "Nach dem Brennen auswerfen" #: plugins/postprocessors/cdrdao_common.h:57 msgid "Simulate" msgstr "Simulieren" #: plugins/postprocessors/cdrdao_common.h:63 plugins/cdaudio/cdparanoia.c:192 msgid "Speed" msgstr "Geschwindigkeit" #: plugins/postprocessors/cdrdao_common.h:68 msgid "Set the writing speed. 0 means autodetect." msgstr "Setzt die Schreibgeschwikdigkeit. 0 heißt automatisch." #: plugins/postprocessors/cdrdao_common.h:72 msgid "No pause" msgstr "Keine Pause" #: plugins/postprocessors/cdrdao_common.h:75 msgid "Skip the 10 second pause before writing or simulating starts." msgstr "" "Überspringe die 10 Sekunden Pause bevor das Schreiben oder Simulieren " "beginnt." #: plugins/postprocessors/e_pp_cdrdao.c:96 msgid "Audio CD options" msgstr "Audio CD Optionen" #: plugins/postprocessors/e_pp_cdrdao.c:101 msgid "TOC file" msgstr "Inhaltsverzeichnis-Datei" #: plugins/postprocessors/e_pp_cdrdao.c:107 msgid "Gap between tracks" msgstr "Lücke zwischen Tracks" #: plugins/postprocessors/e_pp_cdrdao.c:110 msgid "" "Pre gap of each track in CD frames (1/75 seconds). Default is 150 (2 sec)." msgstr "" "\"Pre gap\" für jedes Stück in CD Rahmen (1/75 Sekunden). Voreinstellung ist " "150 (2 Sekunden)." #: plugins/postprocessors/e_pp_cdrdao.c:114 msgid "Write CD-Text" msgstr "Schreibe CD-Text" #: plugins/postprocessors/e_pp_cdrdao.c:243 #, c-format msgid "Cannot get duration of file %s" msgstr "Kann Dauer der Datei %s nicht ermitteln" #: plugins/postprocessors/e_pp_cdrdao.c:290 msgid "Skipping cdrdao run (no tracks)" msgstr "Überspringe cdrdao Lauf (keine Stücke)" #: plugins/postprocessors/e_pp_cdrdao.c:433 #, c-format msgid "Wrote %s" msgstr "%s geschrieben" #: plugins/postprocessors/e_pp_cdrdao.c:443 #: plugins/postprocessors/e_pp_cdrdao.c:447 #: plugins/postprocessors/e_pp_vcdimager.c:365 #: plugins/postprocessors/e_pp_vcdimager.c:369 #: plugins/postprocessors/e_pp_vcdimager.c:376 #: plugins/postprocessors/e_pp_vcdimager.c:378 lib/tree.c:1478 lib/ocr.c:265 #, c-format msgid "Removing %s" msgstr "Lösche %s" #: plugins/postprocessors/e_pp_cdrdao.c:466 msgid "Audio CD generator/burner" msgstr "Audio CDs erzeugen/brennen" #: plugins/postprocessors/e_pp_cdrdao.c:467 msgid "" "This is a frontend for generating audio CD images (optionally with CD-Text) " "for cdrdao (http://cdrdao.sourceforge.net). Optional burning is also " "supported." msgstr "" "Dies ist ein Frontend zum Erzeugen von Audio-CD Abbildern (optional mit CD-" "Text) für cdrdao (http://cdrdao.sourceforge.net). Optionales Brennen wird " "ebenfalls unterstützt." #: plugins/postprocessors/e_pp_vcdimager.c:105 msgid "VCD options" msgstr "VCD Optionen" #: plugins/postprocessors/e_pp_vcdimager.c:114 msgid "VCD 1.1" msgstr "VCD 1.1" #: plugins/postprocessors/e_pp_vcdimager.c:114 msgid "VCD 2.0" msgstr "VCD 2.0" #: plugins/postprocessors/e_pp_vcdimager.c:114 msgid "SVCD" msgstr "SVCD" #: plugins/postprocessors/e_pp_vcdimager.c:114 msgid "HQSVCD" msgstr "HQSVCD" #: plugins/postprocessors/e_pp_vcdimager.c:118 msgid "ISO 9660 volume label" msgstr "ISO 9660 Datenträgerbezeichnung" #: plugins/postprocessors/e_pp_vcdimager.c:124 msgid "Xml file" msgstr "Xml Datei" #: plugins/postprocessors/e_pp_vcdimager.c:130 msgid "Bin file" msgstr "Bin Datei" #: plugins/postprocessors/e_pp_vcdimager.c:136 msgid "Cue file" msgstr "Cue Datei" #: plugins/postprocessors/e_pp_vcdimager.c:254 #, c-format msgid "Scanning %s" msgstr "Durchsuche %s" #: plugins/postprocessors/e_pp_vcdimager.c:261 msgid "Writing image" msgstr "Schreibe Abbild" #: plugins/postprocessors/e_pp_vcdimager.c:322 #, c-format msgid "vcdxgen failed: %s" msgstr "vcdxgen fehlgeschlagen: %s" #: plugins/postprocessors/e_pp_vcdimager.c:403 msgid "VCD image generator/burner" msgstr "VCD Abbilder erzeugen/brennen" #: plugins/postprocessors/e_pp_vcdimager.c:404 msgid "" "This is a frontend for generating (S)VCD images with the vcdimager tools " "(http://www.vcdimager.org). Burning with cdrdao (http://cdrdao.sourceforge." "net) is also possible." msgstr "" "Die ist ein Frontend zum Zrzeugen von (S)VCD Abbildern für die vcdimager " "tools \"\n" "\"(http://www.vcdimager.org). Brennen mit cdrdao (http://cdrdao.sourceforge." "\"\n" "\"net) ist auch möglich." #: plugins/videofilters/fv_colormatrix_yuv.c:90 msgid "Luminance" msgstr "Luminanz" #: plugins/videofilters/fv_colormatrix_yuv.c:96 msgid "Luminance -> Luminance" msgstr "Luminanz -> Luminanz" #: plugins/videofilters/fv_colormatrix_yuv.c:106 msgid "Cb -> Luminance" msgstr "Cb -> Luminanz" #: plugins/videofilters/fv_colormatrix_yuv.c:116 msgid "Cr -> Luminance" msgstr "Cr -> Luminanz" #: plugins/videofilters/fv_colormatrix_yuv.c:126 msgid "Alpha -> Luminance" msgstr "Transparenz -> Luminanz" #: plugins/videofilters/fv_colormatrix_yuv.c:136 msgid "Luminance offset" msgstr "Luminanz Offset" #: plugins/videofilters/fv_colormatrix_yuv.c:148 msgid "Cb" msgstr "Cb" #: plugins/videofilters/fv_colormatrix_yuv.c:154 msgid "Luminance -> Cb" msgstr "Luminanz -> Cb" #: plugins/videofilters/fv_colormatrix_yuv.c:164 msgid "Cb -> Cb" msgstr "Cb -> Cb" #: plugins/videofilters/fv_colormatrix_yuv.c:174 msgid "Cr -> Cb" msgstr "Cb -> Cb" #: plugins/videofilters/fv_colormatrix_yuv.c:184 msgid "Alpha -> Cb" msgstr "Transparenz -> Cb" #: plugins/videofilters/fv_colormatrix_yuv.c:194 msgid "Cb offset" msgstr "Cb Offset" #: plugins/videofilters/fv_colormatrix_yuv.c:206 msgid "Cr" msgstr "Cr" #: plugins/videofilters/fv_colormatrix_yuv.c:212 msgid "Luminance -> Cr" msgstr "Luminanz -> Cr" #: plugins/videofilters/fv_colormatrix_yuv.c:222 msgid "Cb -> Cr" msgstr "Cb -> Cr" #: plugins/videofilters/fv_colormatrix_yuv.c:232 msgid "Cr -> Cr" msgstr "Cr -> Cr" #: plugins/videofilters/fv_colormatrix_yuv.c:242 msgid "Alpha -> Cr" msgstr "Transparenz -> Cr" #: plugins/videofilters/fv_colormatrix_yuv.c:252 msgid "Cr offset" msgstr "Cr Offset" #: plugins/videofilters/fv_colormatrix_yuv.c:264 #: plugins/videofilters/fv_colormatrix_rgb.c:268 msgid "Alpha" msgstr "Transparenz" #: plugins/videofilters/fv_colormatrix_yuv.c:270 msgid "Luminance -> Alpha" msgstr "Luminanz -> Transparenz" #: plugins/videofilters/fv_colormatrix_yuv.c:280 msgid "Cb -> Alpha" msgstr "Cb -> Transparenz" #: plugins/videofilters/fv_colormatrix_yuv.c:290 msgid "Cr -> Alpha" msgstr "Cr -> Transparenz" #: plugins/videofilters/fv_colormatrix_yuv.c:300 #: plugins/videofilters/fv_colormatrix_rgb.c:304 msgid "Alpha -> Alpha" msgstr "Transparenz -> Transparenz" #: plugins/videofilters/fv_colormatrix_yuv.c:310 #: plugins/videofilters/fv_colormatrix_rgb.c:314 msgid "Alpha offset" msgstr "Transparenz Offset" #: plugins/videofilters/fv_colormatrix_yuv.c:320 #: plugins/videofilters/fv_colormatrix_rgb.c:324 msgid "Misc" msgstr "Vermischtes" #: plugins/videofilters/fv_colormatrix_yuv.c:325 #: plugins/videofilters/fv_colormatrix_rgb.c:329 msgid "Force alpha" msgstr "Erzwinge Transparenz" #: plugins/videofilters/fv_colormatrix_yuv.c:328 #: plugins/videofilters/fv_colormatrix_rgb.c:332 msgid "" "Create video with alpha channel even if the input format has no alpha " "channel. Use this to generate the alpha channel from other channels using " "the colormatrix." msgstr "" "Ergeuge ein Video mit Transparenzkanal, selbst wenn die Quelle keinen hat. " "Benutze diese Option um einen Transparenzkanal aus den anderen Kanälen mit " "der Farbmatrix zu erzeugen." #: plugins/videofilters/fv_colormatrix_yuv.c:460 msgid "Y'CbCr(A) Colormatrix" msgstr "Y'CbCr(A) Farbmatrix" #: plugins/videofilters/fv_colormatrix_yuv.c:461 msgid "" "Generic colormatrix (Y'CbCrA). You pass the coefficients in Y'CbCr(A) " "coordinates, but the processing will work in RGB(A) as well." msgstr "" "Allgemeine Farbmatrix (Y'CbCrA). Du gibst die Koeffizienten in Y'CbCr(A) " "Koordinaten an, die Verarbeitung funktioniert aber auch in RGB(A)." #: plugins/videofilters/fv_deinterlace.c:133 msgid "Method" msgstr "Methode" #: plugins/videofilters/fv_deinterlace.c:147 msgid "Scanline doubler" msgstr "Zeilen verdoppeln" #: plugins/videofilters/fv_deinterlace.c:148 msgid "Scaler (hardware)" msgstr "Skalieren (Hardware)" #: plugins/videofilters/fv_deinterlace.c:149 msgid "Scaler (software)" msgstr "Skalieren (Software)" #: plugins/videofilters/fv_deinterlace.c:150 msgid "Blend" msgstr "Felder mischen" #: plugins/videofilters/fv_deinterlace.c:151 msgid "Yadif" msgstr "" #: plugins/videofilters/fv_deinterlace.c:152 msgid "Yadif (fast)" msgstr "" #: plugins/videofilters/fv_deinterlace.c:154 #: plugins/videofilters/fv_tctweak.c:87 msgid "Do nothing" msgstr "Mache nichts" #: plugins/videofilters/fv_deinterlace.c:155 msgid "Simply double all scanlines. Very fast but low image quality" msgstr "" "Verdopple alle Bildzeilen. Dies ist sehr schnell aber liefert schlechte " "Qualität." #: plugins/videofilters/fv_deinterlace.c:157 msgid "" "Drop one field and change the pixel aspect ratio such that a subsequent " "hardware scaler will scale the image to the original height" msgstr "" "Lasse ein Feld wegfallen und verdoppele die Pixelhöhe, so daß ein " "nachfolgender Hardware Skalierer das Bild wieder auf die originale Höhe " "skalieren kann." #: plugins/videofilters/fv_deinterlace.c:158 msgid "Drop one field and scale the image to the original height" msgstr "Lasse ein Feld wegfallen und skaliere das Bild zur Originalhöhe." #: plugins/videofilters/fv_deinterlace.c:159 msgid "yadif" msgstr "" #: plugins/videofilters/fv_deinterlace.c:160 msgid "yadif (fast mode)" msgstr "" #: plugins/videofilters/fv_deinterlace.c:165 include/gmerlin/bggavl.h:244 msgid "Force deinterlacing" msgstr "Erzwinge Deinterlacing" #: plugins/videofilters/fv_deinterlace.c:172 #, fuzzy msgid "Output mode" msgstr "Ausgabe" #: plugins/videofilters/fv_deinterlace.c:176 msgid "" "Specify which field to output. Outputting both fields is not always " "supported." msgstr "" #: plugins/videofilters/fv_deinterlace.c:178 #, fuzzy msgid "Top field" msgstr "Oberes Feld zuerst" #: plugins/videofilters/fv_deinterlace.c:179 #, fuzzy msgid "Bottom field" msgstr "Unteres Feld zuerst" #: plugins/videofilters/fv_deinterlace.c:180 #, fuzzy msgid "First field" msgstr "Lasse oberes Feld weg" #: plugins/videofilters/fv_deinterlace.c:181 #, fuzzy msgid "Second field" msgstr "Befehl schicken fehlgeschlagen" #: plugins/videofilters/fv_deinterlace.c:182 #, fuzzy msgid "Both fields" msgstr "Unteres Feld zuerst" #: plugins/videofilters/fv_deinterlace.c:510 msgid "Deinterlacer" msgstr "Deinterlacer" #: plugins/videofilters/fv_deinterlace.c:511 msgid "Deinterlace with various algorithms" msgstr "Deinterlacer mit verschiedenen Methoden" #: plugins/videofilters/fv_transform.c:166 #: plugins/videofilters/fv_textlogo.c:86 #: plugins/videofilters/fv_tcdisplay.c:81 plugins/cdaudio/i_cdaudio.c:541 #: apps/player/cfgdialog.c:104 apps/transcoder/transcoder_window.c:1304 #: apps/transcoder/transcoder_window.c:1331 #: apps/transcoder/transcoder_window.c:1354 apps/transcoder/trackdialog.c:87 #: apps/transcoder/trackdialog.c:226 apps/transcoder/trackdialog.c:296 #: apps/transcoder/trackdialog.c:382 apps/transcoder/trackdialog.c:450 #: apps/visualizer/gmerlin_visualizer.c:890 #: apps/recorder/recorder_window.c:724 apps/recorder/recorder_window.c:743 #: lib/player_subtitle.c:117 lib/pluginregistry.c:2114 #: lib/x11/x11_window.c:1112 lib/transcoder_track.c:1326 msgid "General" msgstr "Generell" #: plugins/videofilters/fv_transform.c:171 msgid "Transformation mode" msgstr "Transformationsmodus" #: plugins/videofilters/fv_transform.c:178 #: plugins/videofilters/fv_transform.c:208 msgid "Rotate" msgstr "Drehen" #: plugins/videofilters/fv_transform.c:179 #: plugins/videofilters/fv_transform.c:223 msgid "Generic affine" msgstr "Allgemein affin" #: plugins/videofilters/fv_transform.c:180 #: plugins/videofilters/fv_transform.c:290 msgid "Perspective" msgstr "Perspective" #: plugins/videofilters/fv_transform.c:181 #: plugins/videofilters/fv_transform.c:331 msgid "Lens effect" msgstr "Linseneffekt" #: plugins/videofilters/fv_transform.c:182 #: plugins/videofilters/fv_transform.c:367 msgid "Pinch/whirl" msgstr "Quetschen/wirbeln" #: plugins/videofilters/fv_transform.c:185 msgid "" "Choose Transformation method. Each method can be configured in it's section." msgstr "" "Wähle Transformationsmethode. Jede Methode kann in einer eigenen Sektion " "konfiguriert werden." #: plugins/videofilters/fv_transform.c:190 msgid "Interpolation mode" msgstr "Interpolationsmethode" #: plugins/videofilters/fv_transform.c:197 msgid "" "Choose interpolation method. Auto means to choose based on the conversion " "quality. Nearest is fastest, Bicubic is slowest." msgstr "" "Wähle die Interpolationsmethode. Automatisch heißt Wahl aufgrund der " "Qualität. \"Nächstes Pixel\" ist am schnellsten, Bikubisch ist am " "langsamsten." #: plugins/videofilters/fv_transform.c:201 plugins/videofilters/fv_zoom.c:160 #: plugins/lqt/e_lqt.c:948 include/gmerlin/bggavl.h:367 #: lib/x11/x11_window.c:1170 lib/ocr.c:152 msgid "Background color" msgstr "Hintergrundfarbe" #: plugins/videofilters/fv_transform.c:213 #: plugins/videofilters/fv_transform.c:400 msgid "Angle" msgstr "Winkel" #: plugins/videofilters/fv_transform.c:228 msgid "X -> X" msgstr "X -> X" #: plugins/videofilters/fv_transform.c:238 msgid "X -> Y" msgstr "X -> Y" #: plugins/videofilters/fv_transform.c:248 msgid "Y -> X" msgstr "Y -> X" #: plugins/videofilters/fv_transform.c:258 msgid "Y -> Y" msgstr "Y -> Y" #: plugins/videofilters/fv_transform.c:268 msgid "X Offset" msgstr "X Offset" #: plugins/videofilters/fv_transform.c:275 msgid "Normalized X offset. 1 corresponds to image with." msgstr "Normierter X-Offset. 1 enspricht Bildbreite." #: plugins/videofilters/fv_transform.c:279 msgid "Y Offset" msgstr "Y Offset" #: plugins/videofilters/fv_transform.c:286 msgid "Normalized Y offset. 1 corresponds to image height." msgstr "Normierter Y-Offset. 1 enspricht Bildhöhe." #: plugins/videofilters/fv_transform.c:295 msgid "Top left" msgstr "Oben links" #: plugins/videofilters/fv_transform.c:300 msgid "Top left corner in normalized image coordinates" msgstr "Obere linke Ecke in normierten Bildkoordinaten" #: plugins/videofilters/fv_transform.c:304 msgid "Top right" msgstr "Oben rechts" #: plugins/videofilters/fv_transform.c:309 msgid "Top right corner in normalized image coordinates" msgstr "Obere rechte Ecke in normierten Bildkoordinaten" #: plugins/videofilters/fv_transform.c:313 msgid "Bottom left" msgstr "Unten links" #: plugins/videofilters/fv_transform.c:318 msgid "Bottom left corner in normalized image coordinates" msgstr "Untere linke Ecke in normierten Bildkoordinaten" #: plugins/videofilters/fv_transform.c:322 msgid "Bottom right" msgstr "Unten rechts" #: plugins/videofilters/fv_transform.c:327 msgid "Bottom right corner in normalized image coordinates" msgstr "Untere rechte Ecke in normierten Bildkoordinaten" #: plugins/videofilters/fv_transform.c:336 msgid "Position" msgstr "Position" #: plugins/videofilters/fv_transform.c:341 msgid "Center of the lens" msgstr "Mitte der Linse" #: plugins/videofilters/fv_transform.c:345 msgid "Diameter" msgstr "Durchmesser" #: plugins/videofilters/fv_transform.c:352 msgid "Diamater of the lens (1 is image size)" msgstr "Durchmesser der Linse (1 entspricht Bildgröße)" #: plugins/videofilters/fv_transform.c:356 plugins/videofilters/fv_zoom.c:378 msgid "Zoom" msgstr "Zoom" #: plugins/videofilters/fv_transform.c:363 msgid "Zoom factor" msgstr "Vergrößerungsfaktor" #: plugins/videofilters/fv_transform.c:372 #: plugins/videofilters/fv_textlogo.c:136 #: plugins/videofilters/fv_textlogo.c:145 #: plugins/videofilters/fv_tcdisplay.c:132 #: plugins/videofilters/fv_tcdisplay.c:141 lib/textrenderer.c:98 #: lib/textrenderer.c:107 lib/osd.c:121 lib/osd.c:129 msgid "Center" msgstr "Mitte" #: plugins/videofilters/fv_transform.c:380 msgid "Radius" msgstr "Radius" #: plugins/videofilters/fv_transform.c:390 msgid "Pinch" msgstr "Quetschen" #: plugins/videofilters/fv_transform.c:1262 msgid "Transform" msgstr "Transformation" #: plugins/videofilters/fv_transform.c:1263 msgid "Transform the image with different methods" msgstr "Transformiere das Bild mit verschiedenen Methoden" #: plugins/videofilters/fv_swapfields.c:137 msgid "Unsupported interlace mode, need top-first or bottom-first" msgstr "" #: plugins/videofilters/fv_swapfields.c:258 #, fuzzy msgid "Swap fields" msgstr "Oberes Feld zuerst" #: plugins/videofilters/fv_swapfields.c:259 #, fuzzy msgid "Swap field order" msgstr "Ausgabedateien" #: plugins/videofilters/fv_textlogo.c:91 msgid "Text" msgstr "" #: plugins/videofilters/fv_textlogo.c:94 msgid "Text to display" msgstr "" #: plugins/videofilters/fv_textlogo.c:98 #: plugins/videofilters/fv_tcdisplay.c:94 lib/textrenderer.c:60 msgid "Render options" msgstr "Renderoptionen" #: plugins/videofilters/fv_textlogo.c:103 #: plugins/videofilters/fv_tcdisplay.c:99 plugins/lqt/e_lqt.c:942 #: lib/textrenderer.c:65 msgid "Text color" msgstr "Textfarbe" #: plugins/videofilters/fv_textlogo.c:110 #: plugins/videofilters/fv_cropscale.c:317 #: plugins/videofilters/fv_tcdisplay.c:106 lib/textrenderer.c:72 lib/osd.c:101 msgid "Border color" msgstr "Randfarbe" #: plugins/videofilters/fv_textlogo.c:116 #: plugins/videofilters/fv_tcdisplay.c:112 lib/textrenderer.c:78 lib/osd.c:107 msgid "Border width" msgstr "Randfarbe" #: plugins/videofilters/fv_textlogo.c:126 #: plugins/videofilters/fv_tcdisplay.c:122 apps/player/display.c:110 #: apps/transcoder/transcoder_window.c:195 lib/textrenderer.c:88 msgid "Font" msgstr "Schrift" #: plugins/videofilters/fv_textlogo.c:132 #: plugins/videofilters/fv_tcdisplay.c:128 lib/textrenderer.c:94 lib/osd.c:117 msgid "Horizontal justify" msgstr "Horizontale Ausrichtung" #: plugins/videofilters/fv_textlogo.c:136 #: plugins/videofilters/fv_tcdisplay.c:132 lib/textrenderer.c:98 lib/osd.c:121 msgid "Left" msgstr "Links" #: plugins/videofilters/fv_textlogo.c:136 #: plugins/videofilters/fv_tcdisplay.c:132 lib/textrenderer.c:98 lib/osd.c:121 msgid "Right" msgstr "Rechts" #: plugins/videofilters/fv_textlogo.c:141 #: plugins/videofilters/fv_tcdisplay.c:137 lib/textrenderer.c:103 #: lib/osd.c:125 msgid "Vertical justify" msgstr "Vertikale Ausrichtung" #: plugins/videofilters/fv_textlogo.c:145 #: plugins/videofilters/fv_tcdisplay.c:141 lib/textrenderer.c:107 #: lib/osd.c:129 msgid "Top" msgstr "Oben" #: plugins/videofilters/fv_textlogo.c:145 #: plugins/videofilters/fv_tcdisplay.c:141 lib/textrenderer.c:107 #: lib/osd.c:129 msgid "Bottom" msgstr "Unten" #: plugins/videofilters/fv_textlogo.c:149 #: plugins/videofilters/fv_tcdisplay.c:145 lib/textrenderer.c:111 msgid "Cache size" msgstr "Cachegröße" #: plugins/videofilters/fv_textlogo.c:156 #: plugins/videofilters/fv_tcdisplay.c:152 lib/textrenderer.c:117 msgid "" "Specify, how many different characters are cached for faster rendering. For " "European languages, this never needs to be larger than 255." msgstr "" "Gib an, wieviele verschiedene Zeichen zur schelleren Darstellung " "zwischengespeichert werden. Für europäische Sprachen muß dieser Wert nie " "größer als 255 sein." #: plugins/videofilters/fv_textlogo.c:160 #: plugins/videofilters/fv_tcdisplay.c:156 lib/textrenderer.c:121 #: lib/osd.c:133 msgid "Left border" msgstr "Linker Rand" #: plugins/videofilters/fv_textlogo.c:165 #: plugins/videofilters/fv_tcdisplay.c:161 lib/textrenderer.c:126 #: lib/osd.c:138 msgid "Distance from the left text border to the image border" msgstr "Abstand vom linken Textrand zum Bildrand" #: plugins/videofilters/fv_textlogo.c:169 #: plugins/videofilters/fv_tcdisplay.c:165 lib/textrenderer.c:130 #: lib/osd.c:142 msgid "Right border" msgstr "Rechter Rand" #: plugins/videofilters/fv_textlogo.c:174 #: plugins/videofilters/fv_tcdisplay.c:170 lib/textrenderer.c:135 #: lib/osd.c:147 msgid "Distance from the right text border to the image border" msgstr "Abstand vom rechten Textrand zum Bildrand" #: plugins/videofilters/fv_textlogo.c:178 #: plugins/videofilters/fv_tcdisplay.c:174 lib/textrenderer.c:139 #: lib/osd.c:151 msgid "Top border" msgstr "Oberer Rand" #: plugins/videofilters/fv_textlogo.c:183 #: plugins/videofilters/fv_tcdisplay.c:179 lib/textrenderer.c:144 #: lib/osd.c:156 msgid "Distance from the top text border to the image border" msgstr "Abstand vom oberen Textrand zum Bildrand" #: plugins/videofilters/fv_textlogo.c:192 #: plugins/videofilters/fv_tcdisplay.c:188 lib/textrenderer.c:153 #: lib/osd.c:165 msgid "Distance from the bottom text border to the image border" msgstr "Abstand vom unteren Textrand zum Bildrand" #: plugins/videofilters/fv_textlogo.c:196 #: plugins/videofilters/fv_textlogo.c:199 #: plugins/videofilters/fv_tcdisplay.c:192 #: plugins/videofilters/fv_tcdisplay.c:195 lib/textrenderer.c:157 #: lib/textrenderer.c:159 msgid "Ignore linebreaks" msgstr "Ignoriere Zeilenumbrüche" #: plugins/videofilters/fv_textlogo.c:314 #, fuzzy msgid "Text logo" msgstr "Textfarbe" #: plugins/videofilters/fv_textlogo.c:315 #, fuzzy msgid "Burn a static text onto video frames" msgstr "Brenne Timecodes in Videobilder" #: plugins/videofilters/colormatrix.c:1434 #: plugins/videofilters/fv_colorbalance.c:610 #: plugins/videofilters/fv_equalizer.c:729 #, c-format msgid "Pixelformat: %s" msgstr "Pixelformat: %s" #: plugins/videofilters/fv_cropscale.c:137 msgid "Crop" msgstr "Zuschneiden" #: plugins/videofilters/fv_cropscale.c:142 msgid "Crop left" msgstr "Schneide links" #: plugins/videofilters/fv_cropscale.c:150 msgid "Cut this many pixels from the left border of the source images." msgstr "Schneide so viele Pixel vom linken Rand der Quellbilder." #: plugins/videofilters/fv_cropscale.c:154 msgid "Crop right" msgstr "Schneide rechts" #: plugins/videofilters/fv_cropscale.c:162 msgid "Cut this many pixels from the right border of the source images." msgstr "Schneide so viele Pixel vom rechten Rand der Quellbilder." #: plugins/videofilters/fv_cropscale.c:166 msgid "Crop top" msgstr "Schneide oben" #: plugins/videofilters/fv_cropscale.c:174 msgid "Cut this many pixels from the top border of the source images." msgstr "Schneide so viele Pixel vom oberen Rand der Quellbilder." #: plugins/videofilters/fv_cropscale.c:178 msgid "Crop bottom" msgstr "Schneide unten" #: plugins/videofilters/fv_cropscale.c:186 msgid "Cut this many pixels from the bottom border of the source images." msgstr "Schneide so viele Pixel vom unteren Rand der Quellbilder." #: plugins/videofilters/fv_cropscale.c:189 #: plugins/videofilters/fv_cropscale.c:194 include/gmerlin/bggavl.h:495 #: include/gmerlin/bggavl.h:512 msgid "Image size" msgstr "Bildgröße" #: plugins/videofilters/fv_cropscale.c:226 #: plugins/videofilters/fv_cropscale.c:408 include/gmerlin/bggavl.h:193 msgid "From Source" msgstr "Wie Quelle" #: plugins/videofilters/fv_cropscale.c:228 include/gmerlin/bggavl.h:465 msgid "PAL DVD D1 4:3 (720 x 576)" msgstr "PAL DVD D1 4:3 (720 x 576)" #: plugins/videofilters/fv_cropscale.c:229 include/gmerlin/bggavl.h:466 msgid "PAL DVD D1 16:9 (720 x 576)" msgstr "PAL DVD D1 16:9 (720 x 576)" #: plugins/videofilters/fv_cropscale.c:230 include/gmerlin/bggavl.h:467 msgid "PAL DV 4:3 (720 x 576)" msgstr "PAL DV 4:3 (720 x 576)" #: plugins/videofilters/fv_cropscale.c:231 include/gmerlin/bggavl.h:468 msgid "PAL DV 16:9 (720 x 576)" msgstr "PAL DV 16:9 (720 x 576)" #: plugins/videofilters/fv_cropscale.c:232 include/gmerlin/bggavl.h:469 msgid "PAL CVD (352 x 576)" msgstr "PAL CVD (352 x 576)" #: plugins/videofilters/fv_cropscale.c:233 include/gmerlin/bggavl.h:470 msgid "PAL VCD (352 x 288)" msgstr "PAL VCD (352 x 288)" #: plugins/videofilters/fv_cropscale.c:234 include/gmerlin/bggavl.h:471 msgid "PAL SVCD 4:3 (480 x 576)" msgstr "PAL SVCD 4:3 (480 x 576)" #: plugins/videofilters/fv_cropscale.c:235 include/gmerlin/bggavl.h:472 msgid "PAL SVCD 16:9 (480 x 576)" msgstr "PAL SVCD 16:9 (480 x 576)" #: plugins/videofilters/fv_cropscale.c:236 include/gmerlin/bggavl.h:473 msgid "NTSC DVD D1 4:3 (720 x 480)" msgstr "NTSC DVD D1 4:3 (720 x 480)" #: plugins/videofilters/fv_cropscale.c:237 include/gmerlin/bggavl.h:474 msgid "NTSC DVD D1 16:9 (720 x 480)" msgstr "NTSC DVD D1 16:9 (720 x 480)" #: plugins/videofilters/fv_cropscale.c:238 include/gmerlin/bggavl.h:475 msgid "NTSC DV 4:3 (720 x 480)" msgstr "NTSC DV 4:3 (720 x 480)" #: plugins/videofilters/fv_cropscale.c:239 include/gmerlin/bggavl.h:476 msgid "NTSC DV 16:9 (720 x 480)" msgstr "NTSC DV 16:9 (720 x 480)" #: plugins/videofilters/fv_cropscale.c:240 include/gmerlin/bggavl.h:477 msgid "NTSC CVD (352 x 480)" msgstr "NTSC CVD (352 x 480)" #: plugins/videofilters/fv_cropscale.c:241 include/gmerlin/bggavl.h:478 msgid "NTSC VCD (352 x 240)" msgstr "NTSC VCD (352 x 240)" #: plugins/videofilters/fv_cropscale.c:242 include/gmerlin/bggavl.h:479 msgid "NTSC SVCD 4:3 (480 x 480)" msgstr "NTSC SVCD 4:3 (480 x 480)" #: plugins/videofilters/fv_cropscale.c:243 include/gmerlin/bggavl.h:480 msgid "NTSC SVCD 16:9 (480 x 480)" msgstr "NTSC SVCD 16:9 (480 x 480)" #: plugins/videofilters/fv_cropscale.c:244 include/gmerlin/bggavl.h:481 msgid "HD 720p/i (1280x720)" msgstr "HD 720p/i (1280x720)" #: plugins/videofilters/fv_cropscale.c:245 include/gmerlin/bggavl.h:482 msgid "HD 1080p/i (1920x1080)" msgstr "HD 1080p/i (1920x1080)" #: plugins/videofilters/fv_cropscale.c:246 include/gmerlin/bggavl.h:483 msgid "VGA (640 x 480)" msgstr "VGA (640 x 480)" #: plugins/videofilters/fv_cropscale.c:247 include/gmerlin/bggavl.h:484 msgid "QVGA (320 x 240)" msgstr "QVGA (320 x 240)" #: plugins/videofilters/fv_cropscale.c:248 include/gmerlin/bggavl.h:485 msgid "SQCIF (128 × 96)" msgstr "SQCIF (128 × 96)" #: plugins/videofilters/fv_cropscale.c:249 include/gmerlin/bggavl.h:486 msgid "QCIF (176 × 144)" msgstr "QCIF (176 × 144)" #: plugins/videofilters/fv_cropscale.c:250 include/gmerlin/bggavl.h:487 msgid "CIF (352 × 288)" msgstr "CIF (352 × 288)" #: plugins/videofilters/fv_cropscale.c:251 include/gmerlin/bggavl.h:488 msgid "4CIF (704 × 576)" msgstr "4CIF (704 × 576)" #: plugins/videofilters/fv_cropscale.c:252 include/gmerlin/bggavl.h:489 msgid "16CIF (1408 × 1152)" msgstr "16CIF (1408 × 1152)" #: plugins/videofilters/fv_cropscale.c:255 include/gmerlin/bggavl.h:505 #: include/gmerlin/bggavl.h:524 msgid "" "Set the output image size. For a user defined size, you must specify the " "width and height as well as the pixel width and pixel height." msgstr "" "Wähle die ausgegebene Bildgröße. Für \"Benutzerdefiniert\" mußt Du die " "Breite, Höhe, Pixelbreite und Pixelhöhe unten angeben." #: plugins/videofilters/fv_cropscale.c:266 include/gmerlin/bggavl.h:397 msgid "" "User defined width in pixels. Only meaningful if you selected \"User defined" "\" for the image size." msgstr "" "Benutzerdefinierte Breite in Pixels. Nur von Bedeutung, wenn " "\"Benutzerdefiniert\" für die Bildgröße gewählt wurde." #: plugins/videofilters/fv_cropscale.c:277 include/gmerlin/bggavl.h:408 msgid "" "User defined height in pixels. Only meaningful if you selected \"User defined" "\" for the image size." msgstr "" "Benutzerdefinierte Höhe in Pixels. Nur von Bedeutung, wenn " "\"Benutzerdefiniert\" für die Bildgröße gewählt wurde." #: plugins/videofilters/fv_cropscale.c:281 include/gmerlin/bggavl.h:412 msgid "User defined pixel width" msgstr "Benutzerdefinierte Pixelbreite" #: plugins/videofilters/fv_cropscale.c:288 include/gmerlin/bggavl.h:419 msgid "" "User defined pixel width. Only meaningful if you selected \"User defined\" " "for the image size." msgstr "" "Benutzerdefinierte Pixelbreite. Nur von Bedeutung, wenn \"Benutzerdefiniert" "\" für die Bildgröße gewählt wurde." #: plugins/videofilters/fv_cropscale.c:292 include/gmerlin/bggavl.h:423 msgid "User defined pixel height" msgstr "Benutzerdefinierte Pixelhöhe" #: plugins/videofilters/fv_cropscale.c:299 include/gmerlin/bggavl.h:430 msgid "" "User defined pixel height. Only meaningful if you selected \"User defined\" " "for the image size." msgstr "" "Benutzerdefinierte Pixelhöhe. Nur von Bedeutung, wenn \"Benutzerdefiniert\" " "für die Bildgröße gewählt wurde." #: plugins/videofilters/fv_cropscale.c:303 msgid "Image borders" msgstr "Bildrand" #: plugins/videofilters/fv_cropscale.c:308 msgid "Maintain aspect ratio" msgstr "Erhalte Aspektverhältnis" #: plugins/videofilters/fv_cropscale.c:313 msgid "" "Let the aspect ratio appear the same as in the source, probably resulting in " "additional borders." msgstr "" "Lasse das Aspektverhältnis genauso erscheinen wie in der Quelle, " "möglicherweise mit zusätzlichen Rändern" #: plugins/videofilters/fv_cropscale.c:322 msgid "Color of the image borders." msgstr "Farbe für die Bildränder" #: plugins/videofilters/fv_cropscale.c:346 #: plugins/videofilters/fv_cropscale.c:351 plugins/videofilters/fv_zoom.c:106 #: include/gmerlin/bggavl.h:332 lib/x11/x11_window.c:1184 msgid "Scale mode" msgstr "Skaliermethode" #: plugins/videofilters/fv_cropscale.c:358 plugins/videofilters/fv_zoom.c:113 #: include/gmerlin/bggavl.h:339 lib/x11/x11_window.c:1205 msgid "" "Choose scaling method. Auto means to choose based on the conversion quality. " "Nearest is fastest, Sinc with Lanczos window is slowest." msgstr "" "Wähle die Skaliermethode. Automatisch heißt Wahl aufgrund der Qualität. " "\"Nächstes Pixel\" ist am schnellsten, Sinc mit Lanczos Fenster ist am " "langsamsten." #: plugins/videofilters/fv_cropscale.c:362 plugins/videofilters/fv_zoom.c:117 #: include/gmerlin/bggavl.h:343 lib/x11/x11_window.c:1209 msgid "Scale order" msgstr "Skalierordnung" #: plugins/videofilters/fv_cropscale.c:369 plugins/videofilters/fv_zoom.c:124 #: include/gmerlin/bggavl.h:350 lib/x11/x11_window.c:1214 msgid "Order for sinc scaling" msgstr "Ordnung für sinc Skalierung" #: plugins/videofilters/fv_cropscale.c:379 plugins/videofilters/fv_zoom.c:135 msgid "Specifies the antialiasing filter to be used when downscaling images." msgstr "" "Wählt das Antialiasingfilter, welches beim Herunterskalieren verwendet wird." #: plugins/videofilters/fv_cropscale.c:390 plugins/videofilters/fv_zoom.c:146 msgid "" "Specifies how much blurring should be applied when downscaling. Smaller " "values can speed up scaling, but might result in strong aliasing." msgstr "" "Spezifiziert, wie stark beim Herunterskalieren weichgezeichnet werden soll. " "Kleinere Werte können die Skalierung beschleunigen, können aber zu starkem " "Aliasing führen." #: plugins/videofilters/fv_cropscale.c:395 #, fuzzy msgid "Chroma output" msgstr "Videoausgabe" #: plugins/videofilters/fv_cropscale.c:409 msgid "4:4:4" msgstr "" #: plugins/videofilters/fv_cropscale.c:410 msgid "4:2:2" msgstr "" #: plugins/videofilters/fv_cropscale.c:411 msgid "4:2:0 (MPEG-1)" msgstr "" #: plugins/videofilters/fv_cropscale.c:412 #, fuzzy msgid "4:2:0 (MPEG-2)" msgstr "MPEG-2" #: plugins/videofilters/fv_cropscale.c:413 #, fuzzy msgid "4:2:0 (DV PAL)" msgstr "DV PAL" #: plugins/videofilters/fv_cropscale.c:414 msgid "4:1:1" msgstr "" #: plugins/videofilters/fv_cropscale.c:417 msgid "" "Set the output chroma format to that of the destination. This can save one " "chroma scaling operation at a later stage. It only works if the input " "pixelformat is otherwise compatible to the output." msgstr "" #: plugins/videofilters/fv_cropscale.c:421 #: plugins/videofilters/fv_cropscale.c:426 msgid "Deinterlace" msgstr "Deinterlace" #: plugins/videofilters/fv_cropscale.c:431 msgid "Never" msgstr "Nie" #: plugins/videofilters/fv_cropscale.c:431 msgid "Always" msgstr "Immer" #: plugins/videofilters/fv_cropscale.c:441 include/gmerlin/bggavl.h:239 msgid "Drop top field" msgstr "Lasse oberes Feld weg" #: plugins/videofilters/fv_cropscale.c:441 include/gmerlin/bggavl.h:239 msgid "Drop bottom field" msgstr "Lasse unteres Feld weg" #: plugins/videofilters/fv_cropscale.c:442 include/gmerlin/bggavl.h:240 msgid "Specifies which field the deinterlacer should drop." msgstr "Wählt, welches Feld der Deinterlacer weglassen soll." #: plugins/videofilters/fv_cropscale.c:1288 msgid "Crop & Scale" msgstr "Zuschneiden und Skalieren" #: plugins/videofilters/fv_cropscale.c:1289 msgid "" "Crop and scale video images. Has lots of standard video formats as presets. " "Can also do chroma placement correction and simple deinterlacing" msgstr "" "Beschneide und Skaliere Videobilder. Hat viele Standardbildgrößen als " "Voreinstellungen. Kann auch Plazierung der Farbebenen korrigieren und " "einfaches Deinterlacing durchführen." #: plugins/videofilters/fv_pixelformat.c:70 include/gmerlin/bggavl.h:254 #: apps/camelot/vloopback.c:787 msgid "Pixelformat" msgstr "Pixelformat" #: plugins/videofilters/fv_pixelformat.c:200 msgid "Force pixelformat" msgstr "Pixelformat erzwingen" #: plugins/videofilters/fv_pixelformat.c:201 msgid "" "Forces a pixelformat as input for the next filter. Its mainly used for " "testing." msgstr "" "Erzwingt ein Pixelformat als Eingabe für das nächste Filter. Wird " "überwiegend zum Testen benutzt." #: plugins/videofilters/fv_tcdisplay.c:86 plugins/videofilters/fv_tctweak.c:88 msgid "Interpolate missing" msgstr "Interpoliere fehlende" #: plugins/videofilters/fv_tcdisplay.c:90 msgid "Interpolate missing timecodes" msgstr "Interpoliere fehlende Timecodes" #: plugins/videofilters/fv_tcdisplay.c:347 msgid "Display timecodes" msgstr "Timecodes einblenden" #: plugins/videofilters/fv_tcdisplay.c:348 msgid "Burn timecodes into video frames" msgstr "Brenne Timecodes in Videobilder" #: plugins/videofilters/fv_zoom.c:85 msgid "Zoom horizontally" msgstr "Zoome horizontal" #: plugins/videofilters/fv_zoom.c:95 msgid "Zoom vertically" msgstr "Zoome vertikal" #: plugins/videofilters/fv_zoom.c:151 plugins/videofilters/fv_tlp.c:91 #: plugins/jpeg/iw_jpeg.c:265 msgid "Quality" msgstr "Qualität" #: plugins/videofilters/fv_zoom.c:379 msgid "Zoom horizontally and/or vertically" msgstr "Zoome horizontal und/oder vertikal" #: plugins/videofilters/fv_tlp.c:80 plugins/videofilters/fv_oldcolor.c:151 msgid "Strength" msgstr "Stärke" #: plugins/videofilters/fv_tlp.c:87 msgid "0 means no effect, 1 means maximum (= still image)" msgstr "0 heißt kein Effekt, 1 heißt Maximum (= Standbild)" #: plugins/videofilters/fv_tlp.c:208 msgid "Temporal lowpass" msgstr "Zeitlicher Tiefpass" #: plugins/videofilters/fv_tlp.c:209 msgid "Simple temporal lowpass" msgstr "Einfacher zeitlicher Tiefpass" #: plugins/videofilters/fv_tctweak.c:78 plugins/videofilters/fv_blur.c:229 #: apps/camelot/vloopback.c:736 msgid "Mode" msgstr "Modus" #: plugins/videofilters/fv_tctweak.c:89 msgid "Remove redundant" msgstr "Redundante rausschmeißen" #: plugins/videofilters/fv_tctweak.c:90 msgid "Remove all" msgstr "Alle löschen" #: plugins/videofilters/fv_tctweak.c:91 msgid "Add new" msgstr "Neue hinzufügen" #: plugins/videofilters/fv_tctweak.c:92 msgid "Add new (first only)" msgstr "Neue hinzufügen (nur ersten)" #: plugins/videofilters/fv_tctweak.c:103 msgid "Set the integer framerate used when adding new timecodes" msgstr "Ganzzahlige Bildwiederholrate für neu hinzugefügte Timecodes" #: plugins/videofilters/fv_tctweak.c:109 msgid "Set the if drop frame is used when adding new timecodes" msgstr "\"Drop frame\" Flag für neu hinzugefügte Timecodes" #: plugins/videofilters/fv_tctweak.c:118 msgid "Set the start hours used when adding new timecodes" msgstr "Setze die Startstunden der hinzugefügten Timecodes" #: plugins/videofilters/fv_tctweak.c:127 msgid "Set the start minutes used when adding new timecodes" msgstr "Setze die Startminuten der hinzugefügten Timecodes" #: plugins/videofilters/fv_tctweak.c:136 msgid "Set the start seconds used when adding new timecodes" msgstr "Setze die Startsekunden der hinzugefügten Timecodes" #: plugins/videofilters/fv_tctweak.c:145 msgid "Set the start frames used when adding new timecodes" msgstr "Setze die Startframes der hinzugefügten Timecodes" #: plugins/videofilters/fv_tctweak.c:345 msgid "Tweak timecodes" msgstr "Ändere Timecodes" #: plugins/videofilters/fv_tctweak.c:346 msgid "Replace/remove/interpolate timecodes" msgstr "Ersetze/lösche/interpoliere Timecodes" #: plugins/videofilters/fv_interlace.c:86 #, fuzzy msgid "Output field order" msgstr "Ausgabedateien" #: plugins/videofilters/fv_interlace.c:90 #, fuzzy msgid "Top first" msgstr "Oberes Feld zuerst" #: plugins/videofilters/fv_interlace.c:91 #, fuzzy msgid "Bottom first" msgstr "Unteres Feld zuerst" #: plugins/videofilters/fv_interlace.c:246 #, fuzzy msgid "Interlace" msgstr "Deinterlace" #: plugins/videofilters/fv_interlace.c:247 msgid "Interlace video images. Output has half the input framerate." msgstr "" #: plugins/videofilters/fv_colorbalance.c:164 #: plugins/videofilters/fv_oldcolor.c:161 msgid "Red gain" msgstr "Rotverstärkung" #: plugins/videofilters/fv_colorbalance.c:174 #: plugins/videofilters/fv_oldcolor.c:171 msgid "Green gain" msgstr "Grünvertsärkung" #: plugins/videofilters/fv_colorbalance.c:184 #: plugins/videofilters/fv_oldcolor.c:181 msgid "Blue gain" msgstr "Blauverstärkung" #: plugins/videofilters/fv_colorbalance.c:194 msgid "Normalize" msgstr "Normiere" #: plugins/videofilters/fv_colorbalance.c:197 msgid "Normalize for constant luminance." msgstr "Normiere für konstante Helligkeit" #: plugins/videofilters/fv_colorbalance.c:639 msgid "Colorbalance" msgstr "Farbbalance" #: plugins/videofilters/fv_colorbalance.c:640 msgid "" "Apply gain for red, green and blue. RGB formats are processed directly, " "Y'CbCr formats are processed by the colormatrix." msgstr "" "Wähle Verstärkungen für Rot, Grün und Blau. RGB Formate werden direkt " "verarbeitet. Y'CbCr werden mit der Farbmatrix verarbeitet." #: plugins/videofilters/fv_flip.c:70 msgid "Flip horizontally" msgstr "Horizontal spiegeln" #: plugins/videofilters/fv_flip.c:76 msgid "Flip vertically" msgstr "Vertikal spiegeln" #: plugins/videofilters/fv_flip.c:180 msgid "Flip image" msgstr "Spiegeln" #: plugins/videofilters/fv_flip.c:181 msgid "Flip video images horizontally and/or vertically" msgstr "Spiegele Videobilder horizontal und/oder vertikal" #: plugins/videofilters/fv_framerate.c:162 #, fuzzy msgid "Force framerate" msgstr "Bildwiederholrate" #: plugins/videofilters/fv_framerate.c:163 #, fuzzy msgid "" "Forces a framerate as input for the next filter. Its mainly used for testing." msgstr "" "Erzwingt ein Pixelformat als Eingabe für das nächste Filter. Wird " "überwiegend zum Testen benutzt." #: plugins/videofilters/fv_oldcolor.c:128 msgid "Style" msgstr "Stil" #: plugins/videofilters/fv_oldcolor.c:347 msgid "Old color" msgstr "Alte Farben" #: plugins/videofilters/fv_oldcolor.c:348 msgid "Simulate old color- and B/W movies" msgstr "Simuliere alte Farb- und Schwarzweißfilme" #: plugins/videofilters/fv_colormatrix_rgb.c:94 msgid "Red" msgstr "Rot" #: plugins/videofilters/fv_colormatrix_rgb.c:100 msgid "Red -> Red" msgstr "Rot -> Rot" #: plugins/videofilters/fv_colormatrix_rgb.c:110 msgid "Green -> Red" msgstr "Grün -> Rot" #: plugins/videofilters/fv_colormatrix_rgb.c:120 msgid "Blue -> Red" msgstr "Blau -> Red" #: plugins/videofilters/fv_colormatrix_rgb.c:130 msgid "Alpha -> Red" msgstr "Transparenz -> Rot" #: plugins/videofilters/fv_colormatrix_rgb.c:140 msgid "Red offset" msgstr "Rot Offset" #: plugins/videofilters/fv_colormatrix_rgb.c:152 msgid "Green" msgstr "Grün" #: plugins/videofilters/fv_colormatrix_rgb.c:158 msgid "Red -> Green" msgstr "Rot -> Grün" #: plugins/videofilters/fv_colormatrix_rgb.c:168 msgid "Green -> Green" msgstr "Grün -> Grün" #: plugins/videofilters/fv_colormatrix_rgb.c:178 msgid "Blue -> Green" msgstr "Blau -> Grün" #: plugins/videofilters/fv_colormatrix_rgb.c:188 msgid "Alpha -> Green" msgstr "Transparenz -> Grün" #: plugins/videofilters/fv_colormatrix_rgb.c:198 msgid "Green offset" msgstr "Grün Offset" #: plugins/videofilters/fv_colormatrix_rgb.c:210 msgid "Blue" msgstr "Blau" #: plugins/videofilters/fv_colormatrix_rgb.c:216 msgid "Red -> Blue" msgstr "Rot -> Blau" #: plugins/videofilters/fv_colormatrix_rgb.c:226 msgid "Green -> Blue" msgstr "Grün -> Blau" #: plugins/videofilters/fv_colormatrix_rgb.c:236 msgid "Blue -> Blue" msgstr "Blau -> Blau" #: plugins/videofilters/fv_colormatrix_rgb.c:246 msgid "Alpha -> Blue" msgstr "Transparenz -> Blau" #: plugins/videofilters/fv_colormatrix_rgb.c:256 msgid "Blue offset" msgstr "Blau Offset" #: plugins/videofilters/fv_colormatrix_rgb.c:274 msgid "Red -> Alpha" msgstr "Rot -> Transparenz" #: plugins/videofilters/fv_colormatrix_rgb.c:284 msgid "Green -> Alpha" msgstr "Grün -> Transparenz" #: plugins/videofilters/fv_colormatrix_rgb.c:294 msgid "Blue -> Alpha" msgstr "Blau -> Transparenz" #: plugins/videofilters/fv_colormatrix_rgb.c:454 msgid "RGB Colormatrix" msgstr "RGB Farbmatrix" #: plugins/videofilters/fv_colormatrix_rgb.c:455 msgid "" "Generic colormatrix (RGBA). You pass the coefficients in RGB(A) coordinates, " "but the processing will work in Y'CbCr(A) as well." msgstr "" "Allgemeine Farbmatrix (RGBA). Du gibst die Koeffizienten in RGB(A) " "Koordinaten an, die Verarbeitung funktioniert aber auch in Y'CbCr(A)." #: plugins/videofilters/fv_decimate.c:147 msgid "Block threshold" msgstr "Blockschwelle" #: plugins/videofilters/fv_decimate.c:153 msgid "" "Specifies how much a block may differ from the last non-skipped block. 0 " "means identical blocks, 1 means completely different blocks. Note that the " "meaning of \"completely different\" depends on the colorspace." msgstr "" "Gib an, um wieviel ein Block sich vom letzten nicht-weggelassenen Block " "unterscheiden darf. 0 heißt identische Blöcke, 1 heißt völlig verschiedene " "Blöcke. Beachte, daß die Bedeutung von \"völlig verschieden\" vom Farbraum " "abhängt." #: plugins/videofilters/fv_decimate.c:157 msgid "Total threshold" msgstr "Gesamtschwelle" #: plugins/videofilters/fv_decimate.c:163 msgid "" "Specifies how much a frame may differ from the last non-skipped frame. 0 " "means identical frames, 1 means completely different frames. Note that the " "meaning of \"completely different\" depends on the colorspace." msgstr "" "Gib an, um wieviel ein Bild sich vom letzten nicht-weggelassenen Bild " "unterscheiden darf. 0 heißt identische Bilder, 1 heißt völlig verschiedene " "Bilder. Beachte, daß die Bedeutung von \\\"völlig verschieden\\\" vom " "Farbraum abhängt." #: plugins/videofilters/fv_decimate.c:167 msgid "Maximum skipped frames" msgstr "Maximal übersprungene Bilder" #: plugins/videofilters/fv_decimate.c:173 msgid "Maximum number of consecutive skipped frames" msgstr "Maximalzahl der hintereinander übersprungenen Bilder" #: plugins/videofilters/fv_decimate.c:177 msgid "Report results" msgstr "Berichte Ergebnis" #: plugins/videofilters/fv_decimate.c:180 msgid "Log reports about skipped frames" msgstr "Sende Berichte über weggelassene Bilder" #: plugins/videofilters/fv_decimate.c:477 #, c-format msgid "Skipped %d frames" msgstr "%d Bilder übersprungen" #: plugins/videofilters/fv_decimate.c:487 msgid "Decimate" msgstr "Dezimieren" #: plugins/videofilters/fv_decimate.c:488 msgid "Skip almost identical frames" msgstr "Überspringe fast gleiche Bilder" #: plugins/videofilters/fv_blur.c:235 msgid "Gauss" msgstr "Gauß" #: plugins/videofilters/fv_blur.c:236 include/gmerlin/bggavl.h:658 msgid "Triangular" msgstr "Dreieck" #: plugins/videofilters/fv_blur.c:237 include/gmerlin/bggavl.h:657 msgid "Rectangular" msgstr "Rechteck" #: plugins/videofilters/fv_blur.c:242 msgid "Horizontal radius" msgstr "Horizontaler Radius" #: plugins/videofilters/fv_blur.c:252 msgid "Vertical radius" msgstr "Vertikaler Radius" #: plugins/videofilters/fv_blur.c:407 msgid "Blur" msgstr "Weichzeichnen" #: plugins/videofilters/fv_blur.c:408 msgid "Blur filter based on gavl. Supports triangular, box and gauss blur." msgstr "" "Weichzeichner basierend auf gavl. Unterstützt Dreieck, Rechteck und Gauß." #: plugins/videofilters/fv_invert_rgb.c:103 msgid "Invert red" msgstr "Invertiere rot" #: plugins/videofilters/fv_invert_rgb.c:110 msgid "Invert green" msgstr "Invertiere grün" #: plugins/videofilters/fv_invert_rgb.c:117 msgid "Invert blue" msgstr "Invertiere blau" #: plugins/videofilters/fv_invert_rgb.c:124 msgid "Invert alpha" msgstr "Invertiere Transparenz" #: plugins/videofilters/fv_invert_rgb.c:563 msgid "Invert RGBA" msgstr "Invertiere RGBA" #: plugins/videofilters/fv_invert_rgb.c:564 msgid "" "Invert single color channels. RGB(A) formats are processed directly, Y'CbCr" "(A) formats are processed with the colormatrix." msgstr "" "Invertiere einzelne Farbkanäle. RGB(A) Formate werden direkt verarbeitet. " "Y'CbCr(A) werden mit der Farbmatrix verarbeitet." #: plugins/videofilters/fv_bitshift.c:67 msgid "Bits to shift" msgstr "" #: plugins/videofilters/fv_bitshift.c:184 #, fuzzy msgid "Shift image" msgstr "Standbild\n" #: plugins/videofilters/fv_bitshift.c:185 msgid "Upshift 16 bit images, where only some lower bits are used" msgstr "" #: plugins/videofilters/fv_equalizer.c:446 msgid "Saturation" msgstr "Sättigung" #: plugins/videofilters/fv_equalizer.c:758 msgid "Equalizer" msgstr "Equalizer" #: plugins/videofilters/fv_equalizer.c:759 msgid "" "Control hue, saturation, contrast and brightness. For Y'CbCr, it uses " "routines based on the vf_eq and vf_hue filters from the MPlayer project. For " "RGB formats, it uses the colormatrix." msgstr "" "Kontrolliert Ton, Sättigung, Kontrast und Helligkeit. Für Y'CbCr benutzt es " "Routinen basierend auf die fv_eq un d vf_hue Filters vom MPlayer Projekt. " "Für RGB Formate wird die Farbmatrix benutzt." #: plugins/gavl/ir_gavl.c:124 #, fuzzy msgid "GAVL image reader" msgstr "Bildimporteur" #: plugins/gavl/ir_gavl.c:125 #, fuzzy msgid "Reader for GAVL images" msgstr "Importeur für TGA bilder" #: plugins/gavl/iw_gavl.c:115 #, fuzzy msgid "gavl image writer" msgstr "Bildexporteur" #: plugins/gavl/iw_gavl.c:116 #, fuzzy msgid "Writer for GAVL images" msgstr "Exporteur für TGA Bilder" #: plugins/mikmod/i_mikmod.c:125 msgid "Cannot find mikmod executable" msgstr "Kann das mikmod programm nicht finden" #: plugins/mikmod/i_mikmod.c:204 msgid "Unrecognized fileformat" msgstr "Unbekanntens Dateiformat" #: plugins/mikmod/i_mikmod.c:254 lib/gtk/infowindow.c:711 #: lib/gtk/infowindow.c:730 lib/gtk/infowindow.c:749 msgid "Output format" msgstr "Ausgabeformat" #: plugins/mikmod/i_mikmod.c:257 msgid "Mono 8bit" msgstr "Mono 8bit" #: plugins/mikmod/i_mikmod.c:257 msgid "Stereo 8bit" msgstr "Stereo 8bit" #: plugins/mikmod/i_mikmod.c:257 msgid "Mono 16bit" msgstr "Mono 16bit" #: plugins/mikmod/i_mikmod.c:257 msgid "Stereo 16bit" msgstr "Stereo 16bit" #: plugins/mikmod/i_mikmod.c:263 include/gmerlin/bggavl.h:531 #: include/gmerlin/bggavl.h:537 msgid "Samplerate" msgstr "Abtastrate" #: plugins/mikmod/i_mikmod.c:272 msgid "Look for hidden patterns in module" msgstr "Such nach versteckten Mustern im Modul" #: plugins/mikmod/i_mikmod.c:278 msgid "Use surround mixing" msgstr "Benutze Surround-Mixing" #: plugins/mikmod/i_mikmod.c:284 msgid "Force volume fade at the end of module" msgstr "Erzwinge Ausblenden am Modulende" #: plugins/mikmod/i_mikmod.c:290 msgid "Use interpolate mixing" msgstr "Interpolierendes Mischen" #: plugins/mikmod/i_mikmod.c:345 msgid "mikmod input plugin" msgstr "Mikmod Quellplugin" #: plugins/mikmod/i_mikmod.c:346 msgid "Simple wrapper, which calls the mikmod program" msgstr "Einfacger Wrapper der das mikmod Programm aufruft." #: plugins/cdaudio/cdparanoia.c:187 msgid "Cdparanoia" msgstr "Cdparanoia" #: plugins/cdaudio/cdparanoia.c:204 msgid "Maximum retries" msgstr "Maximale Wiederholungen" #: plugins/cdaudio/cdparanoia.c:209 msgid "Maximum number of retries, 0 = infinite" msgstr "Maximale Zahl von Widerholungen, 0 heißt unendlich." #: plugins/cdaudio/cdparanoia.c:213 msgid "Disable paranoia" msgstr "Schalte Paranoia aus." #: plugins/cdaudio/cdparanoia.c:216 msgid "Disable all data verification and correction features." msgstr "Schalte alle Datenverizizierungs- und Korrekturfeatures aus." #: plugins/cdaudio/cdparanoia.c:220 msgid "Disable extra paranoia" msgstr "Schalte extra Paranoia aus" #: plugins/cdaudio/cdparanoia.c:223 msgid "" "Disables intra-read data verification; only overlap checking atread " "boundaries is performed. It can wedge if errors occur in the attempted " "overlap area. Not recommended." msgstr "" "Schaltet Leseverifizierung während des Lesens aus, nur Überlappprüfungen an " "Lesegrenzen werden durchgeführt. Kann hängenbleiben wenn Fehler im " "Überlappbereich auftreten. Nicht empfohlen." #: plugins/cdaudio/cdaudio.c:168 #, c-format msgid "cdio_close_tray failed: %s" msgstr "cdio_close_tray fehlgeschlagen: %s" #: plugins/cdaudio/cdaudio.c:171 msgid "cdio_close_tray failed" msgstr "cdio_close_tray fehlgeschlagen" #: plugins/cdaudio/cdaudio.c:250 #, c-format msgid "DVD Writer (%s)" msgstr "DVD Brenner (%s)" #: plugins/cdaudio/cdaudio.c:254 #, c-format msgid "CD Writer (%s)" msgstr "CD Brenner (%s)" #: plugins/cdaudio/cdaudio.c:258 #, c-format msgid "DVD Drive (%s)" msgstr "DVD Laufwerk (%s)" #: plugins/cdaudio/cdaudio.c:260 #, c-format msgid "CD-ROM Drive (%s)" msgstr "CD-ROM Laufwerk (%s)" #: plugins/cdaudio/i_cdaudio.c:243 msgid "Got metadata from CD-Text" msgstr "Metadaten von CD-Text erhalten" #: plugins/cdaudio/i_cdaudio.c:260 #, c-format msgid "Got metadata from gmerlin cache (%s)" msgstr "Metadaten vom Gmerlin cache erhalten (%s)" #: plugins/cdaudio/i_cdaudio.c:276 #, c-format msgid "Got metadata from musicbrainz (%s)" msgstr "Metadaten von Musicbrainz erhalten (%s)" #: plugins/cdaudio/i_cdaudio.c:295 #, c-format msgid "Got metadata from CDDB (%s)" msgstr "Metadaten von CDDB erhalten (%s)" #: plugins/cdaudio/i_cdaudio.c:321 #, c-format msgid "Audio CD track %02d" msgstr "Audio CD track %02d" #: plugins/cdaudio/i_cdaudio.c:546 msgid "Trackname template" msgstr "Trackname Maske" #: plugins/cdaudio/i_cdaudio.c:549 msgid "" "Template for track name generation from metadata\n" "%p: Artist\n" "%a: Album\n" "%g: Genre\n" "%t: Track name\n" "%n: Track number (d = number of digits, 1-9)\n" "%y: Year\n" "%c: Comment" msgstr "" "Maske zum Ergeugen der Tracknamen von Metadaten\n" "%p: Künstler\n" "%a: Album\n" "%g: Genre\n" "%t: Trackname\n" "%n: Tracknummer (d = Anzahl der Stellen, 1-9)\n" "%y: Jahr\n" "%c: Kommentar" #: plugins/cdaudio/i_cdaudio.c:560 msgid "Use CD-Text" msgstr "Benutze CD-Text" #: plugins/cdaudio/i_cdaudio.c:563 msgid "Try to get CD metadata from CD-Text" msgstr "Versuche, CD Metadaten von CD-Text zu erhalten" #: plugins/cdaudio/i_cdaudio.c:567 msgid "Use locally saved metadata" msgstr "Benutze lokal gespeicherte Metadaten" #: plugins/cdaudio/i_cdaudio.c:570 msgid "" "Whenever we obtain CD metadata from the internet, we save them into $HOME/." "gmerlin/cdaudio_metadata. If you got wrong metadata for a CD, disabling this " "option will retrieve the metadata again and overwrite the saved data." msgstr "" "Immer wenn wir CD Metadaten aus dem Internet bekommen, speichern wir diese " "in $HOME/.gmerlin/cdaudio_metadata. Wenn Du falsche Metadaten für eine CD " "bekommen hast, kannst Du diese Option abschalten und die Metadaten werden " "erneut geholt und die gespeicherten überschrieben." #: plugins/cdaudio/i_cdaudio.c:577 msgid "Musicbrainz" msgstr "Musicbrainz" #: plugins/cdaudio/i_cdaudio.c:582 msgid "Use Musicbrainz" msgstr "Benutze Musicbrainz" #: plugins/cdaudio/i_cdaudio.c:594 plugins/cdaudio/i_cdaudio.c:636 #: lib/lcdproc.c:118 msgid "Port" msgstr "Port" #: plugins/cdaudio/i_cdaudio.c:602 plugins/cdaudio/i_cdaudio.c:650 msgid "Proxy" msgstr "Proxy" #: plugins/cdaudio/i_cdaudio.c:604 plugins/cdaudio/i_cdaudio.c:652 msgid "Proxy server (leave empty for direct connection)" msgstr "Proxy server (leerlassen für Direktverbindung)" #: plugins/cdaudio/i_cdaudio.c:608 plugins/cdaudio/i_cdaudio.c:613 #: plugins/cdaudio/i_cdaudio.c:656 plugins/cdaudio/i_cdaudio.c:661 msgid "Proxy port" msgstr "Proxy port" #: plugins/cdaudio/i_cdaudio.c:619 msgid "Cddb" msgstr "Cddb" #: plugins/cdaudio/i_cdaudio.c:624 msgid "Use Cddb" msgstr "Benutze Cddb" #: plugins/cdaudio/i_cdaudio.c:644 msgid "Path" msgstr "Pfad" #: plugins/cdaudio/i_cdaudio.c:665 msgid "Proxy username" msgstr "Proxy Benutzername" #: plugins/cdaudio/i_cdaudio.c:667 msgid "" "User name for proxy (leave empty for poxies, which don't require " "authentication)" msgstr "" "Benutzername für den Proxy. Leerlassen, wenn der Proxy keine " "Authentifizierung erfordert." #: plugins/cdaudio/i_cdaudio.c:671 msgid "Proxy password" msgstr "Proxy Passwort" #: plugins/cdaudio/i_cdaudio.c:673 msgid "Password for proxy" msgstr "Password für den Proxy" #: plugins/cdaudio/i_cdaudio.c:677 msgid "Timeout" msgstr "Maximalzeit" #: plugins/cdaudio/i_cdaudio.c:682 msgid "Timeout (in seconds) for connections to the CDDB server" msgstr "Maximale Verbindungszeit (in Sekunden) für CDDB Server" #: plugins/cdaudio/i_cdaudio.c:766 #, c-format msgid "Ejecting disk failed: %s" msgstr "Disk Auswerfen fehlgeschlagen: %s" #: plugins/cdaudio/i_cdaudio.c:768 msgid "Ejecting disk failed" msgstr "Disk Auswerfen fehlgeschlagen" #: plugins/cdaudio/i_cdaudio.c:792 msgid "Audio CD player/ripper" msgstr "Audio CD Spieler/Ripper" #: plugins/cdaudio/i_cdaudio.c:793 msgid "" "Plugin for audio CDs. Supports both playing with direct connection from the " "CD-drive to the souncard and ripping with cdparanoia. Metadata are obtained " "from Musicbrainz, freedb or CD-text. Metadata are cached in $HOME/.gmerlin/" "cdaudio_metadata." msgstr "" "Plugin für Musik-CDs. Unterstützt Abspielen mit Direktverbindung vom " "Laufwerk zur Soundkarte und Auslesen mit cdparanoia. Metadaten werden von " "Musicbrainz, freedb oder CD-Text geholt. Metadaten werden in $HOME/gmerlin/" "cdaudio_metadata zwischengespeichert." #: plugins/png/e_spumux.c:224 plugins/png/iw_png.c:96 msgid "Compression level" msgstr "Kompressionslevel" #: plugins/png/e_spumux.c:246 msgid "spumux overlay exporter" msgstr "Spumux Overlay Exporteur" #: plugins/png/e_spumux.c:247 msgid "" "Exports overlay subtitles into the format used by spumux (http://dvdauthor." "sourceforge.net)" msgstr "" "Exportiert Overlay Untertitel im Format von spumux (http://dvdauthor." "sourceforge.net)" #: plugins/png/ir_png.c:311 msgid "PNG reader" msgstr "PNG Importeur" #: plugins/png/ir_png.c:312 msgid "Reader for PNG images" msgstr "Importeur für PNG Bilder" #: plugins/png/iw_png.c:104 msgid "Bits per channel" msgstr "Bits pro Kanal" #: plugins/png/iw_png.c:108 msgid "" "If you select auto, the depth will be chosen according to the input format" msgstr "" "Wenn Du \"Auto\" wählt, wird die Tiefe anhand des Quellenformats gewählt." #: plugins/png/iw_png.c:131 msgid "PNG writer" msgstr "PNG Exporteur" #: plugins/png/iw_png.c:132 msgid "Writer for PNG images" msgstr "Exporteur für PNG Bilder" #: plugins/v4l2/i_v4l2.c:108 plugins/v4l2/i_v4l2.c:153 #, fuzzy msgid "Out of memory" msgstr "Draußen" #: plugins/v4l2/i_v4l2.c:131 plugins/v4l2/ov_v4l2.c:254 #, fuzzy, c-format msgid "%s does not support memory mapping" msgstr "Plugin %s unterstützt keine eingebetteten Fenster" #: plugins/v4l2/i_v4l2.c:137 plugins/v4l2/ov_v4l2.c:260 #, fuzzy, c-format msgid "VIDIOC_REQBUFS failed: %s" msgstr "VIDIOCGMBUF fehlgeschlagen: %s" #: plugins/v4l2/i_v4l2.c:144 plugins/v4l2/ov_v4l2.c:267 #, c-format msgid "Insufficient buffer memory on %s" msgstr "" #: plugins/v4l2/i_v4l2.c:169 plugins/v4l2/ov_v4l2.c:284 #, fuzzy, c-format msgid "VIDIOC_QUERYBUF failed: %s" msgstr "VIDIOCGPICT fehlgeschlagen: %s" #: plugins/v4l2/i_v4l2.c:195 plugins/v4l2/i_v4l2.c:617 #: plugins/v4l2/ov_v4l2.c:359 #, fuzzy, c-format msgid "VIDIOC_QBUF failed: %s" msgstr "VIDIOCGMBUF fehlgeschlagen: %s" #: plugins/v4l2/i_v4l2.c:206 plugins/v4l2/ov_v4l2.c:372 #, fuzzy, c-format msgid "VIDIOC_STREAMON failed: %s" msgstr "VIDIOCSPICT fehlgeschlagen: %s" #: plugins/v4l2/i_v4l2.c:229 plugins/v4l2/ov_v4l2.c:192 #, fuzzy, c-format msgid "VIDIOC_ENUM_FMT failed: %s" msgstr "VIDIOCGPICT fehlgeschlagen: %s" #: plugins/v4l2/i_v4l2.c:261 plugins/v4l2/i_v4l2.c:370 #: plugins/v4l2/i_v4l2.c:400 #, fuzzy, c-format msgid "VIDIOC_G_FMT failed: %s" msgstr "VIDIOCGPICT fehlgeschlagen: %s" #: plugins/v4l2/i_v4l2.c:301 plugins/v4l2/ov_v4l2.c:453 #, fuzzy, c-format msgid "Device name: %s" msgstr "" "\n" "Lizenz: %s" #: plugins/v4l2/i_v4l2.c:305 plugins/v4l2/ov_v4l2.c:458 msgid "Trying mmap i/o" msgstr "" #: plugins/v4l2/i_v4l2.c:310 msgid "Trying read i/o" msgstr "" #: plugins/v4l2/i_v4l2.c:348 msgid "Trying v4lconvert" msgstr "" #: plugins/v4l2/i_v4l2.c:356 #, fuzzy msgid "Got no supported pixelformat" msgstr "Nicht unterstütztes Zahlenformat" #: plugins/v4l2/i_v4l2.c:383 plugins/v4l2/ov_v4l2.c:485 #, fuzzy, c-format msgid "VIDIOC_S_FMT failed: %s" msgstr "VIDIOCSPICT fehlgeschlagen: %s" #: plugins/v4l2/i_v4l2.c:457 plugins/v4l2/ov_v4l2.c:322 #, fuzzy, c-format msgid "VIDIOC_STREAMOFF failed: %s" msgstr "VIDIOCSPICT fehlgeschlagen: %s" #: plugins/v4l2/i_v4l2.c:537 plugins/v4l2/i_v4l2.c:549 #, fuzzy, c-format msgid "read failed: %s" msgstr "mmap fehlgeschlagen: %s" #: plugins/v4l2/i_v4l2.c:579 plugins/v4l2/ov_v4l2.c:539 #, fuzzy, c-format msgid "VIDIOC_DQBUF failed: %s" msgstr "VIDIOCGMBUF fehlgeschlagen: %s" #: plugins/v4l2/i_v4l2.c:651 #, fuzzy, c-format msgid "Select failed: %s" msgstr "Verbindung fehlgeschlagen: %s" #: plugins/v4l2/i_v4l2.c:657 #, fuzzy msgid "Select timeout" msgstr "Wähle eine Datei" #: plugins/v4l2/i_v4l2.c:716 plugins/v4l2/ov_v4l2.c:105 #, fuzzy msgid "V4L2 Device" msgstr "V4L Gerät" #: plugins/v4l2/i_v4l2.c:722 #, fuzzy msgid "Force read" msgstr "Bildwiederholrate" #: plugins/v4l2/i_v4l2.c:725 plugins/v4l2/ov_v4l2.c:114 #, fuzzy msgid "Don't use memory mapping" msgstr "Plugin %s unterstützt keine eingebetteten Fenster" #: plugins/v4l2/i_v4l2.c:892 plugins/v4l2/ov_v4l2.c:613 #, fuzzy msgid "V4L2" msgstr "V4L" #: plugins/v4l2/i_v4l2.c:893 #, fuzzy msgid "" "video4linux 2 recording plugin. Supports only video and no tuner decives." msgstr "" "video4linux Aufnahmeplugin. Unterstützt nur Video und keine Tunergeräte." #: plugins/v4l2/convert.c:84 #, fuzzy msgid "Initializing libv4lconvert failed" msgstr "Alsa Initialisierung fehlgeschlagen" #: plugins/v4l2/convert.c:94 msgid "Initializing libv4lconvert failed (resolution not directly supported)" msgstr "" #: plugins/v4l2/ov_v4l2.c:111 #, fuzzy msgid "Force write" msgstr "Bildwiederholrate" #: plugins/v4l2/ov_v4l2.c:341 #, fuzzy, c-format msgid "write failed: %s" msgstr "mmap fehlgeschlagen: %s" #: plugins/v4l2/ov_v4l2.c:431 msgid "Forcing square pixels" msgstr "" #: plugins/v4l2/ov_v4l2.c:463 msgid "Trying write i/o" msgstr "" #: plugins/v4l2/ov_v4l2.c:475 #, fuzzy, c-format msgid "Using %s" msgstr "Bereinige %s" #: plugins/v4l2/ov_v4l2.c:614 #, fuzzy msgid "V4L2 output driver" msgstr "OSS Ausgabetreiber" #: plugins/v4l2/v4l2_common.c:378 #, fuzzy msgid "VIDIOC_S_CTRL Failed" msgstr "VIDIOCSPICT fehlgeschlagen: %s" #: plugins/v4l2/v4l2_common.c:414 #, fuzzy msgid "VIDIOC_G_CTRL Failed" msgstr "VIDIOCGPICT fehlgeschlagen: %s" #: plugins/v4l2/v4l2_common.c:431 apps/camelot/vloopback.c:494 #, fuzzy, c-format msgid "Opening %s failed: %s" msgstr "Disk Auswerfen fehlgeschlagen: %s" #: plugins/v4l2/v4l2_common.c:440 #, fuzzy, c-format msgid "%s is no V4L2 device" msgstr "V4L Gerät" #: plugins/v4l2/v4l2_common.c:446 #, fuzzy, c-format msgid "VIDIOC_QUERYCAP failed: %s" msgstr "VIDIOCGPICT fehlgeschlagen: %s" #: plugins/v4l2/v4l2_common.c:454 #, fuzzy, c-format msgid "%s is no video %s device" msgstr "V4L Gerät" #: plugins/lqt/i_lqt.c:46 apps/plugincfg/gmerlin_plugincfg.c:281 #: apps/transcoder/trackdialog.c:217 apps/recorder/recorder_window.c:722 #: lib/pluginregistry.c:2125 lib/pluginregistry.c:2609 lib/player_audio.c:181 #: lib/gtk/infowindow.c:697 msgid "Audio" msgstr "Audio" #: plugins/lqt/i_lqt.c:52 msgid "Audio Codecs" msgstr "Audio Codecs" #: plugins/lqt/i_lqt.c:53 msgid "Sort and configure audio codecs" msgstr "Sortiere und konfiguriere Audio Codecs" #: plugins/lqt/i_lqt.c:57 apps/transcoder/trackdialog.c:288 #: apps/recorder/recorder_window.c:740 lib/player_video.c:134 #: lib/pluginregistry.c:2136 lib/pluginregistry.c:2616 #: lib/gtk/infowindow.c:716 msgid "Video" msgstr "Video" #: plugins/lqt/i_lqt.c:63 msgid "Video Codecs" msgstr "Video Codecs" #: plugins/lqt/i_lqt.c:64 msgid "Sort and configure video codecs" msgstr "Sortiere und konfiguriere Video Codecs" #: plugins/lqt/i_lqt.c:281 msgid "More than one chapter track found, using first one" msgstr "Mehr als ein Kapiteltrack gefunden, nehme ersten." #: plugins/lqt/i_lqt.c:572 msgid "libquicktime input plugin" msgstr "Libquicktime Quellenplugin" #: plugins/lqt/i_lqt.c:573 msgid "Input plugin based on libquicktime" msgstr "Quellenplugin basierend auf libquicktime" #: plugins/lqt/lqt_common.c:94 #, c-format msgid "%s Compatible with" msgstr "%s kompatibel mit" #: plugins/lqt/e_lqt.c:41 msgid "Codec" msgstr "Codec" #: plugins/lqt/e_lqt.c:183 #, c-format msgid "Cannot open file %s" msgstr "Kann Datei %s nicht öffnen" #: plugins/lqt/e_lqt.c:478 #, c-format msgid "Audio codec %s cannot be written to AVI files" msgstr "" #: plugins/lqt/e_lqt.c:542 #, fuzzy msgid "AVI subtitles not supported" msgstr "PAM format nicht unterstützt" #: plugins/lqt/e_lqt.c:590 #, c-format msgid "Omitting chapter %d: time (%f) > duration (%f)" msgstr "Lasse Kapitel %d weg: Startzeit (%f) > Dauer (%f)" #: plugins/lqt/e_lqt.c:629 msgid "Making streamable...." msgstr "Mache streamfähig..." #: plugins/lqt/e_lqt.c:631 msgid "Making streamable....done" msgstr "Mache streamfähig...fertig" #: plugins/lqt/e_lqt.c:706 msgid "Quicktime" msgstr "Quicktime" #: plugins/lqt/e_lqt.c:706 msgid "AVI" msgstr "AVI" #: plugins/lqt/e_lqt.c:706 msgid "AVI (Opendml)" msgstr "AVI (Opendml)" #: plugins/lqt/e_lqt.c:707 msgid "MP4" msgstr "MP4" #: plugins/lqt/e_lqt.c:707 msgid "M4A" msgstr "M4A" #: plugins/lqt/e_lqt.c:707 msgid "3GP" msgstr "3GP" #: plugins/lqt/e_lqt.c:712 msgid "Make streamable" msgstr "Make streamable" #: plugins/lqt/e_lqt.c:714 msgid "Make the file streamable afterwards (uses twice the diskspace)" msgstr "Mache die Datei streamfähig (benötigt doppelten Festplattenplatz)" #: plugins/lqt/e_lqt.c:718 msgid "Maximum RIFF size" msgstr "Maximum RIFF size" #: plugins/lqt/e_lqt.c:723 msgid "" "Maximum RIFF size (in MB) for OpenDML AVIs. The default (1GB) is reasonable " "and should only be changed by people who know what they do." msgstr "" "Maximale RIFF-Größe (in MB) für OpenDML AVIs. Die Voreinstellung (1GB) ist " "vernünftig und sollte nur von denen geändert werden, die wissen was sie tun." #: plugins/lqt/e_lqt.c:914 msgid "Text box (top)" msgstr "Text Box (open)" #: plugins/lqt/e_lqt.c:921 msgid "Text box (left)" msgstr "Text box (links)" #: plugins/lqt/e_lqt.c:928 msgid "Text box (bottom)" msgstr "Text box (unten)" #: plugins/lqt/e_lqt.c:935 msgid "Text box (right)" msgstr "Text box (rechts)" #: plugins/lqt/e_lqt.c:999 msgid "Quicktime encoder" msgstr "Quicktime Enkoder" #: plugins/lqt/e_lqt.c:1000 msgid "" "Encoder based on libquicktime (http://libquicktime.sourceforge.net) Writes " "Quicktime, AVI (optionally ODML), MP4, M4A and 3GPP. Supported codecs range " "from high quality uncompressed formats for professional applications to " "consumer level formats like H.264/AVC, AAC, MP3, Divx compatible etc. Also " "supported are chapters and text subtitles" msgstr "" "Enkoder basierend auf libquicktime (http://libquicktime.sourceforge.net). " "Schreibt Quicktime, AVI (optional OpenDML), MP4, M4A und 3GPP. Unterstützte " "Codecs reichen von hochqualitativem unkomprimierten Formaten für " "professionelle Anwendungen bis to Endverbraucherformaten wie H.264/AVC, AAC, " "MP3, Divx compatible usw. Ebenfalls unterstützt werden Kapitel und Text-" "Untertitel." # Kann %s nicht öffnen #: plugins/tiff/iw_tiff.c:101 apps/cmdlineplayer/gmerlin_play.c:543 #: apps/thumbnailer/gmerlin-video-thumbnailer.c:192 #: tests/gmerlin_visualize.c:478 #, c-format msgid "Cannot open %s" msgstr "Kann %s nicht öffnen" #: plugins/tiff/iw_tiff.c:191 msgid "Packbits" msgstr "Packbits" #: plugins/tiff/iw_tiff.c:191 msgid "Deflate" msgstr "Deflate" #: plugins/tiff/iw_tiff.c:191 msgid "JPEG" msgstr "JPEG" #: plugins/tiff/iw_tiff.c:198 msgid "JPEG quality" msgstr "JPEG Qualität" #: plugins/tiff/iw_tiff.c:206 msgid "Deflate compression level" msgstr "Deflate Kompressionslevel" #: plugins/tiff/iw_tiff.c:253 msgid "TIFF writer" msgstr "TIFF Exporteur" #: plugins/tiff/iw_tiff.c:254 msgid "Writer for TIFF images" msgstr "Exporteur für TIFF Bilder" #: plugins/tiff/ir_tiff.c:106 msgid "Seeked beyond buffer." msgstr "Hinter den Puffer gesucht." #: plugins/tiff/ir_tiff.c:616 msgid "Unsupported compression for LOGL/LOGLUV" msgstr "Nicht unterstützte Kompression für LOGL/LOGLUV" #: plugins/tiff/ir_tiff.c:660 plugins/tiff/ir_tiff.c:690 #: plugins/tiff/ir_tiff.c:722 msgid "Unsupported samples per pixel" msgstr "Nicht unterstützte Abtastwerte pro Pixel" #: plugins/tiff/ir_tiff.c:696 #, c-format msgid "Unsupported bits per sample (%d) for UINT" msgstr "Nicht unterstützte Bits pro Abtastwert (%d) für UINT" #: plugins/tiff/ir_tiff.c:703 msgid "Didn't get max sample value" msgstr "Maximaler Abtastwert nicht erhalten." #: plugins/tiff/ir_tiff.c:706 msgid "Didn't get min sample value" msgstr "Minimaler Abtastwert nicht erhalten." #: plugins/tiff/ir_tiff.c:728 #, c-format msgid "Unsupported depth %d for IEEE float" msgstr "Nicht unterstützte Tiefe %d für IEEE Fließkomma." #: plugins/tiff/ir_tiff.c:738 msgid "Unsupported sampleformat" msgstr "Nicht unterstütztes Zahlenformat" #: plugins/tiff/ir_tiff.c:743 #, c-format msgid "Unknown sampleformat %d" msgstr "Unbekanntes Zahlenformat: %d" #: plugins/tiff/ir_tiff.c:869 msgid "BUG!!! convert_func == 0x0" msgstr "BUG!!! convert_func == 0x0" #: plugins/tiff/ir_tiff.c:905 msgid "TIFF reader" msgstr "TIFF Importeur" #: plugins/tiff/ir_tiff.c:906 msgid "Reader for TIFF images" msgstr "Importeur für TIFF Bilder" #: plugins/jpeg/iw_jpeg.c:186 #, c-format msgid "Illegal pixelformat: %s" msgstr "Illegales Pixelformat: %s" #: plugins/jpeg/iw_jpeg.c:273 msgid "Chroma sampling" msgstr "Farbabtastung" #: plugins/jpeg/iw_jpeg.c:325 msgid "JPEG writer" msgstr "JPEG Exporteur" #: plugins/jpeg/iw_jpeg.c:326 msgid "Writer for JPEG images" msgstr "Exporteur für JPEG Bilder" #: plugins/jpeg/ir_jpeg.c:274 msgid "Illegal pixelformat" msgstr "Illegales Pixelformat" #: plugins/jpeg/ir_jpeg.c:295 msgid "JPEG reader" msgstr "JPEG Importeur" #: plugins/jpeg/ir_jpeg.c:296 msgid "Reader for JPEG images" msgstr "Importeur für JPEG-Bilder" #: plugins/wavwrite/e_wav.c:317 msgid "Bits per sample" msgstr "Bits pro Abtastwert" #: plugins/wavwrite/e_wav.c:329 msgid "Write info chunk" msgstr "Schreibe Info Chunk" #: plugins/wavwrite/e_wav.c:472 #, c-format msgid "Cannot open output file: %s" msgstr "Kann Ausgabedatei %s nicht öffnen" #: plugins/wavwrite/e_wav.c:643 msgid "Wave writer" msgstr "Wave Exporteur" #: plugins/wavwrite/e_wav.c:644 msgid "Simple writer for wave files, supports 8, 16, 24 and 32 bit PCM" msgstr "" "Einfacher Exporteur für Wav-Dateien. Unterstützt 8, 16, 24 and 32 bit PCM." #: plugins/edl/i_edl.c:89 msgid "Parser for gmerlin EDLs" msgstr "Parser für gmerlin EDLs" #: plugins/edl/i_edl.c:90 msgid "" "This parses the XML file and exports an EDL, which can be played with the " "builtin EDL decoder." msgstr "" "Dieses Plugin liest eine XML Datei und exportiert eine EDL, die vom " "eingebauten EDL Dekoder gespielt werden kann." #: include/gmerlin/bggavl.h:128 msgid "Conversion Quality" msgstr "Umrechnungsqualität" #: include/gmerlin/bggavl.h:135 msgid "" "Set the conversion quality for format conversions. Lower quality means more " "speed. Values above 3 enable slow high quality calculations." msgstr "" "Setze die Qualität für Formatumrechnungen. Niedrige Qualität heißt höhere " "Geschwindigkeit. Werte über 3 schalten langsame, hochqualitative " "Berechnungen ein." #: include/gmerlin/bggavl.h:142 lib/singlepic.c:76 msgid "Timescale" msgstr "Zeitskala" #: include/gmerlin/bggavl.h:147 msgid "" "Timescale for user defined output framerate (Framerate = timescale / frame " "duration)." msgstr "" "Zeitskala für benutzerdefinierte Bildwiederholfrequenz " "(Bildwiederholfrequenz = Zeitskala / Bilddauer)" #: include/gmerlin/bggavl.h:151 lib/singlepic.c:84 msgid "Frame duration" msgstr "Bilddauer" #: include/gmerlin/bggavl.h:156 msgid "" "Frame duration for user defined output framerate (Framerate = timescale / " "frame duration)." msgstr "" "Zeitskala für benutzerdefinierte Bildwiederholfrequenz " "(Bildwiederholfrequenz = Zeitskala / Bilddauer)" #: include/gmerlin/bggavl.h:172 msgid "23.976 (NTSC encapsulated film rate)" msgstr "23.976 (in NTSC einbetette Filmrate)" #: include/gmerlin/bggavl.h:173 msgid "24 (Standard international cinema film rate)" msgstr "24 (Internationale standard Kinofilmrate)" #: include/gmerlin/bggavl.h:174 msgid "25 (PAL [625/50] video frame rate)" msgstr "25 PAL [625/50] Videorate" #: include/gmerlin/bggavl.h:175 msgid "29.970 (NTSC video frame rate)" msgstr "29.970 (NTSC Videorate)" #: include/gmerlin/bggavl.h:176 msgid "30 (NTSC drop-frame [525/60] video frame rate)" msgstr "30 (NTSC drop-frame [525/60] Videorate)" #: include/gmerlin/bggavl.h:177 msgid "50 (Double frame rate / progressive PAL)" msgstr "50 (doppelte progressive PAL-Rate)" #: include/gmerlin/bggavl.h:178 msgid "59.940 (Double frame rate NTSC)" msgstr "59.940 (doppelte progressive NTSC-Rate)" #: include/gmerlin/bggavl.h:179 msgid "60 (Double frame rate drop-frame NTSC)" msgstr "60 (doppelte drop-frame NTSC-Rate)" #: include/gmerlin/bggavl.h:196 include/gmerlin/bggavl.h:214 msgid "" "Output framerate. For user defined framerate, enter the timescale and frame " "duration below (framerate = timescale / frame duration)." msgstr "" "Ausgegebene Bildwiederholfrequenz. Für benutzerdefinierte " "Bildwiederholfrequenz, gib unten die Zeitskala und Bilddauer an " "(Bildwiederholfrequenz = Zeitskala / Bilddauer)" #: include/gmerlin/bggavl.h:224 msgid "Deinterlace mode" msgstr "Deinterlacemethode" #: include/gmerlin/bggavl.h:229 include/gmerlin/bggavl.h:589 #: apps/transcoder/tracklist.c:1269 lib/gtk/albumwidget.c:1508 #: lib/gtk/albumwidget.c:2906 msgid "Copy" msgstr "Kopieren" #: include/gmerlin/bggavl.h:229 msgid "Scale" msgstr "Skalieren" #: include/gmerlin/bggavl.h:248 msgid "" "Force deinterlacing if you want progressive output and the input format " "pretends to be progressive also." msgstr "" "Erzwinge Deinterlacing wenn Du progressive Ausgabe willst und das " "Quellenformat behauptet, ebenfalls progressiv zu sein." #: include/gmerlin/bggavl.h:267 msgid "Y'CbCr 8 bit" msgstr "" #: include/gmerlin/bggavl.h:267 msgid "Y'CbCrA 8 bit" msgstr "" #: include/gmerlin/bggavl.h:268 #, fuzzy msgid "Y'CbCr 16 bit" msgstr "16 bit" #: include/gmerlin/bggavl.h:268 #, fuzzy msgid "Y'CbCrA 16 bit" msgstr "16 bit" #: include/gmerlin/bggavl.h:269 #, fuzzy msgid "Y'CbCr float" msgstr "Y'CbCr(A) Farbmatrix" #: include/gmerlin/bggavl.h:269 #, fuzzy msgid "Y'CbCrA float" msgstr "Y'CbCr(A) Farbmatrix" #: include/gmerlin/bggavl.h:270 #, fuzzy msgid "RGB 8 bit" msgstr "8 bit" #: include/gmerlin/bggavl.h:270 #, fuzzy msgid "RGBA 8 bit" msgstr "8 bit" #: include/gmerlin/bggavl.h:271 #, fuzzy msgid "RGB 16 bit" msgstr "16 bit" #: include/gmerlin/bggavl.h:271 #, fuzzy msgid "RGBA 16 bit" msgstr "16 bit" #: include/gmerlin/bggavl.h:272 #, fuzzy msgid "RGB float" msgstr "RGB Farbmatrix" #: include/gmerlin/bggavl.h:272 #, fuzzy msgid "RGBA float" msgstr "RGB Farbmatrix" #: include/gmerlin/bggavl.h:274 #, fuzzy msgid "Specify the pixelformat" msgstr "Pixelformat erzwingen" #: include/gmerlin/bggavl.h:290 include/gmerlin/bggavl.h:309 #: lib/x11/x11_window.c:1196 msgid "Nearest" msgstr "Nächstes Pixel" #: include/gmerlin/bggavl.h:291 include/gmerlin/bggavl.h:310 #: lib/x11/x11_window.c:1197 msgid "Bilinear" msgstr "Bilinear" #: include/gmerlin/bggavl.h:292 include/gmerlin/bggavl.h:311 #: lib/x11/x11_window.c:1198 msgid "Quadratic" msgstr "Quadratisch" #: include/gmerlin/bggavl.h:293 include/gmerlin/bggavl.h:312 #: lib/x11/x11_window.c:1199 msgid "Cubic B-Spline" msgstr "Kubisch B-Spline" #: include/gmerlin/bggavl.h:294 lib/x11/x11_window.c:1200 msgid "Cubic Mitchell-Netravali" msgstr "Kubisch Mitchell-Netravali" #: include/gmerlin/bggavl.h:295 lib/x11/x11_window.c:1201 msgid "Cubic Catmull-Rom" msgstr "Kubisch Catmull-Rom" #: include/gmerlin/bggavl.h:296 lib/x11/x11_window.c:1202 msgid "Sinc with Lanczos window" msgstr "sin(x)/x mit Lanczos Fenster" #: include/gmerlin/bggavl.h:325 msgid "Widening" msgstr "Verbreiterung" #: include/gmerlin/bggavl.h:326 msgid "Gaussian preblur" msgstr "Gauß'scher Vorweichzeichner" #: include/gmerlin/bggavl.h:356 msgid "Resample chroma" msgstr "Farbebenen resamplen." #: include/gmerlin/bggavl.h:360 msgid "" "Always perform chroma resampling if chroma subsampling factors or chroma " "placements are different. Usually, this is only done for qualities above 3." msgstr "" "Mache immer Farbenebenen-Resampling, wenn die Farbplazierungen verschieden " "sind. Normalerweise wird dies nur für Qualitätsstufen über 3 gemacht." #: include/gmerlin/bggavl.h:371 msgid "" "Background color to use, when alpha mode above is \"Blend background color\"." msgstr "" "Hintergrundfarbe, die verwendet wird, wenn der Transparenzmodus oben auf " "\"Hintergrundfarbe einblenden\" steht." #: include/gmerlin/bggavl.h:377 msgid "Alpha mode" msgstr "Transparenzmodus" #: include/gmerlin/bggavl.h:382 msgid "Ignore" msgstr "Ignorieren" #: include/gmerlin/bggavl.h:382 msgid "Blend background color" msgstr "Hintergrundfarbe einblenden" #: include/gmerlin/bggavl.h:383 msgid "" "This option is used if the source has an alpha (=transparency) channel, but " "the output supports no transparency. Either, the transparency is ignored, or " "the background color you specify below is blended in." msgstr "" "Diese Option wird verwendet, wenn die Quelle einen Alpha-(=Transparenz)-" "Kanal hat und die Ausgabe keine Transparenz unterstützt. Entweder wird die " "Transparenz ignoriert, oder eine Hintergrundfarbe, die Du unten angibst, " "wird eingeblendet." #: include/gmerlin/bggavl.h:520 #, fuzzy msgid "From source" msgstr "Wie Quelle" #: include/gmerlin/bggavl.h:544 msgid "Fixed samplerate" msgstr "Feste Abtastrate" #: include/gmerlin/bggavl.h:548 msgid "" "If disabled, the output samplerate is taken from the source. If enabled, the " "samplerate you specify below us used." msgstr "" "Wenn ausgeschaltet, wird die Abtastrate für die Ausgabe von der Quelle " "übernommen. Wenn eingeschaltet, wird die Abtastrate, die Du unten angibst, " "genommen." #: include/gmerlin/bggavl.h:555 msgid "Front channels" msgstr "Frontkanäle" #: include/gmerlin/bggavl.h:564 msgid "Rear channels" msgstr "Hinterkanäle" #: include/gmerlin/bggavl.h:573 lib/formats.c:195 msgid "LFE" msgstr "Subwoofer" #: include/gmerlin/bggavl.h:580 msgid "Front to rear mode" msgstr "Vorne nach hinten modus" #: include/gmerlin/bggavl.h:588 msgid "Mute" msgstr "Stumm" #: include/gmerlin/bggavl.h:590 msgid "Diff" msgstr "Differenz" #: include/gmerlin/bggavl.h:592 msgid "" "Mix mode when the output format has rear channels, but the source doesn't." msgstr "Mischmodus wenn die Ausgabe Hinterkanäle hat, aber die Quelle nicht." #: include/gmerlin/bggavl.h:597 msgid "Stereo to mono mode" msgstr "Stereo nach Mono Mode" #: include/gmerlin/bggavl.h:605 msgid "Choose left" msgstr "Nehme Links" #: include/gmerlin/bggavl.h:606 msgid "Choose right" msgstr "Nehme Rechts" #: include/gmerlin/bggavl.h:607 msgid "Mix" msgstr "Mischen" #: include/gmerlin/bggavl.h:609 msgid "Mix mode when downmixing Stereo to Mono." msgstr "Mischmethode zum Heruntermischen von Stereo auf Mono." #: include/gmerlin/bggavl.h:616 msgid "Fixed channel setup" msgstr "Feste Kanalkonfiguration" #: include/gmerlin/bggavl.h:620 msgid "" "If disabled, the output channel configuration is taken from the source. If " "enabled, the setup you specify below us used." msgstr "" "Wenn ausgeschaltet, wird die Kanalkonfiguration von der Quelle übernommen. " "Wenn eingeschaltet, wird die Konfiguration, die Du unten angibst, verwendet." #: include/gmerlin/bggavl.h:633 msgid "8 bit" msgstr "8 bit" #: include/gmerlin/bggavl.h:633 include/gmerlin/bggavl.h:645 msgid "16 bit" msgstr "16 bit" #: include/gmerlin/bggavl.h:633 include/gmerlin/bggavl.h:645 msgid "32 bit" msgstr "32 bit" #: include/gmerlin/bggavl.h:633 include/gmerlin/bggavl.h:645 msgid "Float" msgstr "Fließkomma" #: include/gmerlin/bggavl.h:633 include/gmerlin/bggavl.h:645 msgid "Double" msgstr "Fließkomma (doppelt)" #: include/gmerlin/bggavl.h:634 msgid "" "Force a sampleformat to be used for processing. None means to take the input " "format." msgstr "" "Erzwinge Zahlenformat für die Verarbeitung. Kein(s) bedeutet nehme das " "Quellenformat." #: include/gmerlin/bggavl.h:646 #, fuzzy msgid "Sampleformat to be used for processing." msgstr "" "Erzwinge Zahlenformat für die Verarbeitung. Kein(s) bedeutet nehme das " "Quellenformat." #: include/gmerlin/bggavl.h:652 msgid "Dither mode" msgstr "Dithermodus" #: include/gmerlin/bggavl.h:658 msgid "Shaped" msgstr "Geformt" #: include/gmerlin/bggavl.h:659 msgid "" "Dither mode. Auto means to use the quality level. Subsequent options are " "ordered by increasing quality (i.e. decreasing speed)." msgstr "" "Dithermodus. Automatisch wählt den Modus aufgrund der Qualität. Nachfolgende " "Optionen sind nach aufsteigender Qualität (absteigender Geschwindigkeit) " "geordnet." #: include/gmerlin/bggavl.h:665 msgid "Resample mode" msgstr "Resamplemodus" #: include/gmerlin/bggavl.h:670 msgid "Zero order hold" msgstr "0. Ordnung halten" #: include/gmerlin/bggavl.h:670 msgid "Linear" msgstr "Linear" #: include/gmerlin/bggavl.h:671 msgid "Sinc fast" msgstr "Sinc (schnellste Berechnung)" #: include/gmerlin/bggavl.h:671 msgid "Sinc medium" msgstr "Sinc (mittel)" #: include/gmerlin/bggavl.h:671 msgid "Sinc best" msgstr "Sinc (beste Qualität)" #: include/gmerlin/bggavl.h:672 msgid "" "Resample mode. Auto means to use the quality level. Subsequent options are " "ordered by increasing quality (i.e. decreasing speed)." msgstr "" "Resamplemethode. Automatisch verwendet die Qualitätsstufe. Nachfolgende " "Optionen sind nach aufsteigender Qualität (absteigender Geschwindigkeit) " "geordnet." #: include/gmerlin/bggavl.h:678 #, fuzzy msgid "Number of threads" msgstr "Zahl der Meldungen" #: include/gmerlin/bggavl.h:683 msgid "" "Threads to launch for processing operations. Changing this requires program " "restart" msgstr "" #: include/gmerlin/pluginfuncs.h:40 #, fuzzy msgid "Default timescale" msgstr "Voreingestellte Bildwiederholrate" #: include/gmerlin/pluginfuncs.h:43 msgid "" "For formats, which support only constant framerates, set the default " "timescale here" msgstr "" #: include/gmerlin/pluginfuncs.h:47 #, fuzzy msgid "Default frame duration" msgstr "Voreingestellte Bildwiederholrate" #: include/gmerlin/pluginfuncs.h:50 msgid "" "For formats, which support only constant framerates, set the default frame " "duration here" msgstr "" #: apps/player/skinbrowser.c:315 #, c-format msgid "" "Installing skin from\n" "%s\n" "failed" msgstr "" "Installation des Skins von\n" "%s\n" "fehlgeschlagen." #: apps/player/skinbrowser.c:406 msgid "Skin browser" msgstr "Skinbrowser" #: apps/player/gmerlin.c:305 msgid "Gmerlin player" msgstr "Gmerlin Player" #: apps/player/gmerlin.c:711 msgid "General Options" msgstr "Allgemeine Optionen" #: apps/player/gmerlin.c:717 msgid "Skip error tracks" msgstr "Überspringe fehlerhafte Tracks" #: apps/player/gmerlin.c:720 msgid "If a track cannot be opened, switch to the next one" msgstr "Wenn ein Track nicht geöffnet werden kann, springe zum nächsten." #: apps/player/gmerlin.c:724 msgid "Don't advance" msgstr "Nicht weiterschalten" #: apps/player/gmerlin.c:730 msgid "Shuffle mode" msgstr "Zufallswiedergabe" #: apps/player/gmerlin.c:736 apps/player/mainmenu.c:751 msgid "Off" msgstr "Aus" #: apps/player/gmerlin.c:737 msgid "Current album" msgstr "Aktuelles Album" #: apps/player/gmerlin.c:738 msgid "All open albums" msgstr "Alle offenen Alben" #: apps/player/gmerlin.c:744 msgid "Show tooltips" msgstr "Zeige Tooltips" #: apps/player/main.c:52 msgid "[options] [gmls ...]\n" msgstr "[Optionen] [gmls...]\n" #: apps/player/main.c:53 msgid "Gmerlin GUI Player" msgstr "Gmerlin GUI Spieler" #: apps/player/main.c:58 apps/player/gmerlin_remote.c:567 #: apps/transcoder/main.c:74 apps/transcoder/gmerlin_transcoder_remote.c:179 msgid "Default port for the remote control" msgstr "Voreingestellter Port für die Fernbedienung" #: apps/player/main.c:63 apps/cmdlinerecorder/gmerlin-record.c:321 #: apps/cmdlineplayer/gmerlin_play.c:842 apps/nmjedit/gmerlin-nmjedit.c:174 #: apps/thumbnailer/gmerlin-video-thumbnailer.c:98 tests/fvtest.c:179 msgid "Cache of the plugin registry (shared by all applicatons)" msgstr "" "Zwischenspeicher für die Plugin-Registry (von allen Programmen gemeinsam " "benutzt)" #: apps/player/main.c:65 msgid "" "Used for configuration data. Delete this file if you think you goofed " "something up." msgstr "" "Wird für Konfigurationsdaten benutzt. Lösche diese Datein, wenn Du meinst " "was zerschossen zu haben." #: apps/player/main.c:67 msgid "" "Media tree is saved here. The albums are saved as separate files in the same " "directory." msgstr "" "Mediatree wird hier gespeichert. Alben werden als separate Dateien im " "gleichen Verzeichnis gespeichert" #: apps/player/cfgdialog.c:39 lib/gtk/plugin_single.c:379 msgid "Audio options" msgstr "Audio Optionen" #: apps/player/cfgdialog.c:47 apps/plugincfg/gmerlin_plugincfg.c:399 msgid "Audio filters" msgstr "Audio Filter" #: apps/player/cfgdialog.c:56 lib/gtk/plugin_single.c:387 msgid "Video options" msgstr "Video Optionen" #: apps/player/cfgdialog.c:64 apps/plugincfg/gmerlin_plugincfg.c:413 msgid "Video filters" msgstr "Video Filter" #: apps/player/cfgdialog.c:74 msgid "Subtitle options" msgstr "Untertiteloptionen" #: apps/player/cfgdialog.c:83 apps/visualizer/gmerlin_visualizer.c:1110 #: lib/gtk/plugininfo.c:169 msgid "Visualization" msgstr "Visualisierung" #: apps/player/cfgdialog.c:86 lib/pluginregistry.c:2158 #: lib/pluginregistry.c:2623 msgid "Text subtitles" msgstr "Text Untertitel" #: apps/player/cfgdialog.c:89 apps/transcoder/trackdialog.c:374 #: apps/transcoder/trackdialog.c:442 lib/gtk/infowindow.c:735 msgid "Subtitles" msgstr "Untertitel" #: apps/player/cfgdialog.c:97 msgid "Gmerlin confiuration" msgstr "Gmerlin Konfiuration" #: apps/player/cfgdialog.c:114 apps/camelot/webcam_window.c:536 #: lib/gtk/plugininfo.c:154 msgid "Input" msgstr "Quelle" #: apps/player/cfgdialog.c:122 apps/plugincfg/gmerlin_plugincfg.c:273 #: apps/transcoder/transcoder_window.c:1391 msgid "Input plugins" msgstr "Quellenplugins" #: apps/player/cfgdialog.c:130 apps/plugincfg/gmerlin_plugincfg.c:574 #: apps/transcoder/transcoder_window.c:1399 msgid "Image readers" msgstr "Bilderimporteure" #: apps/player/cfgdialog.c:140 msgid "OSD" msgstr "OSD" #: apps/player/cfgdialog.c:151 apps/transcoder/transcoder_window.c:172 msgid "Display" msgstr "Display" #: apps/player/cfgdialog.c:161 apps/player/mainmenu.c:1009 msgid "Media Tree" msgstr "Media Tree" #: apps/player/cfgdialog.c:171 msgid "Remote control" msgstr "Fernbedienung" #: apps/player/cfgdialog.c:181 apps/player/mainmenu.c:1015 #: apps/camelot/webcam_window.c:803 apps/transcoder/transcoder_window.c:1432 #: apps/visualizer/gmerlin_visualizer.c:908 #: apps/recorder/recorder_window.c:803 msgid "Log window" msgstr "Meldungen" #: apps/player/cfgdialog.c:191 msgid "LCDproc" msgstr "LCDproc" #: apps/player/mainmenu.c:765 apps/player/mainmenu.c:802 #: apps/player/mainmenu.c:1192 msgid "Options..." msgstr "Optionen..." #: apps/player/mainmenu.c:769 msgid "Filters..." msgstr "Filter..." #: apps/player/mainmenu.c:772 msgid "Output plugin..." msgstr "Ausgabeplugin..." #: apps/player/mainmenu.c:797 msgid "Enable visualizations" msgstr "Verwende Visualisierungen" #: apps/player/mainmenu.c:806 lib/gtk/treewidget.c:1412 msgid "Plugin..." msgstr "Plugin..." #: apps/player/mainmenu.c:941 #, c-format msgid "Chapter %d [%s]" msgstr "Kapitel %d [%s]" #: apps/player/mainmenu.c:1012 msgid "Info window" msgstr "Track information" #: apps/player/mainmenu.c:1022 apps/transcoder/transcoder_window.c:862 msgid "About..." msgstr "Über..." #: apps/player/mainmenu.c:1024 apps/transcoder/transcoder_window.c:863 msgid "Userguide" msgstr "Benutzerhandbuch" #: apps/player/mainmenu.c:1045 apps/transcoder/transcoder_window.c:847 msgid "Preferences..." msgstr "Präferenzen..." #: apps/player/mainmenu.c:1052 msgid "Skins..." msgstr "Skins..." #: apps/player/mainmenu.c:1056 msgid "Multimedia keys..." msgstr "Multimedia Tasten..." #: apps/player/mainmenu.c:1062 msgid "Seek forward" msgstr "Vorwärts suchen" #: apps/player/mainmenu.c:1069 msgid "Seek backward" msgstr "Rückwärts suchen" #: apps/player/mainmenu.c:1076 msgid "Increase volume" msgstr "Lauter" #: apps/player/mainmenu.c:1083 msgid "Decrease volume" msgstr "Leiser" #: apps/player/mainmenu.c:1089 apps/player/gmerlin_remote.c:414 msgid "Toggle mute" msgstr "Stummschalten" #: apps/player/mainmenu.c:1095 msgid "Next track" msgstr "Nächster Track" #: apps/player/mainmenu.c:1100 msgid "Previous track" msgstr "Vorheriger Track" #: apps/player/mainmenu.c:1105 msgid "Next chapter" msgstr "Nächstes Kapitel" #: apps/player/mainmenu.c:1111 msgid "Previous chapter" msgstr "Vorheriges Kapitel" #: apps/player/mainmenu.c:1116 lib/gtk/treewidget.c:1336 #: lib/gtk/treewidget.c:2046 msgid "Goto current track" msgstr "Gehe zum nächsten Track" #: apps/player/mainmenu.c:1123 msgid "Copy current track to favourites" msgstr "Kopiere aktuellen Track zu Favoriten" #: apps/player/mainmenu.c:1131 msgid "Seek to start" msgstr "Zum Anfang suchen" #: apps/player/mainmenu.c:1136 lib/player.c:331 msgid "Pause" msgstr "Pause" #: apps/player/mainmenu.c:1141 msgid "Quit gmerlin" msgstr "Gmerlin beenden" #: apps/player/mainmenu.c:1152 msgid "Transcoder" msgstr "Transkoder" #: apps/player/mainmenu.c:1156 apps/visualizer/gmerlin_visualizer.c:899 msgid "Visualizer" msgstr "Visualisierer" #: apps/player/mainmenu.c:1160 msgid "Mixer" msgstr "Mischpult" #: apps/player/mainmenu.c:1167 msgid "Audio..." msgstr "Audio..." #: apps/player/mainmenu.c:1171 msgid "Video..." msgstr "Video..." #: apps/player/mainmenu.c:1175 msgid "Subtitles..." msgstr "Untertitel..." #: apps/player/mainmenu.c:1179 msgid "Chapters..." msgstr "Kapitel" #: apps/player/mainmenu.c:1184 msgid "Visualization..." msgstr "Visualisierung..." #: apps/player/mainmenu.c:1188 msgid "Windows..." msgstr "Fenster..." #: apps/player/mainmenu.c:1196 msgid "Commands..." msgstr "Befehle..." #: apps/player/mainmenu.c:1200 msgid "Accessories..." msgstr "Zubehör..." #: apps/player/mainmenu.c:1204 msgid "Help..." msgstr "Hilfe..." #: apps/player/display.c:67 msgid "Get colors from skin" msgstr "Hole Farben vom Skin" #: apps/player/display.c:70 msgid "Take the display colors from the skin definition" msgstr "Hole die Farben des Displays aus der Beschreibung des Skins" #: apps/player/display.c:74 apps/transcoder/transcoder_window.c:189 msgid "Background" msgstr "Hintergrund" #: apps/player/display.c:80 msgid "Normal foreground" msgstr "Vordergrund (normal)" #: apps/player/display.c:86 apps/transcoder/transcoder_window.c:183 #: lib/gtk/logwindow.c:378 msgid "Error foreground" msgstr "Vordergrund (Fehler)" #: apps/player/display.c:92 msgid "Display mode" msgstr "Display modus" #: apps/player/display.c:101 msgid "Repeat mode" msgstr "Wiederholmodus" #: apps/player/gmerlin_remote.c:201 msgid "Option -addplay requires an argument\n" msgstr "Option -addplay erfordert ein Argument\n" #: apps/player/gmerlin_remote.c:223 msgid "Option -add requires an argument\n" msgstr "Option -add erfordert ein Argument\n" #: apps/player/gmerlin_remote.c:246 msgid "Option -openplay requires an argument\n" msgstr "Option -openplay erfordert ein Argument\n" #: apps/player/gmerlin_remote.c:268 msgid "Option -open requires an argument\n" msgstr "Option -open erfordert ein Argument\n" #: apps/player/gmerlin_remote.c:291 msgid "Option -volume requires an argument\n" msgstr "Option -volume erfordert ein Argument\n" #: apps/player/gmerlin_remote.c:314 msgid "Option -volume_rel requires an argument\n" msgstr "Option -volume_rel erfordert ein Argument\n" #: apps/player/gmerlin_remote.c:339 msgid "Option -seek_rel requires an argument\n" msgstr "Option -seek_rel erfordert ein Argument\n" #: apps/player/gmerlin_remote.c:364 msgid "Option -chapter requires an argument\n" msgstr "Option -chapter erfordert ein Argument\n" #: apps/player/gmerlin_remote.c:389 msgid "Play current track" msgstr "Spiele aktuellen Track" #: apps/player/gmerlin_remote.c:394 msgid "Switch to next track" msgstr "Nächster Track" #: apps/player/gmerlin_remote.c:399 msgid "Switch to previous track" msgstr "Vorheriger Track" #: apps/player/gmerlin_remote.c:404 msgid "Stop playback" msgstr "Beende Wiedergabe" #: apps/player/gmerlin_remote.c:409 msgid "Pause playback" msgstr "Unterbreche Weidergabe" #: apps/player/gmerlin_remote.c:419 apps/player/gmerlin_remote.c:425 msgid "" msgstr "" #: apps/player/gmerlin_remote.c:420 msgid "Add to the incoming album" msgstr "Füge zum Eingangs-Album" #: apps/player/gmerlin_remote.c:426 msgid "Add to the incoming album and play it" msgstr "Füge zum Eingangs-Album und starte Wiedergabe" #: apps/player/gmerlin_remote.c:431 apps/player/gmerlin_remote.c:437 msgid "" msgstr "" #: apps/player/gmerlin_remote.c:432 msgid "Open album for . Device must be a GML (e.g. dvd:///dev/hdd)." msgstr "" "Öffne Album für . Gerät muß eine GML sein (z.B. dvd:///dev/hdd)." #: apps/player/gmerlin_remote.c:438 msgid "" "Open album for and play first track. Device must be a GML (e.g. " "dvd:///dev/hdd)." msgstr "" "Öffne Album für und spiele ersten Track. Gerät muß eine GML sein (z." "B. dvd:///dev/hdd)" #: apps/player/gmerlin_remote.c:443 msgid "" msgstr "" #: apps/player/gmerlin_remote.c:444 msgid "Set player volume. is in dB, 0.0 is max" msgstr "Setze Wiedergabelautstärke. ist in dB, 0.0 ist maximal" #: apps/player/gmerlin_remote.c:449 apps/player/gmerlin_remote.c:455 msgid "" msgstr "" #: apps/player/gmerlin_remote.c:450 msgid "In- or decrease player volume. is in dB" msgstr "Erhöhe oder Verringere die Lautstärke. ist in dB" #: apps/player/gmerlin_remote.c:456 msgid "Seek relative. is in seconds." msgstr "Suche relativ. ist in Sekunden" #: apps/player/gmerlin_remote.c:462 msgid "" "Go to the specified chapter. Use '+' and '-' to go to the next or previous " "chapter respectively" msgstr "" "Gehe zu einem bestimmten Kapitel. Mit '+' oder '.' kommst Du zum nächsten " "bzw. vorherigen Kapitel" #: apps/player/gmerlin_remote.c:467 #, fuzzy msgid "Print name of the current track" msgstr "Gehe zum nächsten Track" #: apps/player/gmerlin_remote.c:472 #, fuzzy msgid "Print metadata of the current track" msgstr "Gehe zum nächsten Track" #: apps/player/gmerlin_remote.c:477 #, fuzzy msgid "Print time of the current track" msgstr "Gehe zum nächsten Track" #: apps/player/gmerlin_remote.c:492 msgid "Option -host requires an argument" msgstr "Option -host erfordert ein Argument" #: apps/player/gmerlin_remote.c:504 msgid "Option -port requires an argument" msgstr "Option -port erfordert ein Argument" #: apps/player/gmerlin_remote.c:522 msgid "Host to connect to, default is localhost" msgstr "Rechner zum Verbinden. Voreinstellung ist localhost" #: apps/player/gmerlin_remote.c:528 msgid "Port to connect to" msgstr "Port zum Verbinden" #: apps/player/gmerlin_remote.c:533 msgid "Launch new player if necessary" msgstr "Starte neuen Player wenn nötig" #: apps/player/gmerlin_remote.c:560 #: apps/transcoder/gmerlin_transcoder_remote.c:172 msgid "[options] command\n" msgstr "[Optionen] Befehl\n" #: apps/player/gmerlin_remote.c:561 msgid "Remote control command for the Gmerlin GUI Player\n" msgstr "Fernbedienung für den Gmerlin GUI Player\n" #: apps/player/gmerlin_remote.c:562 #: apps/transcoder/gmerlin_transcoder_remote.c:174 msgid "Global options" msgstr "Globale Optionen" #: apps/player/gmerlin_remote.c:563 #: apps/transcoder/gmerlin_transcoder_remote.c:175 msgid "Commands" msgstr "Befehle" #: apps/player/gmerlin_remote.c:605 msgid "Cannot launch gmerlin process" msgstr "Kann keinen gmerlin Prozess starten" #: apps/plugincfg/gmerlin_plugincfg.c:261 msgid "Gmerlin Plugin Configurator" msgstr "Gmerlin Pluginkonfiguration" #: apps/plugincfg/gmerlin_plugincfg.c:313 msgid "Encode audio into video file" msgstr "Schreibe Audio in die Videodatei" #: apps/plugincfg/gmerlin_plugincfg.c:331 msgid "Encode text subtitles into video file" msgstr "Schreibe Textuntertitel in die Videodatei" #: apps/plugincfg/gmerlin_plugincfg.c:351 msgid "Encode overlay subtitles into video file" msgstr "Schreibe Oberlayuntertitel in die Videodatei" #: apps/plugincfg/gmerlin_plugincfg.c:382 apps/transcoder/ppwidget.c:79 msgid "Enable postprocessing" msgstr "Verwende Weiterverarbeitung" #: apps/plugincfg/gmerlin_plugincfg.c:427 msgid "Visualizations" msgstr "Visualisierungen" #: apps/plugincfg/gmerlin_plugincfg.c:453 msgid "Output" msgstr "Ausgabe" #: apps/plugincfg/gmerlin_plugincfg.c:536 #: apps/transcoder/transcoder_window.c:1383 #: apps/recorder/recorder_window.c:777 msgid "Encoders" msgstr "Enkoder" #: apps/plugincfg/gmerlin_plugincfg.c:559 lib/gtk/plugininfo.c:181 msgid "Recorder" msgstr "Aufnahme" #: apps/plugincfg/gmerlin_plugincfg.c:607 msgid "Image writers" msgstr "Bild Exporteure" #: apps/cmdlinerecorder/gmerlin-record.c:315 apps/transcoder/main.c:68 #: apps/nmjedit/gmerlin-nmjedit.c:168 msgid "[options]\n" msgstr "[Optionen]\n" #: apps/cmdlinerecorder/gmerlin-record.c:316 #, fuzzy msgid "Commandline recorder\n" msgstr "Kommandozeilen-Multimediaplayer\n" #: apps/cmdlinerecorder/gmerlin-record.c:317 #: apps/transcoder/transcoder_window.c:1006 apps/transcoder/main.c:70 #: apps/cmdlineplayer/gmerlin_play.c:838 apps/nmjedit/gmerlin-nmjedit.c:170 #: apps/thumbnailer/gmerlin-video-thumbnailer.c:94 tests/imgconvert.c:97 #: tests/fvtest.c:175 tests/cfgtest.c:624 tests/visualization.c:78 #: tests/gmerlin_visualize.c:344 msgid "Options" msgstr "Optionen" #: apps/cmdlinerecorder/gmerlin-record.c:323 #: apps/cmdlineplayer/gmerlin_play.c:844 apps/nmjedit/gmerlin-nmjedit.c:176 #: apps/thumbnailer/gmerlin-video-thumbnailer.c:100 tests/fvtest.c:181 msgid "" "Default plugin parameters are read from there. Use gmerlin_plugincfg to " "change them." msgstr "" "Voreingestellte Pluginparameter werden von hier gelesen. Nehme " "gmerlin_plugincfg um die zu ändern" #: apps/camelot/webcam.c:52 apps/camelot/webcam.c:561 msgid "read_frame failed" msgstr "read_frame fehlgeschlagen" #: apps/camelot/webcam.c:241 msgid "do_capture: No plugin loaded" msgstr "do_capture: Kein Plugin geladen" #: apps/camelot/webcam.c:259 #, c-format msgid "Saving %s failed" msgstr "Speichern von %s fehlgeschlagen" #: apps/camelot/webcam.c:303 msgid "Opening monitor plugin failed" msgstr "Öffnen des Monitorplugins fehlgeschlagen" #: apps/camelot/webcam.c:391 #, c-format msgid "Initializing %s failed, check settings" msgstr "Initialisierung von %s fehlgeschlagen, überprüfe Einstellungen" #: apps/camelot/webcam.c:683 lib/player_video.c:249 msgid "Restarting playback due to changed video filters" msgstr "Starte Abspielen neu wegen geänderter Videofilter" #: apps/camelot/webcam.c:722 msgid "Restarting vloopback failed, close client and try again" msgstr "" #: apps/camelot/webcam.c:735 #, fuzzy msgid "Video capture" msgstr "Videostream" #: apps/camelot/webcam.c:740 #, fuzzy msgid "Maximum framerate" msgstr "Maximale Wiederholungen" #: apps/camelot/vloopback.c:185 msgid "VIDIOCGCAP" msgstr "" #: apps/camelot/vloopback.c:201 msgid "VIDIOCGCHAN" msgstr "" #: apps/camelot/vloopback.c:216 msgid "VIDIOCSCHAN" msgstr "" #: apps/camelot/vloopback.c:226 #, c-format msgid "VIDIOCCAPTURE %d" msgstr "" #: apps/camelot/vloopback.c:242 #, fuzzy, c-format msgid "VIDIOCGPICT %d %d" msgstr "VIDIOCGPICT fehlgeschlagen: %s" #: apps/camelot/vloopback.c:251 #, fuzzy msgid "VIDIOCSPICT" msgstr "VIDIOCSPICT fehlgeschlagen: %s" #: apps/camelot/vloopback.c:259 #, c-format msgid "unsupported pixel format (%d) is requested in VIDIOCSPICT" msgstr "" #: apps/camelot/vloopback.c:282 #, fuzzy, c-format msgid "VIDIOCGWIN %dx%d" msgstr "VIDIOCGWIN fehlgeschlagen: %s" #: apps/camelot/vloopback.c:291 msgid "VIDIOCSWIN" msgstr "" #: apps/camelot/vloopback.c:295 #, fuzzy, c-format msgid "width %d out of range" msgstr "Audiosuche reichte außerhalb des Bereichs" #: apps/camelot/vloopback.c:300 #, fuzzy, c-format msgid "height %d out of range" msgstr "Audiosuche reichte außerhalb des Bereichs" #: apps/camelot/vloopback.c:305 #, c-format msgid "invalid flags %08x in VIDIOCSWIN" msgstr "" #: apps/camelot/vloopback.c:318 msgid "VIDIOCSYNC" msgstr "" #: apps/camelot/vloopback.c:322 #, c-format msgid "frame %d out of range in VIDIOCSYNC" msgstr "" #: apps/camelot/vloopback.c:333 msgid "VIDIOCMCAPTURE" msgstr "" #: apps/camelot/vloopback.c:340 #, c-format msgid "VIDIOCMCAPTURE: requested capture size is too big: %dx%d" msgstr "" #: apps/camelot/vloopback.c:346 #, c-format msgid "VIDIOCMCAPTURE: requested capture size is too small: %dx%d" msgstr "" #: apps/camelot/vloopback.c:351 #, c-format msgid "VIDIOCMCAPTURE %dx%d, format: %d" msgstr "" #: apps/camelot/vloopback.c:364 #, c-format msgid "unsupported pixel format (%d) is requested in VIDIOCMCAPTURE" msgstr "" #: apps/camelot/vloopback.c:375 #, c-format msgid "Invalid frame (%d) in VIDIOCMCAPTURE" msgstr "" #: apps/camelot/vloopback.c:388 #, fuzzy msgid "VIDIOCGMBUF" msgstr "VIDIOCGMBUF fehlgeschlagen: %s" #: apps/camelot/vloopback.c:400 #, fuzzy, c-format msgid "Unknown ioctl %lx" msgstr "Unbekannte Skaliermethode: %s" #: apps/camelot/vloopback.c:535 #, fuzzy, c-format msgid "VIDIOCGCAP failed %s" msgstr "VIDIOCGPICT fehlgeschlagen: %s" #: apps/camelot/vloopback.c:557 #, fuzzy msgid "ioctl VIDIOCGWIN failed" msgstr "VIDIOCGWIN fehlgeschlagen: %s" #: apps/camelot/vloopback.c:566 #, fuzzy msgid "ioctl VIDIOCSWIN failed" msgstr "VIDIOCGWIN fehlgeschlagen: %s" #: apps/camelot/vloopback.c:574 msgid "Opened vloopback in write mode" msgstr "" #: apps/camelot/vloopback.c:585 #, fuzzy, c-format msgid "vloopback mmap failed: %s" msgstr "mmap fehlgeschlagen: %s" #: apps/camelot/vloopback.c:592 msgid "Opened vloopback in ioctl mode" msgstr "" #: apps/camelot/vloopback.c:612 msgid "Closed vloopback" msgstr "" #: apps/camelot/vloopback.c:655 #, fuzzy msgid "Client connected" msgstr "Clientverbindung geschlossen" #: apps/camelot/vloopback.c:670 #, fuzzy msgid "Client disconnected" msgstr "Clientverbindung geschlossen" #: apps/camelot/vloopback.c:684 #, c-format msgid "ioctl %lx unsuccessfull." msgstr "" #: apps/camelot/vloopback.c:740 #, fuzzy msgid "Write" msgstr "Wave Exporteur" #: apps/camelot/vloopback.c:740 #, fuzzy msgid "ioctl" msgstr "Titel" #: apps/camelot/vloopback.c:741 msgid "" "Set the operating mode. Ioctl is more flexible on the clients side but " "doesn't work with all applications. Write works with more applications but " "has a larger overhead" msgstr "" #: apps/camelot/vloopback.c:765 msgid "Fixed resolution for write mode" msgstr "" #: apps/camelot/vloopback.c:774 #, fuzzy msgid "User defined width for write mode" msgstr "Benutzerdefinierte Breite" #: apps/camelot/vloopback.c:783 #, fuzzy msgid "User defined height for write mode" msgstr "Benutzerdefinierte Höhe" #: apps/camelot/vloopback.c:792 msgid "Y'CbCr 4:2:0" msgstr "" #: apps/camelot/vloopback.c:793 msgid "RGB (24 bit)" msgstr "" #: apps/camelot/vloopback.c:795 msgid "Pixelformat for write mode" msgstr "" #: apps/camelot/webcam_window.c:309 apps/recorder/recorder_window.c:441 #, c-format msgid "Framerate: %.2f fps" msgstr "Bildwiederholrate: %.2f fps" #: apps/camelot/webcam_window.c:434 apps/camelot/webcam_window.c:456 #: apps/camelot/webcam_window.c:494 lib/recorder_video.c:160 #: lib/recorder_video.c:284 lib/recorder_video.c:388 lib/singlepic.c:755 #: lib/transcoder_track.c:182 lib/recorder_audio.c:93 lib/ovl2text.c:157 msgid "Plugin" msgstr "Plugin" #: apps/camelot/webcam_window.c:442 msgid "Reopen" msgstr "Neu öffnen" #: apps/camelot/webcam_window.c:448 #, fuzzy msgid "Setup filters" msgstr "Audio Filter" #: apps/camelot/webcam_window.c:465 msgid "Take picture" msgstr "Schnappschuß" #: apps/camelot/webcam_window.c:470 apps/camelot/webcam_window.c:844 msgid "Automatic capture" msgstr "Automatisch aufnehmen" #: apps/camelot/webcam_window.c:483 #, fuzzy msgid "Enable vloopback" msgstr "Verwende Monitor" #: apps/camelot/webcam_window.c:504 msgid "Enable Monitor" msgstr "Verwende Monitor" #: apps/camelot/webcam_window.c:527 msgid "Set" msgstr "Übernehmen" #: apps/camelot/webcam_window.c:567 apps/transcoder/transcoder_window.c:1315 #: apps/transcoder/transcoder_window.c:1341 apps/transcoder/trackdialog.c:234 #: apps/transcoder/trackdialog.c:304 apps/recorder/recorder_window.c:732 #: apps/recorder/recorder_window.c:751 msgid "Filters" msgstr "Filter" #: apps/camelot/webcam_window.c:616 msgid "Cam" msgstr "" #: apps/camelot/webcam_window.c:640 msgid "Interval (sec)" msgstr "Intervall (sek)" #: apps/camelot/webcam_window.c:655 apps/alsamixer/card.c:231 msgid "Capture" msgstr "Aufnahme" #: apps/camelot/webcam_window.c:667 msgid "Directory" msgstr "Verzeichnis" #: apps/camelot/webcam_window.c:684 lib/recorder.c:520 msgid "" "Extension is appended by the plugin\n" "%t Inserts time\n" "%d Inserts date\n" "%n Inserts Frame number with digits" msgstr "" "Erweiterung wird vom Plugin angefügt.\n" "%t Fügt Zeit ein\n" "%d Fügt Datum ein\n" "%n Fügt Bildnummer mit Stellen ein" #: apps/camelot/webcam_window.c:695 msgid "Filename base" msgstr "Basis für Dateinamen" #: apps/camelot/webcam_window.c:704 msgid "Frame counter" msgstr "Bilderzähler" #: apps/camelot/webcam_window.c:721 apps/recorder/recorder_window.c:787 msgid "Output files" msgstr "Ausgabedateien" #: apps/camelot/webcam_window.c:737 apps/recorder/recorder_window.c:614 #: lib/gtk/aboutwindow.c:126 msgid "About" msgstr "Über" #: apps/camelot/webcam_window.c:738 apps/transcoder/transcoder_window.c:858 #: apps/recorder/recorder_window.c:616 msgid "Log messages" msgstr "Meldungen" #: apps/camelot/webcam_window.c:739 apps/recorder/recorder_window.c:618 #, fuzzy msgid "Preferences" msgstr "Präferenzen..." #: apps/camelot/webcam_window.c:790 #, fuzzy msgid "Camelot confiuration" msgstr "Gmerlin Konfiuration" #: apps/camelot/webcam_window.c:794 apps/camelot/webcam_window.c:880 msgid "vloopback" msgstr "" #: apps/camelot/webcam_window.c:837 msgid "Do monitor" msgstr "Monitor aktiv" #: apps/camelot/webcam_window.c:840 msgid "Enable monitoring of the webcam image" msgstr "Verwende Monitoring des Webcambildes" #: apps/camelot/webcam_window.c:847 msgid "Automatically capture in the specified capture interval" msgstr "Speichere automatisch Aufnahmen im angegebenen Intervall" #: apps/camelot/webcam_window.c:851 msgid "Capture interval" msgstr "Aufnahmeintervall" #: apps/camelot/webcam_window.c:856 msgid "Capture interval (in seconds)" msgstr "Aufnahmeintervall (in Sekunden)" #: apps/camelot/webcam_window.c:860 lib/recorder.c:496 msgid "Output directory" msgstr "Ausgabeverzeichnis" #: apps/camelot/webcam_window.c:866 msgid "Output namebase" msgstr "Ausgabe Namensbasis" #: apps/camelot/webcam_window.c:869 msgid "" "Template for the output files. A mask \"%n\" inserts the frame number " "with digits (e.g. webcam-shot-%6n)" msgstr "" "Schablone für die Ausgabedateien. Eine Maske \"%n\" fügt die Bildnummer " "mit Stellen ein (z.B. webcam-shot-%6n)" #: apps/camelot/webcam_window.c:873 msgid "Output framecounter" msgstr "Bilderzähler der Ausgabe" #: apps/camelot/webcam_window.c:886 msgid "vloopback_dev" msgstr "" #: apps/transcoder/transcoder_window.c:177 msgid "Foreground" msgstr "Vordergrund" #: apps/transcoder/transcoder_window.c:222 msgid "GUI" msgstr "GUI" #: apps/transcoder/transcoder_window.c:227 msgid "Show Tooltips" msgstr "Zeige Tooltips" #: apps/transcoder/transcoder_window.c:659 #: apps/transcoder/transcoder_window.c:968 msgid "Load task list" msgstr "Lade Aufgabenliste" #: apps/transcoder/transcoder_window.c:669 #: apps/transcoder/transcoder_window.c:970 msgid "Save task list" msgstr "Speichere Aufgabenliste" #: apps/transcoder/transcoder_window.c:680 msgid "Load profile" msgstr "Lade Profil" #: apps/transcoder/transcoder_window.c:690 msgid "Save profile" msgstr "Speichere Profil" #: apps/transcoder/transcoder_window.c:841 msgid "Load tasklist..." msgstr "Lade Aufgabenliste..." #: apps/transcoder/transcoder_window.c:842 msgid "Save tasklist..." msgstr "Speichere Aufgabenliste..." #: apps/transcoder/transcoder_window.c:843 #: apps/visualizer/gmerlin_visualizer.c:1050 msgid "Quit" msgstr "Beenden" #: apps/transcoder/transcoder_window.c:848 msgid "Load profile..." msgstr "Lade Profil..." #: apps/transcoder/transcoder_window.c:849 msgid "Save profile..." msgstr "Speichere Profile..." #: apps/transcoder/transcoder_window.c:853 #: apps/transcoder/transcoder_window.c:958 msgid "Start transcoding" msgstr "Beginne Transkodierung" #: apps/transcoder/transcoder_window.c:854 #: apps/transcoder/transcoder_window.c:961 msgid "Stop transcoding" msgstr "Stoppe Transkodierung" #: apps/transcoder/transcoder_window.c:950 msgid "Gmerlin transcoder" msgstr "Gmerlin Transcoder" #: apps/transcoder/transcoder_window.c:964 msgid "Set global options and track defaults" msgstr "" "Setzte globale Optionen und Voreinstellungen für neu hinzugefügte Tracks" #: apps/transcoder/transcoder_window.c:966 msgid "Quit program" msgstr "Beende Programm" #: apps/transcoder/transcoder_window.c:1001 lib/gtk/plugininfo.c:182 msgid "File" msgstr "Datei" #: apps/transcoder/transcoder_window.c:1011 msgid "Actions" msgstr "Aktionen" #: apps/transcoder/transcoder_window.c:1016 #: apps/transcoder/transcoder_window.c:1075 msgid "Tasklist" msgstr "Aufgabenliste" #: apps/transcoder/transcoder_window.c:1021 msgid "Windows" msgstr "Fenster" #: apps/transcoder/transcoder_window.c:1026 msgid "Help" msgstr "Hilfe" #: apps/transcoder/transcoder_window.c:1274 msgid "Transcoder configuration" msgstr "Transkoderkonfiguration" #: apps/transcoder/transcoder_window.c:1279 msgid "Output options" msgstr "Ausgabeoptionen" #: apps/transcoder/transcoder_window.c:1290 msgid "Track defaults" msgstr "Track Voreinstellungen" #: apps/transcoder/transcoder_window.c:1299 msgid "Audio defaults" msgstr "Audio Voreinstellungen" #: apps/transcoder/transcoder_window.c:1328 msgid "Video defaults" msgstr "Video Voreinstellungen" #: apps/transcoder/transcoder_window.c:1349 msgid "Text subtitle defaults" msgstr "Text Untertitel Voreinstellungen" #: apps/transcoder/transcoder_window.c:1364 apps/transcoder/trackdialog.c:390 msgid "Textrenderer" msgstr "Textrenderer" #: apps/transcoder/transcoder_window.c:1375 msgid "Overlay subtitle defaults" msgstr "Overlay Unrertitel Voreinstellungen" #: apps/transcoder/transcoder_window.c:1410 msgid "Window" msgstr "Fenster" #: apps/transcoder/transcoder_window.c:1421 msgid "Remote" msgstr "Fernbedienung" #: apps/transcoder/main.c:69 msgid "GTK multimedia transcoder\n" msgstr "GTK Multimediatranscoder\n" #: apps/transcoder/ppwidget.c:209 msgid "Postprocessing" msgstr "Weiterverarbeitung" #: apps/transcoder/gmerlin_transcoder_remote.c:173 msgid "Remote control command for the Gmerlin GUI transcoder\n" msgstr "Fernbedienung für den GTK Multimediatranscoder\n" #: apps/transcoder/gmerlin_transcoder_remote.c:214 msgid "Cannot launch transcoder process" msgstr "Kann Transkoderprozess nicht starten" #: apps/transcoder/tracklist.c:832 #, fuzzy msgid "Encoder configuration" msgstr "Transkoderkonfiguration" #: apps/transcoder/tracklist.c:891 msgid "" "Use \"-\" to clear this field for all tracks. Empty string means to leave it " "unchanged for all tracks" msgstr "" #: apps/transcoder/tracklist.c:902 #, fuzzy msgid "Mass tag" msgstr "Meldung" #: apps/transcoder/tracklist.c:951 lib/tree.c:1176 msgid "Format for track names" msgstr "Format für Tracknamen" #: apps/transcoder/tracklist.c:953 lib/tree.c:1179 msgid "" "Format specifier for tracknames from\n" "metadata\n" "%p: Artist\n" "%a: Album\n" "%g: Genre\n" "%t: Track name\n" "%n: Track number with digits\n" "%y: Year\n" "%c: Comment" msgstr "" "Format für Erzeugung von Tracknamen aus Metadaten\n" "%p: Künstler\n" "%a: Album\n" "%g: Genre\n" "%t: Trackname\n" "%n: Tracknummer mit Stellen\n" "%y: Jahr\n" "%c: Kommentar" #: apps/transcoder/tracklist.c:1007 #, fuzzy msgid "Auto rename" msgstr "Automatische Geschwindigkeit" #: apps/transcoder/tracklist.c:1096 lib/gtk/albumwidget.c:2899 msgid "Add files" msgstr "Dateien hinzufügen" #: apps/transcoder/tracklist.c:1229 lib/gtk/albumwidget.c:1453 msgid "Files..." msgstr "Dateien..." #: apps/transcoder/tracklist.c:1231 msgid "Urls..." msgstr "Urls..." #: apps/transcoder/tracklist.c:1233 msgid "Drives..." msgstr "Laufwerke..." #: apps/transcoder/tracklist.c:1241 msgid "Move Up" msgstr "Verschiebe hoch" #: apps/transcoder/tracklist.c:1243 msgid "Move Down" msgstr "Verschiebe nach unten" #: apps/transcoder/tracklist.c:1245 lib/gtk/treewidget.c:1386 #: lib/gtk/albumwidget.c:1494 msgid "Remove" msgstr "Löschen" #: apps/transcoder/tracklist.c:1247 msgid "Configure..." msgstr "Konfigurieren..." #: apps/transcoder/tracklist.c:1249 msgid "Edit chapters..." msgstr "Kapitel bearbeiten" #: apps/transcoder/tracklist.c:1251 msgid "Mass tag..." msgstr "" #: apps/transcoder/tracklist.c:1253 #, fuzzy msgid "Auto numbering" msgstr "Gmerlin beenden" #: apps/transcoder/tracklist.c:1255 #, fuzzy msgid "Auto rename..." msgstr "Umbenennen..." #: apps/transcoder/tracklist.c:1257 msgid "Change encoders..." msgstr "Wechsele Enkoder..." #: apps/transcoder/tracklist.c:1264 lib/gtk/albumwidget.c:1501 #: lib/gtk/albumwidget.c:2904 msgid "Cut" msgstr "Auschneiden" #: apps/transcoder/tracklist.c:1273 lib/gtk/albumwidget.c:1515 #: lib/gtk/albumwidget.c:2908 msgid "Paste" msgstr "Einfügen" #: apps/transcoder/tracklist.c:1284 lib/gtk/albumwidget.c:1581 #: lib/gtk/cfg_device.c:339 msgid "Add..." msgstr "Hinzufügen..." #: apps/transcoder/tracklist.c:1290 lib/gtk/albumwidget.c:1595 msgid "Selected..." msgstr "Ausgewählte..." #: apps/transcoder/tracklist.c:1296 lib/gtk/albumwidget.c:1588 msgid "Edit..." msgstr "Bearbeiten..." #: apps/transcoder/tracklist.c:1302 msgid "Postprocess..." msgstr "Weiterverarbeitung..." #: apps/transcoder/tracklist.c:1517 lib/gtk/albumwidget.c:2934 msgid "Total playback time" msgstr "Gesamtspielzeit" #: apps/transcoder/tracklist.c:1526 msgid "Append files to the task list" msgstr "Füge Dateien an die Aufgabenliste an" #: apps/transcoder/tracklist.c:1531 msgid "Append URLs to the task list" msgstr "Füge URLs an die Aufgabenliste an" #: apps/transcoder/tracklist.c:1536 msgid "Append removable media to the task list" msgstr "Füge Wechselmedien an die Aufgabenliste an" #: apps/transcoder/tracklist.c:1541 msgid "Delete selected tracks" msgstr "Lösche ausgewählte Tracks" #: apps/transcoder/tracklist.c:1546 msgid "Configure selected track" msgstr "Konfiguriere ausgewählten Track" #: apps/transcoder/tracklist.c:1551 lib/gtk/chapterdialog.c:343 msgid "Edit chapters" msgstr "Bearbeite Kapitel" #: apps/transcoder/tracklist.c:1556 msgid "Change encoder plugins for selected tracks" msgstr "Ändere Enkoderplugins für ausgewählte Tracks" #: apps/transcoder/tracklist.c:1561 msgid "Copy selected tracks to clipboard" msgstr "Kopiere ausgewählte Tracks in die Zwischenablage" #: apps/transcoder/tracklist.c:1565 msgid "Cut selected tracks to clipboard" msgstr "Verschiebe ausgewählte Tracks in die Zwischenablage" #: apps/transcoder/tracklist.c:1570 msgid "Paste tracks from clipboard" msgstr "Füge Tracks von der Zwischenablage ein" #: apps/transcoder/trackdialog.c:82 msgid "Track options" msgstr "Trackoptionen" #: apps/transcoder/trackdialog.c:96 apps/recorder/recorder_window.c:795 #: lib/gtk/infowindow.c:692 lib/gtk/infowindow.c:701 lib/gtk/infowindow.c:720 #: lib/gtk/infowindow.c:739 msgid "Metadata" msgstr "Metadaten" #: apps/transcoder/trackdialog.c:208 #, c-format msgid "Audio #%d: %s" msgstr "Audio #%d: %s" #: apps/transcoder/trackdialog.c:210 #, c-format msgid "Audio #%d" msgstr "Audio #%d" #: apps/transcoder/trackdialog.c:215 #, c-format msgid "Audio: %s" msgstr "Audio: %s" #: apps/transcoder/trackdialog.c:243 apps/transcoder/trackdialog.c:313 #: apps/transcoder/trackdialog.c:459 #, fuzzy msgid "Encode options" msgstr "Renderoptionen" #: apps/transcoder/trackdialog.c:279 #, c-format msgid "Video #%d: %s" msgstr "Video #%d: %s" #: apps/transcoder/trackdialog.c:281 #, c-format msgid "Video #%d" msgstr "Video #%d" #: apps/transcoder/trackdialog.c:286 #, c-format msgid "Video: %s" msgstr "Video: %s" #: apps/transcoder/trackdialog.c:365 apps/transcoder/trackdialog.c:432 #, c-format msgid "Subtitles #%d: %s" msgstr "Untertitel #%d: %s" #: apps/transcoder/trackdialog.c:367 apps/transcoder/trackdialog.c:435 #, c-format msgid "Subtitles #%d" msgstr "Untertitel #%d" #: apps/transcoder/trackdialog.c:372 apps/transcoder/trackdialog.c:440 #, c-format msgid "Subtitles: %s" msgstr "Untertitel: %s" #: apps/transcoder/trackdialog.c:399 #, fuzzy msgid "Encode options (text)" msgstr "Transkodiere als Text" #: apps/transcoder/trackdialog.c:412 #, fuzzy msgid "Encode options (overlay)" msgstr "Transkodiere als Overlay" #: apps/visualizer/gmerlin_visualizer.c:335 #: apps/visualizer/gmerlin_visualizer.c:361 msgid "Opening audio device failed, fix settings and click restart" msgstr "" "Öffnen des Audiogerätes fehlgeschlegen. Korrigiere Einstellungen und Klicke " "\"Neu starten\"" #: apps/visualizer/gmerlin_visualizer.c:336 #: apps/visualizer/gmerlin_visualizer.c:362 msgid "No audio" msgstr "Kein Audio" #: apps/visualizer/gmerlin_visualizer.c:498 #, c-format msgid "Changed recording plugin to %s" msgstr "Aufnahmeplugin geändert zu %s" #: apps/visualizer/gmerlin_visualizer.c:515 lib/gtk/plugininfo.c:157 msgid "Audio recorder" msgstr "Audiorecorder" #: apps/visualizer/gmerlin_visualizer.c:525 lib/gtk/plugininfo.c:156 msgid "Video output" msgstr "Videoausgabe" #: apps/visualizer/gmerlin_visualizer.c:887 msgid "Visualizer configuration" msgstr "Visualisierer-Konfiguration" #: apps/visualizer/gmerlin_visualizer.c:1041 msgid "Gmerlin visualizer" msgstr "Gmerlin Visualisierer" #: apps/visualizer/gmerlin_visualizer.c:1044 msgid "Configure" msgstr "Konfigurieren" #: apps/visualizer/gmerlin_visualizer.c:1046 msgid "Recording and display plugins" msgstr "Aufnahme- und Anzeigeplugins" #: apps/visualizer/gmerlin_visualizer.c:1048 msgid "Restart visualization" msgstr "Visualisierung neu starten" #: apps/visualizer/gmerlin_visualizer.c:1052 #: apps/recorder/recorder_window.c:627 msgid "Fullscreen mode" msgstr "Vollbild" #: apps/visualizer/gmerlin_visualizer.c:1054 #: apps/recorder/recorder_window.c:629 msgid "Leave fullscreen mode" msgstr "Beende Vollbild" #: apps/visualizer/gmerlin_visualizer.c:1058 msgid "Show log window" msgstr "Zeige Meldungen" #: apps/visualizer/gmerlin_visualizer.c:1061 msgid "About Gmerlin visualizer" msgstr "Über Gmerlin Visualisierer" #: apps/visualizer/gmerlin_visualizer.c:1064 msgid "Launch help in a webwroswer" msgstr "Starte Hilfe im Webbrowser" #: apps/cmdlineplayer/gmerlin_play.c:558 #, c-format msgid "No such track %d" msgstr "Kein solcher Track %d" #: apps/cmdlineplayer/gmerlin_play.c:600 #, c-format msgid "Got redirector %s (%d/%d)" msgstr "Weiterleitung erhalten %s (%d/%d)" #: apps/cmdlineplayer/gmerlin_play.c:687 #, c-format msgid "Name: %s" msgstr "Name: %s" #: apps/cmdlineplayer/gmerlin_play.c:695 #, c-format msgid "Audio streams %d" msgstr "Audio streams %d" #: apps/cmdlineplayer/gmerlin_play.c:700 #, c-format msgid "Video streams %d" msgstr "Video streams %d" #: apps/cmdlineplayer/gmerlin_play.c:705 #, c-format msgid "Subtitle streams %d" msgstr "Untertitelstream %d" #: apps/cmdlineplayer/gmerlin_play.c:717 #, c-format msgid "" "Playing audio stream %d\n" "Input format:\n" "%s\n" "Output format:\n" "%s" msgstr "" "Spiele Audiostream %d\n" "Quellenformat:\n" "%s\n" "Ausgabeformat:\n" "%s" #: apps/cmdlineplayer/gmerlin_play.c:732 #, c-format msgid "" "Playing video stream %d\n" "Input format:\n" "%s\n" "Output format:\n" "%s" msgstr "" "Spiele Videostream %d\n" "Quellenformat:\n" "%s\n" "Ausgabeformat:\n" "%s" #: apps/cmdlineplayer/gmerlin_play.c:759 msgid "Player cleaned up" msgstr "Spieler aufgeräumt" #: apps/cmdlineplayer/gmerlin_play.c:776 msgid "Player now playing" msgstr "Spieler spielt jetzt" #: apps/cmdlineplayer/gmerlin_play.c:780 msgid "Player now seeking" msgstr "Spieler sucht jetzt" #: apps/cmdlineplayer/gmerlin_play.c:784 msgid "Player now changing" msgstr "Spieler wechselt jetzt" #: apps/cmdlineplayer/gmerlin_play.c:836 msgid "[options] gml...\n" msgstr "[Optionen] gml...\n" #: apps/cmdlineplayer/gmerlin_play.c:837 msgid "Commandline Multimedia player\n" msgstr "Kommandozeilen-Multimediaplayer\n" #: apps/kbd/kbd_daemon.c:97 #, c-format msgid "Grabbing key (Code: %d, modifiers: %s) failed" msgstr "" "Exklusiver Zugriff auf Taste (Code: %d, Modifizierer: %s) fehlgeschlagen" #: apps/kbd/kbd_daemon.c:132 msgid "Exiting" msgstr "Beende" #: apps/kbd/kbd_daemon.c:200 #, c-format msgid "State %02x -> %02x\n" msgstr "Status %02x -> %02x\n" #: apps/kbd/kbd_daemon.c:239 msgid "Reloaded keys" msgstr "Tasten neu geladen" #: apps/kbd/kbd_config.c:190 apps/kbd/kbd_config.c:625 msgid "Edit key" msgstr "Taste bearbeiten" #: apps/kbd/kbd_config.c:196 msgid "Grab key" msgstr "Taste auslesen" #: apps/kbd/kbd_config.c:227 apps/kbd/kbd_config.c:647 msgid "Scancode" msgstr "Scancode" #: apps/kbd/kbd_config.c:236 apps/kbd/kbd_config.c:656 msgid "Modifiers" msgstr "Modifizierer" #: apps/kbd/kbd_config.c:248 apps/kbd/kbd_config.c:664 msgid "Command" msgstr "Befehl" #: apps/kbd/kbd_config.c:507 msgid "Keyboard daemon not found" msgstr "Tastaturdämon nicht gefunden" #: apps/kbd/kbd_config.c:609 msgid "Keyboard daemon configuration" msgstr "Tastaturdämon Konfiguration" #: apps/kbd/kbd_config.c:616 msgid "Daemon running" msgstr "Dämon läuft" #: apps/kbd/kbd_config.c:619 msgid "" "Switch deamon on and off. If you want to start the daemon with each start of " "X, add \"gmerlin_kbd\" to your startup programs" msgstr "" "Schalte den Dämon ein und aus. Wenn Du den Dämon bei jedem Start von X " "starten willst, füge \"gmerlin_kbd\" zu den Startprogrammen hinzu" #: apps/kbd/kbd_config.c:623 msgid "Add new key" msgstr "Taste hinzufügen" #: apps/kbd/kbd_config.c:627 msgid "Delete key" msgstr "Taste löschen" #: apps/alsamixer/g_card.c:637 msgid "Card controls" msgstr "Einstellungen für Karte" #: apps/alsamixer/g_card.c:642 #, c-format msgid "Controls for %s" msgstr "Einstellungen für %s" #: apps/alsamixer/main.c:33 msgid "" "Could not find any Alsa mixers.\n" "Check your setup!\n" msgstr "" "Konnte keine Alsa-Mischer finden.\n" "Überprüfe deine Einstellungen.\n" #: apps/alsamixer/card.c:36 msgid "snd_hctl_elem_read failed" msgstr "snd_hctl_elem_read fehlgeschlagen" #: apps/alsamixer/card.c:47 msgid "snd_hctl_elem_write failed" msgstr "snd_hctl_elem_write fehlgeschlagen" #: apps/alsamixer/card.c:117 msgid "snd_hctl_open failed" msgstr "snd_hctl_open fehlgeschlagen" #: apps/alsamixer/card.c:122 msgid "snd_hctl_load failed" msgstr "snd_hctl_load failed fehlgeschlagen" #: apps/alsamixer/card.c:130 msgid "snd_ctl_card_info_malloc failed" msgstr "snd_ctl_card_info_malloc fehlgeschlagen" #: apps/alsamixer/card.c:135 msgid "snd_ctl_card_info failed" msgstr "snd_ctl_card_info fehlgeschlagen" #: apps/alsamixer/card.c:235 msgid "Unknown" msgstr "Unbekannt" #: apps/alsamixer/g_control.c:863 msgid "Tone" msgstr "Klang" #: apps/alsamixer/g_control.c:894 msgid "Treble" msgstr "Höhen" #: apps/alsamixer/g_control.c:924 msgid "Bass" msgstr "Tiefen" #: apps/alsamixer/g_control.c:1011 msgid "Rec" msgstr "Aufnahmne" #: apps/alsamixer/g_control.c:1057 msgid "Play" msgstr "Abspielen" #: apps/alsamixer/g_control.c:1405 #, c-format msgid "Type %s not handled for %s" msgstr "Typ %s wird nicht behandelt für %s" #: apps/nmjedit/file.c:59 #, fuzzy, c-format msgid "Opening directory %s failed: %s" msgstr "Starten eines Prozesses fehlgeschlagen: %s" #: apps/nmjedit/bgalbum.c:51 tests/album2pls.c:75 lib/mediafiledevice.c:229 #, fuzzy, c-format msgid "Album file %s could not be opened" msgstr "Quellplugin konnte nicht geladen werden" #: apps/nmjedit/bgalbum.c:60 tests/album2pls.c:85 lib/mediafiledevice.c:238 #, c-format msgid "Album file %s contains no entries" msgstr "" #: apps/nmjedit/bgalbum.c:71 #, fuzzy, c-format msgid "No directory found for location %s" msgstr "Kein Plugin gefunden für Bild %s" #: apps/nmjedit/bgalbum.c:93 #, c-format msgid "Clearing existent playlist %s" msgstr "" #: apps/nmjedit/bgalbum.c:149 #, c-format msgid "Song %s not found" msgstr "" #: apps/nmjedit/nmjedit.c:47 #, fuzzy, c-format msgid "SQL query: \"%s\" failed: %s" msgstr "Disk Auswerfen fehlgeschlagen: %s" #: apps/nmjedit/nmjedit.c:431 #, fuzzy, c-format msgid "Adding %s" msgstr "%s hinzufügen" #: apps/nmjedit/nmjedit.c:437 apps/nmjedit/nmjedit.c:488 #, fuzzy, c-format msgid "Scanned %d files" msgstr "Dateien hinzufügen" #: apps/nmjedit/nmjedit.c:484 #, fuzzy, c-format msgid "Updating %s" msgstr "Lade %s" #: apps/nmjedit/nmjedit.c:500 #, c-format msgid "Found %d files in database" msgstr "" #: apps/nmjedit/nmjedit.c:571 #, fuzzy, c-format msgid "Directory %s exists" msgstr "Reinige Verzeichnis beim Beenden" #: apps/nmjedit/nmjedit.c:576 apps/nmjedit/nmjedit.c:601 #, fuzzy, c-format msgid "Directory %s doesn't exist" msgstr "Reinige Verzeichnis beim Beenden" #: apps/nmjedit/nmjedit.c:697 apps/thumbnailer/gmerlin-video-thumbnailer.c:266 #, fuzzy, c-format msgid "No plugin for %s" msgstr "Kein Plugin gefunden für Bild %s" #: apps/nmjedit/nmjedit.c:705 apps/thumbnailer/gmerlin-video-thumbnailer.c:274 #: lib/tree.c:1120 lib/transcoder_track.c:820 lib/transcoder_track.c:831 #: lib/album.c:2270 #, c-format msgid "Loading %s failed" msgstr "Laden von %s fehlgeschlagen" #: apps/nmjedit/nmjedit.c:714 apps/thumbnailer/gmerlin-video-thumbnailer.c:375 #, fuzzy msgid "Writing image header failed" msgstr "Schreibe Abbild" #: apps/nmjedit/nmjedit.c:729 apps/nmjedit/nmjedit.c:738 #: apps/thumbnailer/gmerlin-video-thumbnailer.c:393 #: apps/thumbnailer/gmerlin-video-thumbnailer.c:403 #, fuzzy msgid "Writing image failed" msgstr "Schreibe Abbild" #: apps/nmjedit/nmjedit.c:863 #, fuzzy, c-format msgid "Removing empty genre %s" msgstr "Lösche %s" #: apps/nmjedit/nmjedit.c:898 #, fuzzy, c-format msgid "Removing empty person %s" msgstr "Lösche %s" #: apps/nmjedit/dir.c:115 msgid "Either ID or path must be set in directory\n" msgstr "" #: apps/nmjedit/song.c:150 msgid "Either ID or path must be set in directory" msgstr "" #: apps/nmjedit/song.c:286 #, fuzzy, c-format msgid "Adding song %s" msgstr "Audio: %s" #: apps/nmjedit/song.c:442 #, c-format msgid "Deleting song %s" msgstr "" #: apps/nmjedit/album.c:129 #, fuzzy, c-format msgid "Adding album %s" msgstr "Füge Alben zu %s hinzu" #: apps/nmjedit/album.c:205 #, fuzzy, c-format msgid "Using thumbnail %s" msgstr "Videofilter" #: apps/nmjedit/album.c:302 #, fuzzy, c-format msgid "Removing empty album %s" msgstr "Öffne Album %s" #: apps/nmjedit/album.c:318 #, fuzzy, c-format msgid "Removing thumbnail %s" msgstr "Lösche %s" #: apps/nmjedit/album.c:325 #, fuzzy, c-format msgid "Removing poster %s" msgstr "Lösche %s" #: apps/nmjedit/gmerlin-nmjedit.c:169 msgid "Editor for NMJ2 databases\n" msgstr "" #: apps/recorder/recorder_window.c:502 msgid "Error, check messages and settings" msgstr "" #: apps/recorder/recorder_window.c:620 #, fuzzy msgid "Reopen inputs" msgstr "Neu öffnen" #: apps/recorder/recorder_window.c:624 msgid "Make snapshot" msgstr "" #: apps/recorder/recorder_window.c:631 #, fuzzy msgid "Hide controls" msgstr "Einstellungen für Karte" #: apps/recorder/recorder_window.c:717 #, fuzzy msgid "Recorder configuration" msgstr "Transkoderkonfiguration" #: apps/recorder/recorder_window.c:767 msgid "Snapshots" msgstr "" #: apps/thumbnailer/gmerlin-video-thumbnailer.c:46 #, fuzzy msgid "Option -s requires an argument" msgstr "Option -host erfordert ein Argument" #: apps/thumbnailer/gmerlin-video-thumbnailer.c:58 #, fuzzy msgid "Option -t requires an argument" msgstr "Option -host erfordert ein Argument" #: apps/thumbnailer/gmerlin-video-thumbnailer.c:92 #, fuzzy msgid "[options] video_file thumbnail_file...\n" msgstr "[-co options] quellbild ausgabebild\n" #: apps/thumbnailer/gmerlin-video-thumbnailer.c:93 #, fuzzy msgid "Video thumbnailer\n" msgstr "Videofilter" #: apps/thumbnailer/gmerlin-video-thumbnailer.c:158 #, fuzzy msgid "No input files given" msgstr "Kein Quellplugin definiert" #: apps/thumbnailer/gmerlin-video-thumbnailer.c:169 #, fuzzy, c-format msgid "Cannot stat %s" msgstr "Kann Dateistatus von %s nicht ermitteln: %s" #: apps/thumbnailer/gmerlin-video-thumbnailer.c:200 #, fuzzy, c-format msgid "%s has no tracks" msgstr "CD Audio Track" #: apps/thumbnailer/gmerlin-video-thumbnailer.c:214 #, fuzzy, c-format msgid "File %s has no video" msgstr "Mische aufs Video" #: apps/thumbnailer/gmerlin-video-thumbnailer.c:317 #, fuzzy msgid "Cannot reset stream after failed seek" msgstr "Kann Dauer der Datei %s nicht ermitteln" #: apps/thumbnailer/gmerlin-video-thumbnailer.c:344 #, fuzzy msgid "Couldn't read frame" msgstr "Kann Adresse nicht auflösen" #: apps/thumbnailer/gmerlin-video-thumbnailer.c:416 #, c-format msgid "Successfully saved %s" msgstr "" #: tests/imgconvert.c:95 msgid "[-co options] input_image output_image\n" msgstr "[-co options] quellbild ausgabebild\n" #: tests/imgconvert.c:96 msgid "Image converter\n" msgstr "Bilder Konverter\n" #: tests/fvtest.c:173 #, fuzzy msgid "[options] infile outimage\n" msgstr "[-co options] quellbild ausgabebild\n" #: tests/fvtest.c:174 msgid "Test tool for video filters\n" msgstr "" #: tests/cfgtest.c:622 msgid "[Options]" msgstr "[Optionen]" #: tests/cfgtest.c:623 msgid "Configure test\n" msgstr "Konfigurationstest\n" #: tests/visualization.c:76 msgid "[]\n" msgstr "[]\n" #: tests/visualization.c:77 msgid "Visualize test\n" msgstr "Visualisierungstest\n" #: tests/visualization.c:127 msgid "No input plugin defined" msgstr "Kein Quellplugin definiert" #: tests/visualization.c:134 msgid "Input plugin could not be loaded" msgstr "Quellplugin konnte nicht geladen werden" #: tests/visualization.c:144 msgid "No output plugin defined" msgstr "Kein Ausgabeplugin definiert" #: tests/visualization.c:151 msgid "Output plugin could not be loaded" msgstr "Ausgabeplugin konnte nicht geladen werden" #: tests/visualization.c:168 msgid "Opening input plugin failed" msgstr "Öffnen des Quellplugins fehlgeschlagen" #: tests/gmerlin_visualize.c:154 #, fuzzy msgid "No encoder plugin present" msgstr "Kein Quellplugin definiert" #: tests/gmerlin_visualize.c:160 #, fuzzy, c-format msgid "Cannot load plugin %s" msgstr "Kann Plugin %s nicht finden" #: tests/gmerlin_visualize.c:169 #, fuzzy, c-format msgid "Opening %s failed" msgstr "Speichern von %s fehlgeschlagen" #: tests/gmerlin_visualize.c:208 #, fuzzy, c-format msgid "Starting %s failed" msgstr "Speichern von %s fehlgeschlagen" #: tests/gmerlin_visualize.c:342 msgid "[-w width -h height -fps num:den] infile out_base\n" msgstr "" #: tests/gmerlin_visualize.c:343 msgid "Visualize audio files and save as A/V files\n" msgstr "" #: tests/gmerlin_visualize.c:481 #, fuzzy, c-format msgid "Opened %s" msgstr "Öffnen" # Kann %s nicht öffnen #: tests/gmerlin_visualize.c:517 #, fuzzy msgid "Cannot open encoder" msgstr "Kann %s nicht öffnen" #: lib/recorder_video.c:51 #, c-format msgid "Won't save snapshot %s (file exists)" msgstr "" #: lib/recorder_video.c:55 #, c-format msgid "Saving snapshot %s" msgstr "" #: lib/recorder_video.c:154 #, fuzzy msgid "Record video" msgstr "Aufnahme" #: lib/recorder_video.c:166 msgid "Limit fps" msgstr "" #: lib/recorder_video.c:170 msgid "" "Limit frames per second. By default, the maximum possible framerate will be " "used." msgstr "" #: lib/recorder_video.c:175 msgid "fps limit" msgstr "" #: lib/recorder_video.c:181 msgid "" "Specify the maximum framerate for input plugins, which can capture images " "really fast" msgstr "" #: lib/recorder_video.c:278 #, fuzzy msgid "Enable monitor" msgstr "Verwende Monitor" #: lib/recorder_video.c:369 #, fuzzy msgid "Automatic" msgstr "Automatisch aufnehmen" #: lib/recorder_video.c:374 #, fuzzy msgid "Snapshot interval" msgstr "Aufnahmeintervall" #: lib/recorder_video.c:383 msgid "Overwrite existing files" msgstr "" #: lib/recorder_video.c:710 lib/recorder_audio.c:236 msgid "Read failed (device unplugged?)" msgstr "" #: lib/bggavl.c:393 lib/bggavl.c:411 #, c-format msgid "Unknown scale mode %s\n" msgstr "Unbekannter Skaliermodus: %s\n" #: lib/player_subtitle.c:122 lib/transcoder_track.c:324 #, fuzzy msgid "Time offset" msgstr "Rot Offset" #: lib/transcoder_pp.c:209 #, c-format msgid "Not adding %s: Unsupported filename" msgstr "Füge %s nicht hinzu: Nicht unterstützter Dateiname" #: lib/transcoder_pp.c:218 #, c-format msgid "Scheduling %s for postprocessing" msgstr "Plane %s für Weiterverarbeitung ein" #: lib/transcoder_pp.c:236 msgid "Skipping postprocessing (no suitable files found)" msgstr "Überspringe Weiterverabreitung (keine geeigneten Dateien defunden)" #: lib/player_video.c:143 msgid "Still image framerate" msgstr "Wiederholrate für Standbilder" #: lib/player_video.c:149 #, fuzzy msgid "Set framerate with which still images will be redisplayed periodically" msgstr "Setze die Wiederholrate mit der Stanbilder neu angezeigt werden" #: lib/player_video.c:199 msgid "Restarting playback due to changed video options" msgstr "Starte Abspielen neu wegen geänderter Videoeinstellungen" #: lib/player_video.c:278 lib/player_loop.c:1123 lib/player_audio.c:320 msgid "Detected EOF" msgstr "" #: lib/preset.c:290 #, fuzzy msgid "Cannot make new preset: No home directory" msgstr "Verzeichnis erstellt: %s" #: lib/preset.c:307 #, fuzzy, c-format msgid "Could not create directory: %s" msgstr "Verzeichnis erstellt: %s" #: lib/bgladspa.c:196 msgid "Add effect to input data" msgstr "Addiere Effekt zu den Quelldaten" #: lib/bgladspa.c:206 msgid "Add gain (dB)" msgstr "Additionsverstärkung" #: lib/bgladspa.c:214 msgid "" "Overall gain for this filter. This is only valid if you add the effect to " "the input data" msgstr "" "Gesamtverstärkung für dieses Filter. Dies ist nur gültig, wenn der Effekt " "addiert wird." #: lib/bgladspa.c:264 #, c-format msgid "" "ladspa plugin\n" "Author:\t%s\n" "Copyright:\t%s" msgstr "" "ladspa plugin\n" "Author:\t%s\n" "Copyright:\t%s" #: lib/bgladspa.c:295 lib/bgladspa.c:673 #, c-format msgid "No symbol \"ladspa_descriptor\" found: %s" msgstr "Kein Symbol \"ladspa_descriptor\" gefunden: %s" #: lib/bgladspa.c:390 #, c-format msgid "Remixing to stereo for filter \"%s\"" msgstr "Mische zu Stereo für Filter %s" #: lib/searchpath.c:154 #, fuzzy, c-format msgid "Creating directory %s failed: %s" msgstr "Starten eines Prozesses fehlgeschlagen: %s" #: lib/searchpath.c:160 lib/transcoder.c:1882 #, c-format msgid "Created directory %s" msgstr "Verzeichnis erstellt: %s" #: lib/pluginregistry.c:626 lib/pluginregistry.c:1571 #, c-format msgid "Plugin %s has no or wrong version" msgstr "Plugin %s hat keine oder eine falsche Version" #: lib/pluginregistry.c:632 #, c-format msgid "No symbol the_plugin in %s" msgstr "Kein Symbol \"the_plugin\" in %s" #: lib/pluginregistry.c:636 #, c-format msgid "Plugin %s has zero priority" msgstr "Plugin %s hat Null als Priorität" #: lib/pluginregistry.c:647 #, fuzzy, c-format msgid "Not loading %s (blacklisted)" msgstr "Laden von %s fehlgeschlagen" #: lib/pluginregistry.c:749 lib/pluginregistry.c:1560 #, c-format msgid "dlopen failed for %s: %s" msgstr "dlopen fehlgeschlagen für %s: %s" #: lib/pluginregistry.c:1343 #, c-format msgid "bg_plugin_ref %s: %d" msgstr "bg_plugin_ref %s: %d" #: lib/pluginregistry.c:1407 #, c-format msgid "bg_plugin_unref_nolock %s: %d" msgstr "bg_plugin_unref_nolock %s: %d" #: lib/pluginregistry.c:1418 #, c-format msgid "bg_plugin_unref %s: %d" msgstr "bg_plugin_unref %s: %d" #: lib/pluginregistry.c:1443 lib/pluginregistry.c:1497 #, c-format msgid "No plugin found for image %s" msgstr "Kein Plugin gefunden für Bild %s" #: lib/pluginregistry.c:1578 #, fuzzy, c-format msgid "dlsym failed for %s: %s" msgstr "dlopen fehlgeschlagen für %s: %s" #: lib/pluginregistry.c:1666 msgid "Invalid plugin type for video output" msgstr "Ungültiger Plugintyp für Videoausgabe" #: lib/pluginregistry.c:1673 #, c-format msgid "Plugin %s doesn't support embedded windows" msgstr "Plugin %s unterstützt keine eingebetteten Fenster" #: lib/pluginregistry.c:1921 #, c-format msgid "Loading plugin \"%s\" failed" msgstr "Laden von Plugin \"%s\" fehlgeschlagen" #: lib/pluginregistry.c:1933 lib/pluginregistry.c:1970 #, c-format msgid "Opening %s with \"%s\" failed" msgstr "Öffnen von %s mit \"%s\" fehlgeschlagen" #: lib/pluginregistry.c:2147 lib/pluginregistry.c:2630 #, fuzzy msgid "Overlay subtitles" msgstr "Overlay Unrertitel Voreinstellungen" #: lib/pluginregistry.c:2302 msgid "Registry settings" msgstr "" #: lib/pluginregistry.c:2309 #, fuzzy msgid "Plugin settings" msgstr "Pluginoptionen" #: lib/pluginregistry.c:2316 lib/gtk/plugin_multi.c:402 msgid "Extensions" msgstr "Erweiterungen" #: lib/pluginregistry.c:2323 lib/gtk/plugin_multi.c:394 msgid "Protocols" msgstr "Protokolle" #: lib/pluginregistry.c:2330 lib/gtk/plugin_multi.c:384 msgid "Priority" msgstr "Priorität" #: lib/pluginregistry.c:2588 msgid "Write audio stream to video file if possible" msgstr "" #: lib/pluginregistry.c:2595 #, fuzzy msgid "Write text subtitles to video file if possible" msgstr "Schreibe Textuntertitel in die Videodatei" #: lib/pluginregistry.c:2602 #, fuzzy msgid "Write overlay subtitles to video file if possible" msgstr "Schreibe Oberlayuntertitel in die Videodatei" #: lib/visualize_slave.c:298 #, fuzzy, c-format msgid "Cannot dlopen plugin module %s: %s" msgstr "Kann Datei %s nicht öffnen: %s" #: lib/visualize_slave.c:307 #, fuzzy, c-format msgid "cannot get API version: %s" msgstr "Kann Dauer der Datei %s nicht ermitteln" #: lib/visualize_slave.c:313 #, c-format msgid "Wrong API version: Got %d expected %d" msgstr "" #: lib/visualize_slave.c:321 #, fuzzy, c-format msgid "No symbol the_plugin: %s" msgstr "Kein Symbol \"the_plugin\" in %s" #: lib/visualize_slave.c:431 msgid "No window ID given" msgstr "" #: lib/visualize_slave.c:436 #, fuzzy msgid "No plugin given" msgstr "Kein Quellplugin definiert" #: lib/visualize_slave.c:674 msgid "Joined thread" msgstr "Thread beendet" #: lib/visualize_slave.c:693 msgid "Started thread" msgstr "Thread gestarted" #: lib/visualize_slave.c:929 #, fuzzy msgid "Starting visualization failed" msgstr "Starten des Quellplugins fehlgeschlagen" #: lib/visualize.c:110 lib/visualize.c:130 lib/visualize.c:597 msgid "Visualization process crashed, restart to try again" msgstr "" "Visualisierungsprozess abgestürzt, starte neu um es noch einmal zu versuchen" #: lib/visualize.c:336 msgid "Width" msgstr "Breite" #: lib/visualize.c:342 msgid "" "Desired image with, the visualization plugin might override this for no " "apparent reason" msgstr "" "Gewünschte Bildbreite. Das Visualisierungsplugin kann dies ohne erkennbaren " "Grund überschreiben." #: lib/visualize.c:346 msgid "Height" msgstr "Höhe" #: lib/visualize.c:352 msgid "" "Desired image height, the visualization plugin might override this for no " "apparent reason" msgstr "" "Gewünschte Bildhöhe. Das Visualisierungsplugin kann dies ohne erkennbaren " "Grund überschreiben." #: lib/visualize.c:366 msgid "Gain" msgstr "Verstärkung" #: lib/visualize.c:373 msgid "" "Gain (in dB) to apply to the audio samples before it is sent to the " "visualization plugin" msgstr "" "Verstärkung (in dB) für die Audio Abtastwerte, bevor sie zum " "Visualisierungsplugin geschickt werden" #: lib/visualize.c:392 #, c-format msgid "Got visualization plugin %s" msgstr "Visualisierungsplugin erhalten: %s" #: lib/thumbnail.c:134 lib/bgxml.c:77 #, c-format msgid "Cannot stat %s: %s" msgstr "Kann Dateistatus von %s nicht ermitteln: %s" #: lib/thumbnail.c:143 #, fuzzy msgid "Cannot get home directory" msgstr "Verzeichnis erstellt: %s" #: lib/formats.c:33 msgid "Zero" msgstr "Null" #: lib/formats.c:63 #, c-format msgid "" "Channels: %d\n" "Channel order: %s\n" "Samplerate: %d\n" "Samples per frame: %d\n" "Interleave Mode: %s\n" "Sample format: %s" msgstr "" "Kanäle: %d\n" "Kanalreihenfolge: %s\n" "Abtastfrequenz: %d\n" "Abtastwerte pro Rahmen: %d\n" "Interleave Modus: %s\n" "Zahlenformat: %s" #: lib/formats.c:65 #, c-format msgid "" "Channels:\t %d\n" "Channel order\t %s\n" "Samplerate:\t %d\n" "Samples per frame:\t %d\n" "Interleave Mode:\t %s\n" "Sample format:\t %s" msgstr "" "Kanäle:\t %d\n" "Kanalreihenfolge:\t %s\n" "Abtastfrequenz:\t %d\n" "Abtastwerte pro Rahmen:\t %d\n" "Interleave Modus:\t %s\n" "Zahlenformat:\t %s" #: lib/formats.c:85 #, c-format msgid "" "Frame size: %d x %d\n" "Image size: %d x %d\n" "Pixel size: %d x %d\n" "Pixel format: %s\n" msgstr "" "Rahmengröße: %d x %d\n" "Bildgröße: %d x %d\n" "Pixelgröße: %d x %d\n" "Pixelformat: %s\n" #: lib/formats.c:87 #, c-format msgid "" "Frame size:\t %d x %d\n" "Image size:\t %d x %d\n" "Pixel size:\t %d x %d\n" "Pixel format:\t %s\n" msgstr "" "Rahmengröße:\t %d x %d\n" "Bildgröße:\t %d x %d\n" "Pixelgröße:\t %d x %d\n" "Pixelformat:\t %s\n" #: lib/formats.c:98 msgid "Still image\n" msgstr "Standbild\n" #: lib/formats.c:104 #, c-format msgid "Framerate: Variable (timescale: %d)\n" msgstr "" #: lib/formats.c:106 #, c-format msgid "Framerate:\tVariable (timescale: %d)\n" msgstr "" #: lib/formats.c:115 #, c-format msgid "Framerate: %f fps [%d / %d]%s\n" msgstr "Bildwiderholrate: %f fps [%d / %d]%s\n" #: lib/formats.c:117 #, c-format msgid "Framerate:\t%f fps [%d / %d]%s\n" msgstr "Bildwiderholrate:\t %f fps [%d / %d]%s\n" #: lib/formats.c:123 msgid " (constant)" msgstr "(konstant)" #: lib/formats.c:124 msgid " (variable)" msgstr " (variabel)" #: lib/formats.c:130 #, c-format msgid "Interlace mode: %s" msgstr "Interlacemodus: %s" #: lib/formats.c:132 #, c-format msgid "Interlace mode:\t%s" msgstr "Interlacemodus:\t%s" #: lib/formats.c:143 #, c-format msgid "" "\n" "Chroma placement: %s" msgstr "" "\n" "Farbebenenplatzierung: %s" #: lib/formats.c:145 #, c-format msgid "" "\n" "Chroma placement:\t%s" msgstr "" "\n" "Farbebenenplatzierung:\t%s" #: lib/formats.c:154 #, c-format msgid "" "\n" "Timecode rate: %d" msgstr "" "\n" "Timecoderate: %d" #: lib/formats.c:156 #, c-format msgid "" "\n" "Timecode rate:\t%d" msgstr "" "\n" "Timecoderate:\t%d" #: lib/formats.c:164 msgid "" "\n" "Timecode flags: " msgstr "" "\n" "Timecodeflags: " #: lib/formats.c:166 msgid "" "\n" "Timecode flags:\t" msgstr "" "\n" "Timecodeflags:\t" #: lib/formats.c:171 msgid "Drop " msgstr "Drop" #: lib/formats.c:184 msgid "Unknown channel" msgstr "Unbekannter Kanal" #: lib/formats.c:185 msgid "Front C" msgstr "Vorne C" #: lib/formats.c:186 msgid "Front L" msgstr "Vorne L" #: lib/formats.c:187 msgid "Front R" msgstr "Vorne R" #: lib/formats.c:188 msgid "Front CL" msgstr "Vorne CL" #: lib/formats.c:189 msgid "Front CR" msgstr "Vorne CR" #: lib/formats.c:190 msgid "Rear C" msgstr "Hinten C" #: lib/formats.c:191 msgid "Rear L" msgstr "Hinten L" #: lib/formats.c:192 msgid "Rear R" msgstr "Hinten R" #: lib/formats.c:193 msgid "Side L" msgstr "Seite L" #: lib/formats.c:194 msgid "Side R" msgstr "Seite R" #: lib/formats.c:196 msgid "AUX" msgstr "AUX" #: lib/formats.c:200 msgid "Not specified" msgstr "Unspezifiziert" #: lib/formats.c:201 msgid "Unsigned 8 bit" msgstr "Vorzeichenlos 8 bit" #: lib/formats.c:202 msgid "Signed 8 bit" msgstr "8 bit mit Vorzeichen" #: lib/formats.c:203 msgid "Unsigned 16 bit" msgstr "Vorzeichenlos 16 bit" #: lib/formats.c:204 msgid "Signed 16 bit" msgstr "16 bit mit Vorzeichen" #: lib/formats.c:205 msgid "Signed 32 bit" msgstr "32 bit mit Vorzeichen" #: lib/formats.c:206 msgid "Floating point" msgstr "Fließkomma" #: lib/formats.c:207 msgid "Double precision" msgstr "Doppelte Genauigkeit" #: lib/formats.c:210 msgid "Not interleaved" msgstr "Nicht interleaved" #: lib/formats.c:211 msgid "Interleaved channel pairs" msgstr "Interleavte Kanalpaare" #: lib/formats.c:212 msgid "All channels interleaved" msgstr "Alle Kanäle interleaved" #: lib/formats.c:216 msgid "None (Progressive)" msgstr "Keiner (progressiv)" #: lib/formats.c:217 msgid "Top field first" msgstr "Oberes Feld zuerst" #: lib/formats.c:218 msgid "Bottom field first" msgstr "Unteres Feld zuerst" #: lib/formats.c:219 msgid "Mixed" msgstr "Gemischt" #: lib/formats.c:222 msgid "MPEG-1/JPEG" msgstr "MPEG-1/JPEG" #: lib/formats.c:223 msgid "MPEG-2" msgstr "MPEG-2" #: lib/formats.c:224 msgid "DV PAL" msgstr "DV PAL" #: lib/formats.c:228 msgid "15 bpp RGB" msgstr "15 bpp RGB" #: lib/formats.c:229 msgid "15 bpp BGR" msgstr "15 bpp BGR" #: lib/formats.c:230 msgid "16 bpp RGB" msgstr "16 bpp RGB" #: lib/formats.c:231 msgid "16 bpp BGR" msgstr "16 bpp BGR" #: lib/formats.c:232 msgid "24 bpp RGB" msgstr "24 bpp RGB" #: lib/formats.c:233 msgid "24 bpp BGR" msgstr "24 bpp BGR" #: lib/formats.c:234 msgid "32 bpp RGB" msgstr "32 bpp RGB" #: lib/formats.c:235 msgid "32 bpp BGR" msgstr "32 bpp BGR" #: lib/formats.c:236 msgid "32 bpp RGBA" msgstr "32 bpp RGBA" #: lib/formats.c:237 msgid "48 bpp RGB" msgstr "48 bpp RGB" #: lib/formats.c:238 msgid "64 bpp RGBA" msgstr "64 bpp RGBA" #: lib/formats.c:239 msgid "Float RGB" msgstr "Fließkomma RGB" #: lib/formats.c:240 msgid "Float RGBA" msgstr "Fließkomma RGBA" #: lib/formats.c:241 msgid "YUV 422 (YUY2)" msgstr "YUV 422 (YUY2)" #: lib/formats.c:242 msgid "YUV 422 (UYVY)" msgstr "YUV 422 (UYVY)" #: lib/formats.c:243 msgid "YUVA 4444" msgstr "YUVA 4444" #: lib/formats.c:244 msgid "YUV 420 Planar" msgstr "YUV 420 Planar" #: lib/formats.c:245 msgid "YUV 410 Planar" msgstr "YUV 410 Planar" #: lib/formats.c:246 msgid "YUV 411 Planar" msgstr "YUV 411 Planar" #: lib/formats.c:247 msgid "YUV 422 Planar" msgstr "YUV 422 Planar" #: lib/formats.c:248 msgid "YUV 422 Planar (16 bit)" msgstr "YUV 422 Planar (16 bit)" #: lib/formats.c:249 msgid "YUV 444 Planar" msgstr "YUV 444 Planar" #: lib/formats.c:250 msgid "YUV 444 Planar (16 bit)" msgstr "YUV 444 Planar (16 bit)" #: lib/formats.c:251 msgid "YUVJ 420 Planar" msgstr "YUVJ 420 Planar" #: lib/formats.c:252 msgid "YUVJ 422 Planar" msgstr "YUVJ 422 Planar" #: lib/formats.c:253 msgid "YUVJ 444 Planar" msgstr "YUVJ 444 Planar" #: lib/formats.c:254 msgid "Undefined" msgstr "Undefiniert" #: lib/cmdline.c:221 msgid "Copyright (C) 2001-2007 Members of the gmerlin project\n" msgstr "Copyright (C) 2001-2007 Mitglieder des gmerlin projekts\n" #: lib/cmdline.c:222 msgid "" "This is free software. You may redistribute copies of it under the terms " "of\n" "the GNU General Public License .\n" "There is NO WARRANTY.\n" msgstr "" "Dies ist freie Software, die unter den Bedingungen der GNU General Public " "License weitergegeben werden kann.\n" "Es gibt KEINE HAFTUNG.\n" #: lib/cmdline.c:290 msgid "Print this help message and exit" msgstr "Gib diese Hilfe aus und beende" #: lib/cmdline.c:295 msgid "Print this help message as a manual page and exit" msgstr "Gib diese Hilfe als Manualpage aus und beende" #: lib/cmdline.c:300 msgid "Print this help message in texinfo format and exit" msgstr "Gib diese Hilfe im texinfo-Format aus und beende" #: lib/cmdline.c:305 msgid "Print version info and exit" msgstr "Gib Version aus und beende" #: lib/cmdline.c:338 msgid "" "Environment variables\n" "\n" msgstr "" "Umgebungsvariablen\n" "\n" #: lib/cmdline.c:352 msgid "" "Files\n" "\n" msgstr "" "Dateien\n" "\n" #: lib/cmdline.c:416 msgid ".SH ENVIRONMENT VARIABLES\n" msgstr ".SH UMGEBUNGSVARIABLEN\n" #: lib/cmdline.c:431 msgid ".SH FILES\n" msgstr ".SH DATEIEN\n" #: lib/cmdline.c:470 msgid "@item Environment variables\n" msgstr "@item Umgebungsvariablen\n" #: lib/cmdline.c:484 msgid "@item Files\n" msgstr "@item Dateien\n" #: lib/cmdline.c:697 msgid "" "Supported options:\n" "\n" msgstr "" "Unterstützte Optionen:\n" "\n" #: lib/cmdline.c:777 #, c-format msgid "[1|0] (default: %d)" msgstr "[1|0] (Voreinstellung: %d)" #: lib/cmdline.c:786 lib/cmdline.c:800 msgid " (" msgstr " (" #: lib/cmdline.c:792 #, c-format msgid "default: %d)" msgstr "Voreinstellung: %d)" #: lib/cmdline.c:811 #, c-format msgid "default: %%.%df)" msgstr "Voreinstellung: %%.%df)" #: lib/cmdline.c:827 lib/cmdline.c:840 lib/cmdline.c:847 msgid "" msgstr "" #: lib/cmdline.c:830 #, c-format msgid " (Default: %s)" msgstr " (Voreinstellung: %s)" #: lib/cmdline.c:857 msgid "Supported strings: " msgstr "Unterstützte Kennzeichner:" #: lib/cmdline.c:879 lib/cmdline.c:960 #, c-format msgid "Default: %s" msgstr "Voreinstellung: %s" #: lib/cmdline.c:886 #, c-format msgid ",, (default: %.3f,%.3f,%.3f)" msgstr ",, (Voreinstellung: %.3f,%.3f,%.3f)" #: lib/cmdline.c:897 lib/cmdline.c:1029 msgid ", and are in the range 0.0..1.0" msgstr ", und sind im Bereich 0.0..1.0" #: lib/cmdline.c:904 #, c-format msgid ",,, (default: %.3f,%.3f,%.3f,%.3f)" msgstr ",,, (Voreinstellung: %.3f,%.3f,%.3f,%.3f)" #: lib/cmdline.c:916 msgid ", , and are in the range 0.0..1.0" msgstr ", und sind im Bereich 0.0..1.0" #: lib/cmdline.c:923 msgid "option[{suboptions}]" msgstr "option[{unteroptionen}]" #: lib/cmdline.c:932 lib/cmdline.c:978 msgid "Supported options: " msgstr "Unterstützte Optionen: " #: lib/cmdline.c:954 #, fuzzy msgid "" msgstr "Kein(s)" #: lib/cmdline.c:966 msgid "{option[{suboptions}][:option[{suboptions}]...]}" msgstr "{option[{unteroptionen}][:option[{unteroptionen}]...]}" #: lib/cmdline.c:998 msgid "{[[HH:]MM:]SS} (" msgstr "{[[HH:]MM:]SS} (" #: lib/cmdline.c:1008 #, c-format msgid "default: %s)" msgstr "Voreinstellung: %s)" #: lib/cmdline.c:1016 msgid "Seconds can be fractional (i.e. with decimal point)\n" msgstr "Sekunden können gebrochen sein (d.h. mit Dezimalpunkt)\n" #: lib/cmdline.c:1019 #, c-format msgid ", (default: %.3f,%.3f)" msgstr ", (Voreinstellung: %.3f,%.3f)" #: lib/cmdline.c:1068 lib/cmdline.c:1071 #, c-format msgid "Suboptions for %s=%s" msgstr "Unteroptionen %s=%s" #: lib/cmdline.c:1076 #, c-format msgid "Suboptions for %s" msgstr "Unteroptionen für %s" #: lib/ov.c:181 #, c-format msgid "Using hardeware overlay for stream %d" msgstr "" #: lib/ov.c:190 #, c-format msgid "Using software overlay for stream %d" msgstr "" #: lib/converters.c:331 lib/converters.c:338 #, fuzzy msgid "variable" msgstr " (variabel)" #: lib/converters.c:344 #, fuzzy, c-format msgid "Doing framerate conversion %s -> %s" msgstr "Ändere Bildwiederholfrequenz %5.2f (%s) -> %5.2f (%s)" #: lib/converters.c:373 #, c-format msgid "Initialized video converter, %d steps" msgstr "Initialisierte Videokonverter (%d Schritte)" #: lib/mediafiledevice.c:116 lib/metadata.c:59 msgid "Album" msgstr "Album" #: lib/mediafiledevice.c:121 #, fuzzy msgid "Shuffle" msgstr "Zufallswiedergabe" #: lib/mediafiledevice.c:222 #, fuzzy msgid "No album file given" msgstr "Kein Quellplugin definiert" #: lib/mediafiledevice.c:259 #, c-format msgid "Album file %s contains no usable entries" msgstr "" #: lib/mediafiledevice.c:295 msgid "Reloading album (file changed)" msgstr "" #: lib/mediafiledevice.c:488 #, fuzzy msgid "Audiofile recorder" msgstr "Audiorecorder" #: lib/mediafiledevice.c:489 msgid "" "Take a bunch of audio file and make them available as a recording device" msgstr "" #: lib/lcdproc.c:106 msgid "Enable LCDproc" msgstr "Schalte LCDproc ein" #: lib/lcdproc.c:112 msgid "Hostname" msgstr "Rechnername" #: lib/lcdproc.c:126 msgid "Display track name and time" msgstr "Zeige Name und Zeit an" #: lib/lcdproc.c:132 msgid "Display audio/video formats" msgstr "Zeige Audio- und Videoformate an" #: lib/lcdproc.c:138 msgid "Display audio/video descriptions" msgstr "Zeige Audio- und Videobeschreibnungen an" #: lib/lcdproc.c:165 lib/lcdproc.c:170 msgid "Sending command failed" msgstr "Befehl schicken fehlgeschlagen" #: lib/lcdproc.c:193 #, c-format msgid "Command \"%s\" not unserstood by server" msgstr "Befehl \"%s\" vom Server nicht verstanden" #: lib/lcdproc.c:214 #, c-format msgid "Could not resolve adress for: %s" msgstr "Konnte Adresse nicht auflösen für %s" #: lib/lcdproc.c:221 #, c-format msgid "Could not connect to server at %s:%d" msgstr "Konnte keine Verbindung zum Server %s:%d aufbauen" #: lib/lcdproc.c:231 msgid "Could not send hello message" msgstr "Konnte keine \"hello\" Nachricht schicken" #: lib/lcdproc.c:237 msgid "Could not get server welcome line" msgstr "Konnte keine \"welcome\" Zeile bekommen" #: lib/lcdproc.c:246 #, c-format msgid "Invalid answer: %s" msgstr "Ungültige Antwort: %s" #: lib/lcdproc.c:278 #, c-format msgid "Connection to server established, display size: %dx%d" msgstr "Verbindung zum Server hergestellt, Displaygröße: %dx%d" #: lib/lcdproc.c:290 lib/lcdproc.c:837 msgid "Connection to server closed due to error" msgstr "Verbindung zum Server aufgrund eines Fehlers geschlossen" #: lib/lcdproc.c:931 msgid "Server connection closed" msgstr "Serververbindung beendet" #: lib/player_loop.c:291 #, fuzzy msgid "Cannot pause live stream" msgstr "Kann Datei %s nicht öffnen" #: lib/player_loop.c:1200 msgid "Ignoring command while playback is interrupted" msgstr "Ignoriere Befehl während das Absplielen unterbrochen ist" #: lib/charset.c:97 msgid "Invalid Multibyte sequence" msgstr "Ungültige Multibyte-Sequenz" #: lib/charset.c:101 msgid "Incomplete Multibyte sequence" msgstr "Unvollständige Multibyte-Sequenz" #: lib/transcoder.c:507 #, c-format msgid "Transcoding took %s (%.2f %% of realtime duration)" msgstr "" #: lib/transcoder.c:517 msgid "Output Directory" msgstr "Ausgabeverzeichnis" #: lib/transcoder.c:523 msgid "Delete incomplete output files" msgstr "Lösche unvollständige Ausgabedateien" #: lib/transcoder.c:526 msgid "" "Delete the encoded files if you hit the stop button. This option will " "automatically be disabled, when the track is an URL" msgstr "" "Lösche enkodierte Dateien wenn Du den \"Stop\"-Button drückst. Diese Option " "wird automatisch deaktiviert, wenn der Track eine URL ist." #: lib/transcoder.c:531 msgid "Clean up after postprocessing" msgstr "Aufräumen nach der Weiterverarbeitung" #: lib/transcoder.c:533 msgid "Clean up all encoded files, which were postprocessed" msgstr "Lösche alle enkodierten Dateien, die weiterverarbeitet wurden" #: lib/transcoder.c:537 msgid "Send finished files to player" msgstr "Schicke fertige Dateien zum Player" #: lib/transcoder.c:1212 #, c-format msgid "Using statistics file: %s" msgstr "Benutze Statistikdatei: %s" #: lib/transcoder.c:1347 msgid "Encoding audio failed" msgstr "Ton Enkodieren fehlgeschlagen" #: lib/transcoder.c:1666 msgid "Encoding video failed" msgstr "Bild Enkodieren fehlgeschlagen" #: lib/transcoder.c:1756 lib/transcoder.c:1809 msgid "Encoding subtitles failed" msgstr "Untertitel Enkodieren fehlgeschlagen" #: lib/transcoder.c:1876 #, c-format msgid "Cannot create directory %s: %s, using default" msgstr "Kann Verzeichnis %s nicht erstellen: %s, nehme Voreinstellung" #: lib/transcoder.c:1933 #, c-format msgid "Postprocessing %s" msgstr "Weiterverarbeitung von %s" #: lib/transcoder.c:1937 lib/transcoder.c:3184 #, c-format msgid "Transcoding %s [Track %d, Pass %d/%d]" msgstr "Transkodiere %s [Track %d, Durchgang %d/%d]" #: lib/transcoder.c:1942 #, c-format msgid "Transcoding %s [Track %d]" msgstr "Transkodiere %s [Track %d]" #: lib/transcoder.c:1953 #, c-format msgid "" "Metadata:\n" "%s" msgstr "" "Metadaten:\n" "%s" #: lib/transcoder.c:1970 #, c-format msgid "" "Audio stream %d input format:\n" "%s" msgstr "" "Audiostream %d, Quellformat:\n" "%s" #: lib/transcoder.c:1976 #, c-format msgid "" "Audio stream %d output format:\n" "%s" msgstr "" "Audiostream %d, Ausgabeformat:\n" "%s" #: lib/transcoder.c:1984 #, fuzzy, c-format msgid "" "Audio stream %d format:\n" "%s" msgstr "" "Audiostream %d, Quellformat:\n" "%s" #: lib/transcoder.c:1999 #, c-format msgid "" "Video stream %d input format:\n" "%s" msgstr "" "Videostream %d, Quellformat:\n" "%s" #: lib/transcoder.c:2004 #, c-format msgid "" "Video stream %d output format:\n" "%s" msgstr "" "Videostream %d, Ausgabeformat:\n" "%s" #: lib/transcoder.c:2011 #, fuzzy, c-format msgid "" "Video stream %d format:\n" "%s" msgstr "" "Videostream %d, Quellformat:\n" "%s" #: lib/transcoder.c:2023 #, c-format msgid "Text subtitle stream %d: Blending onto video stream %d" msgstr "Text-Untertitelstream %d: Mische auf Videostream %d" #: lib/transcoder.c:2028 #, c-format msgid "Text subtitle stream %d: Exporting to file" msgstr "Text-Untertitelstream %d: Exportiere in Datei" #: lib/transcoder.c:2042 #, fuzzy, c-format msgid "Overlay subtitle stream %d: Blending onto video stream %d" msgstr "Text-Untertitelstream %d: Mische auf Videostream %d" #: lib/transcoder.c:2047 #, fuzzy, c-format msgid "Overlay subtitle stream %d: Exporting to file" msgstr "Text-Untertitelstream %d: Exportiere in Datei" #: lib/transcoder.c:2093 #, c-format msgid "Cannot find plugin %s" msgstr "Kann Plugin %s nicht finden" #: lib/transcoder.c:2124 #, c-format msgid "Invalid track number %d" msgstr "Ungültige Tracknummer %d" #: lib/transcoder.c:2154 #, fuzzy, c-format msgid "Audio stream %d cannot be read compressed" msgstr "Audiostream %d: %s Abtastwerte transkodiert" #: lib/transcoder.c:2164 #, fuzzy, c-format msgid "Audio stream %d cannot be written compressed" msgstr "Audiostream %d: %s Abtastwerte transkodiert" #: lib/transcoder.c:2169 #, c-format msgid "Copying compressed audio stream %d" msgstr "" #: lib/transcoder.c:2183 #, fuzzy, c-format msgid "Video stream %d cannot be read compressed" msgstr "Videostream %d: %s Bilder transkodiert" #: lib/transcoder.c:2195 lib/transcoder.c:2210 #, c-format msgid "Not copying video stream %d: Will blend subtitles" msgstr "" #: lib/transcoder.c:2223 #, fuzzy, c-format msgid "Video stream %d cannot be written compressed" msgstr "Videostream %d: %s Bilder transkodiert" #: lib/transcoder.c:2228 #, c-format msgid "Copying compressed video stream %d" msgstr "" #: lib/transcoder.c:2351 lib/player_input.c:219 msgid "Starting input plugin failed" msgstr "Starten des Quellplugins fehlgeschlagen" #: lib/transcoder.c:2361 lib/transcoder.c:2370 msgid "Cannot seek to start point" msgstr "Kann nicht zum Startpunkt suchen" #: lib/transcoder.c:2381 msgid "End time if before start time" msgstr "Endzeit vor Anfangszeit" #: lib/transcoder.c:2543 lib/transcoder.c:2591 msgid "Subtitle stream cannot be handled" msgstr "Untertitelstream kann nicht verarbeitet werden" #: lib/transcoder.c:2612 msgid "Input and output are the same file" msgstr "Quelle und Ausgabe sind die gleiche Datei" #: lib/transcoder.c:2924 msgid "Zero peaks detected (silent file?). Disabling normalization." msgstr "Null Spitzenwerte detektiert (stumme Datei?). Deaktiviere Normierung" #: lib/transcoder.c:2930 #, c-format msgid "Correcting volume by %.2f dB" msgstr "Korrigiere Lautstärke um %.2f dB" #: lib/transcoder.c:2989 msgid "No stream to encode" msgstr "Kein Stream zum Enkodieren" #: lib/transcoder.c:3393 #, c-format msgid "Video stream %d: Transcoded %s frames" msgstr "Videostream %d: %s Bilder transkodiert" #: lib/transcoder.c:3404 #, c-format msgid "Audio stream %d: Transcoded %s samples" msgstr "Audiostream %d: %s Abtastwerte transkodiert" #: lib/x11/xvideo.c:120 #, c-format msgid "Visual and depth not supported by adaptor %d" msgstr "" #: lib/x11/xvideo.c:253 #, fuzzy msgid "Image width out of range" msgstr "Audiosuche reichte außerhalb des Bereichs" #: lib/x11/xvideo.c:258 #, fuzzy msgid "Image height out of range" msgstr "Audiosuche reichte außerhalb des Bereichs" #: lib/x11/xvideo.c:268 #, c-format msgid "Using XV format: %c%c%c%c" msgstr "" #: lib/x11/xvideo.c:280 #, fuzzy msgid "No suitable pixelformat" msgstr "Nicht unterstütztes Zahlenformat" #: lib/x11/xvideo.c:295 #, c-format msgid "Port %li already grabbed, trying next one" msgstr "" #: lib/x11/xvideo.c:300 #, c-format msgid "Grabbing Port %li failed (invalid time), trying next one" msgstr "" #: lib/x11/xvideo.c:305 #, c-format msgid "Grabbing Port %li failed (unknown error)" msgstr "" #: lib/x11/xvideo.c:316 #, fuzzy msgid "Could not find free port" msgstr "Kann Socket nicht binden" #: lib/x11/x11_video.c:233 #, c-format msgid "Trying %s driver" msgstr "" #: lib/x11/x11_video.c:237 #, fuzzy, c-format msgid "Opening %s driver failed" msgstr "Speichern von %s fehlgeschlagen" #: lib/x11/x11_video.c:245 #, fuzzy, c-format msgid "Opening %s driver succeeded" msgstr "Speichern von %s fehlgeschlagen" #: lib/x11/x11_window.c:1116 msgid "Auto resize window" msgstr "Fenstergröße automatisch ändern" #: lib/x11/x11_window.c:1150 msgid "Disable Screensaver for normal playback" msgstr "Deaktiviere Bildschirmschoner für normales Abspielen" #: lib/x11/x11_window.c:1156 msgid "Disable Screensaver for fullscreen playback" msgstr "Deaktiviere Bildschirmschoner für Abspielen im Vollbildmodus" #: lib/x11/x11_window.c:1162 msgid "Force hardware scaling" msgstr "Erzwinge Hardwareskalierung" #: lib/x11/x11_window.c:1164 msgid "" "Use hardware scaling even if it involves more CPU intensive pixelformat " "conversions" msgstr "" "Benutze Hardwareskalierung auch wenn es mehr rechenaufwendige Pixelformat-" "Umwandlungen erfordert" #: lib/x11/x11_window.c:1173 msgid "" "Specify the background color for videos with alpha channel. This is only " "used by the OpenGL driver." msgstr "" #: lib/x11/x11_window.c:1179 msgid "Software scaler" msgstr "Softwareskalierer" #: lib/x11/x11_window.c:1218 lib/x11/x11_window.c:1223 msgid "Scale quality" msgstr "Skalierungsqualität" #: lib/x11/x11_window.c:1389 msgid "Could not get GL Visual" msgstr "Kein GL Visual erhalten" #: lib/x11/x11_window.c:1404 #, c-format msgid "Got Visual 0x%lx depth %d" msgstr "" #: lib/x11/x11_gl.c:75 msgid "GLX extension missing" msgstr "" #: lib/x11/x11_gl.c:82 #, c-format msgid "GLX version too old: requested >= 1.3 but got %d.%d" msgstr "" #: lib/x11/x11_gl.c:88 #, c-format msgid "Got GLX version %d.%d" msgstr "" #: lib/x11/x11_gl.c:127 msgid "No framebuffer configs found (insufficient driver or hardware)" msgstr "" #: lib/x11/grab.c:57 msgid "Grab from root window" msgstr "" #: lib/x11/grab.c:62 msgid "Draw cursor" msgstr "" #: lib/x11/grab.c:68 msgid "Keep grab window on top" msgstr "" #: lib/x11/grab.c:74 msgid "Make grab window sticky" msgstr "" #: lib/x11/grab.c:80 #, fuzzy msgid "Disable screensaver" msgstr "Schalte Paranoia aus." #: lib/x11/grab.c:83 msgid "Disable screensaver and energy saving mode" msgstr "" #: lib/x11/grab.c:602 #, c-format msgid "Window geometry: %dx%d+%d+%d" msgstr "" #: lib/x11/grab.c:673 #, fuzzy msgid "Couldn't get shared memory segment" msgstr "Konnte keine \"welcome\" Zeile bekommen" #: lib/x11/grab.c:681 msgid "Couldn't attach shared memory segment" msgstr "" #: lib/x11/grab.c:687 msgid "Using shared memory for grabbing" msgstr "" #: lib/x11/grab.c:776 #, c-format msgid "Cursor too wide, increase MAX_CURSOR_SIZE in grab.c to %d" msgstr "" #: lib/x11/grab.c:783 #, c-format msgid "Cursor too high, increase MAX_CURSOR_SIZE in grab.c to %d" msgstr "" #: lib/x11/grab.c:903 msgid "XShmGetImage failed" msgstr "" #: lib/x11/shm.c:87 #, fuzzy msgid "Cannot create shared memory" msgstr "Kann Socket nicht erzeugen" #: lib/textrenderer.c:163 msgid "Default format" msgstr "Voreingestelltes Format" #: lib/textrenderer.c:168 msgid "Default width" msgstr "Voreingestellte Breite" #: lib/textrenderer.c:176 msgid "Default height" msgstr "Voreingestellte Höhe" #: lib/textrenderer.c:184 msgid "Default Colorspace" msgstr "Voreingestellter Farbraum" #: lib/textrenderer.c:188 msgid "YCrCb" msgstr "YCrCb" #: lib/textrenderer.c:188 msgid "RGB" msgstr "RGB" #: lib/textrenderer.c:192 msgid "Default Framerate" msgstr "Voreingestellte Bildwiederholrate" #: lib/tree.c:252 lib/tree.c:435 msgid "Incoming" msgstr "Eingang" #: lib/tree.c:257 lib/tree.c:443 msgid "Favourites" msgstr "Favoriten" #: lib/tree.c:1086 msgid "Doubleclick on a track first" msgstr "Erst auf einen Track doppelklicken" #: lib/tree.c:1107 #, c-format msgid "Cannot open %s: no plugin found" msgstr "Kann %s nicht öffnen: Kein Plugin gefunden" #: lib/tree.c:1111 #, c-format msgid "Loading %s (plugin: %s)" msgstr "Lade %s (Plugin: %s)" #: lib/tree.c:1130 #, c-format msgid "Selecting track %d for %s failed" msgstr "Auswahl des Tracks %d für %s fehlgeschlagen" #: lib/tree.c:1169 msgid "Use metadata for track names" msgstr "Benutze Metadaten für Tracknamen" #: lib/tree.c:1172 msgid "If disabled, track name will be taken from filename" msgstr "Wenn deaktiviert, wird der Trackname aus dem Dateinamen erzeugt" #: lib/tree.c:1192 msgid "Purge directory on exit" msgstr "Reinige Verzeichnis beim Beenden" #: lib/tree.c:1195 msgid "" "Purge directory (i.e. delete\n" "unused album files) at program exit" msgstr "Reinige Verzeichnis (d.h. lösche unbenutzte Albumdateien) beim Beenden" #: lib/tree.c:1200 #, fuzzy msgid "Blacklisted extensions" msgstr "Hintergrundlichtausgleich" #: lib/tree.c:1203 msgid "File extensions, which are never loaded automatically" msgstr "" #: lib/tree.c:1207 #, fuzzy msgid "Blacklisted filenames" msgstr "Aufgabenliste" #: lib/tree.c:1209 msgid "Filenames, which are never loaded automatically" msgstr "" #: lib/tree.c:1463 #, c-format msgid "Purging %s" msgstr "Bereinige %s" #: lib/tree.c:1580 msgid "No current track for copying to favourites" msgstr "Kein aktueller Track zum Kopieren zu Favoriten" #: lib/singlepic.c:97 msgid "Display time" msgstr "Anzeigedauer" #: lib/singlepic.c:102 msgid "Time to pass until the next track will be selected. 0 means infinite." msgstr "" "Zeit, die vergeht, bis der nächste Track gewählt wird. 0 heißt unendlich." #: lib/singlepic.c:327 #, fuzzy, c-format msgid "Plugin %s could not be loaded" msgstr "Quellplugin konnte nicht geladen werden" #: lib/singlepic.c:594 msgid "Image video input plugin" msgstr "Bilder als Video" #: lib/singlepic.c:595 msgid "" "This plugin reads series of images as a video. It uses the installed image " "readers." msgstr "" "Dieses Plugin liest eine Reihe Bilder als Video. Es benutzt die " "installierten Bildimporteure." #: lib/singlepic.c:641 msgid "" "This plugin reads images as stills. It uses the installed image readers." msgstr "" "Dieses Plugin liest Standbilder. Es benutzt die installierten Bildimporteure." #: lib/singlepic.c:760 msgid "Framenumber digits" msgstr "Dezimalstellen für Bildnummer" #: lib/singlepic.c:768 msgid "Framenumber offset" msgstr "Offset für Bildnummer" #: lib/singlepic.c:1037 #, fuzzy, c-format msgid "Couldn't write data to %s: %s" msgstr "Kann Verzeichnis %s nicht erstellen: %s" #: lib/singlepic.c:1098 msgid "" "This plugin encodes a video as a series of images. It uses the installed " "image writers." msgstr "" "Dieses Plugin exportiert Video als Bilderserie. Es benutzt die installierten " "Bildexportplugins" #: lib/metadata.c:38 msgid "Artist" msgstr "Künstler" #: lib/metadata.c:45 #, fuzzy msgid "Album artist" msgstr "Künstler" #: lib/metadata.c:52 msgid "Title" msgstr "Titel" #: lib/metadata.c:66 lib/transcoder_track.c:194 lib/gtk/infowindow.c:782 msgid "Track" msgstr "Track" #: lib/metadata.c:73 msgid "Genre" msgstr "Genre" #: lib/metadata.c:80 msgid "Author" msgstr "Autor" #: lib/metadata.c:87 msgid "Copyright" msgstr "Copyright" #: lib/metadata.c:94 #, fuzzy msgid "Year" msgstr "Linear" #: lib/metadata.c:448 #, c-format msgid "%s%s%s\n" msgstr "" #: lib/player_audio.c:246 msgid "Restarting playback due to changed audio options" msgstr "Starte Abspielen neu wegen geänderter Audioeinstellungen" #: lib/player_audio.c:288 msgid "Restarting playback due to changed audio filters" msgstr "Starte Abspielen neu wegen geänderter Audiofilter" #: lib/transcoder_track.c:170 lib/gtk/infowindow.c:767 #: lib/gtk/treewidget.c:1123 lib/gtk/chapterdialog.c:185 #: lib/gtk/presetmenu.c:181 msgid "Name" msgstr "Name" #: lib/transcoder_track.c:176 lib/gtk/infowindow.c:777 msgid "Location" msgstr "Ort" #: lib/transcoder_track.c:188 lib/gtk/fileselect.c:269 msgid "Prefer EDL" msgstr "EDl bevorzugen" #: lib/transcoder_track.c:200 msgid "Subdirectory" msgstr "Unterverzeichnis" #: lib/transcoder_track.c:202 msgid "Subdirectory, where this track will be written to" msgstr "Unterverzeichnis, in das die Tracks geschrieben werden" #: lib/transcoder_track.c:242 msgid "Postprocess only" msgstr "Nur Weiterverarbeiten" #: lib/transcoder_track.c:244 msgid "" "Skip transcoding of this track and send the file directly to the " "postprocessor." msgstr "" "Überspringe Transkodieren dieses Tracks und schicke die Datei direkt zum " "Weiterverarbeiten" #: lib/transcoder_track.c:248 msgid "Set start time" msgstr "Setze die Startzeit" #: lib/transcoder_track.c:252 msgid "" "Specify a start time below. This time will be slightly wrong if the input " "format doesn't support sample accurate seeking." msgstr "" "Gib unten eine Startzeit an. Diese Zeit wird geringfügig falsch sein, wenn " "die Quelle kein exaktes Suchen unterstützt." #: lib/transcoder_track.c:257 msgid "Start time" msgstr "Startzeit" #: lib/transcoder_track.c:264 msgid "Set end time" msgstr "Setzte Endzeit" #: lib/transcoder_track.c:268 msgid "Specify an end time below." msgstr "Gib unten eine Endzeit an" #: lib/transcoder_track.c:272 msgid "End time" msgstr "Endzeit" #: lib/transcoder_track.c:286 lib/transcoder_track.c:351 #: lib/transcoder_track.c:1331 lib/transcoder_track.c:1360 msgid "Action" msgstr "Aktion" #: lib/transcoder_track.c:294 lib/transcoder_track.c:357 #: lib/transcoder_track.c:1336 lib/transcoder_track.c:1366 msgid "Forget" msgstr "Vergessen" #: lib/transcoder_track.c:295 msgid "Transcode as text" msgstr "Transkodiere als Text" #: lib/transcoder_track.c:296 msgid "Transcode as overlay" msgstr "Transkodiere als Overlay" #: lib/transcoder_track.c:297 lib/transcoder_track.c:359 msgid "Blend onto video" msgstr "Mische aufs Video" #: lib/transcoder_track.c:299 msgid "Select action for this subtitle stream." msgstr "Wähle Aktion für diesen Untertitelstream" #: lib/transcoder_track.c:303 lib/transcoder_track.c:365 #: lib/transcoder_track.c:1372 msgid "Input Language" msgstr "Ursprüngliche Sprache" #: lib/transcoder_track.c:309 lib/transcoder_track.c:371 #: lib/transcoder_track.c:1378 lib/recorder_audio.c:99 msgid "Language" msgstr "Sprache" #: lib/transcoder_track.c:317 lib/transcoder_track.c:379 #: lib/transcoder_track.c:1386 msgid "Force language" msgstr "Erzwinge Sprache" #: lib/transcoder_track.c:320 lib/transcoder_track.c:382 #: lib/transcoder_track.c:1389 msgid "" "Force the given language even if the input has the language set differently." msgstr "" "Erzwinge die angegebene Sprache, selbst wenn die Quelle was anderes " "behautpet." #: lib/transcoder_track.c:333 msgid "Video stream" msgstr "Videostream" #: lib/transcoder_track.c:338 msgid "" "Attach subtitle stream to this video stream. For blending, this video stream " "will get the subtitles. For encoding, take frame dimensions and framerate " "from this video stream as they are sometimes needed by subtitle encoders." msgstr "" "Hänge Untertitelstream an diesen Videostream an. Wenn der Stream auf das " "Video gemischt wird, ist dies der Videostream, der die Untertitel bekommt. " "Für das Enkodieren werden Bildwiederholrate und -größe von diesem " "Videostream genommen, da diese manchmal von Enkodern gebraucht werden." #: lib/transcoder_track.c:358 lib/transcoder_track.c:1334 #: lib/transcoder_track.c:1364 lib/gtk/albumwidget.c:1543 msgid "Transcode" msgstr "Transkodieren" #: lib/transcoder_track.c:386 msgid "Video stream to blend onto" msgstr "Videostream zum draufmischen" #: lib/transcoder_track.c:1335 lib/transcoder_track.c:1365 msgid "Copy (if possible)" msgstr "" #: lib/transcoder_track.c:1338 lib/transcoder_track.c:1368 msgid "" "Choose the desired action for the stream. If copying is not possible, the " "stream will be transcoded" msgstr "" #: lib/transcoder_track.c:1343 msgid "Enable 2-pass encoding" msgstr "Aktiviere 2-Pass Enkodierung" #: lib/transcoder_track.c:1345 msgid "" "Encode this stream in 2 passes, i.e. analyze it first and do the final " "transcoding in the second pass. This enables higher quality within the given " "bitrate constraints but roughly doubles the video encoding time." msgstr "" "Enkodiere diesen Stream in 2 Durchläufen, d.h. analysiere ihn erst und " "enkodiere ihn endgütlig im zweiten Durchlauf. Dies bringt bessere Qualität " "für eine gegebene Bitrate aber verdoppelt in etwa die Enkodierzeit." #: lib/transcoder_track.c:1393 msgid "Normalize audio" msgstr "Normiere Audio" #: lib/transcoder_track.c:1395 msgid "" "This will enable 2 pass transcoding. In the first pass, the peak volume is " "detected. In the second pass, the stream is transcoded with normalized " "volume." msgstr "" "Dies wird 2-pass Enkodieren aktivieren. Im ersten Durchgang wird die " "Spitzenlautstärke ermittelt. Im zweiten Durchgang wird der Stream mit " "normierter Lautstärke transkodiert." #: lib/osd.c:76 msgid "Enable OSD" msgstr "Aktiviere OSD" #: lib/osd.c:83 msgid "Size" msgstr "Größe" #: lib/osd.c:89 msgid "" "Specify fontsize for OSD. The value you enter, is for an image width of 640. " "For other widths, the value will be scaled" msgstr "" "Gib die Schriftgröße für OSD an. Der Wert gilt für eine Bildbreite von 640. " "Für andere Breiten wird er skaliert." #: lib/osd.c:94 msgid "Foreground color" msgstr "Vordergrundfarbe" #: lib/osd.c:160 msgid "Bottom border" msgstr "Unterer Rand" #: lib/osd.c:169 msgid "Duration (milliseconds)" msgstr "Dauer (Millisekunden)" #: lib/remote.c:102 msgid "Setting up socket failed, this instance won't be reachable via remote" msgstr "" "Initialisierung des Sockets fehlgeschlagen. Diese Instanz wird nicht mit der " "Fernbedienung erreichbar sein." #: lib/remote.c:107 #, c-format msgid "Remote socket listening at port %d" msgstr "Socket für Fernbedienung lauscht an Port %d" #: lib/remote.c:127 msgid "Reading hello line failed" msgstr "Lesen der Begrüßungszeile fehlgeschlagen" #: lib/remote.c:136 lib/remote.c:457 msgid "Protocol mismatch" msgstr "Protokolle stimmen nicht überein" #: lib/remote.c:187 msgid "Client connection closed" msgstr "Clientverbindung geschlossen" #: lib/remote.c:211 msgid "New client connection" msgstr "Neue Clientverbindung" #: lib/remote.c:321 msgid "Allow connections from other machines" msgstr "Erlaube Verbindungen von anderen Maschinen" #: lib/remote.c:327 msgid "Maximum number of connections" msgstr "Maximale Zahl der Verbindungen" #: lib/remote.c:427 msgid "Connecting failed" msgstr "Verbindung fehlgeschlagen" #: lib/remote.c:439 msgid "Sending initialization string failed" msgstr "Senden des Initialisierungsstrings fehlgeschlagen" #: lib/remote.c:448 msgid "Reading welcome line failed" msgstr "Lesen der Bergrüßungszeile fehlgeschlagen" #: lib/player_input.c:267 msgid "Cannot select track, skipping" msgstr "Kann Track nicht auswählen, überspringe" #: lib/player_input.c:310 msgid "Track has neither audio nor video, skipping" msgstr "Track hat weder Audio noch Video, überspringe ihn." #: lib/player_input.c:351 #, c-format msgid "Audio sample counter: %s" msgstr "Audiosamplezähler: %s" #: lib/player_input.c:356 #, c-format msgid "Video frame counter: %s" msgstr "Bilderzähler: %s" #: lib/player_input.c:581 msgid "" "When showing still images, gmerlin repeats them periodically to make " "realtime filter tweaking work." msgstr "" "Wenn Standbilder gezeigt werden, wiederholt Gmerlin sie periodisch. Dies " "ermöglicht Herumspielen an den Filtereinstellungen in Echtzeit. " #: lib/player_input.c:591 msgid "" "Use this for playing buggy files, which have a constant offset between audio " "and video. Use positive values if the video is ahead of audio" msgstr "" #: lib/chapterlist.c:134 #, c-format msgid "Chapter %d" msgstr "Kapitel %d" #: lib/stringutils.c:181 #, c-format msgid "Cannot open file \"%s\" for writing" msgstr "Kann Datei \"%s\" nicht zum Schreiben öffnen" #: lib/stringutils.c:595 #, c-format msgid "Stream %d [%s]" msgstr "Stream %d [%s]" #: lib/stringutils.c:597 #, c-format msgid "Stream %d" msgstr "Stream %d" #: lib/ocr.c:88 #, fuzzy, c-format msgid "Writing image file %s" msgstr "Schreibe Abbild" #: lib/ocr.c:129 msgid "No engine found" msgstr "" #: lib/ocr.c:155 msgid "" "Background color to use, when converting formats with transparency to " "grayscale" msgstr "" #: lib/ocr.c:159 #, fuzzy msgid "Temporary directory" msgstr "Wähle ein Verzeichnis" #: lib/ocr.c:162 msgid "Temporary directory for image files" msgstr "" #: lib/ocr.c:257 #, c-format msgid "OCR failed, keeping %s" msgstr "" #: lib/socket.c:149 #, c-format msgid "Cannot resolve address of %s: %s" msgstr "Kann Adresse von %s nicht auflösen: %s" #: lib/socket.c:191 msgid "Cannot create socket" msgstr "Kann Socket nicht erzeugen" #: lib/socket.c:198 lib/socket.c:380 lib/socket.c:416 msgid "Cannot set nonblocking mode" msgstr "Kann nicht in Nichtblockiermodus wechseln" #: lib/socket.c:216 msgid "Connection timed out" msgstr "Zeitüberschreitung beim Verbinden" #: lib/socket.c:221 msgid "select() failed on connect" msgstr "" #: lib/socket.c:227 lib/socket.c:239 #, c-format msgid "Connecting failed: %s" msgstr "Verbindung fehlgeschlagen: %s" #: lib/socket.c:248 msgid "Cannot set blocking mode" msgstr "Kann nicht in Blockiermodus wechseln" #: lib/socket.c:262 msgid "Cannot create unix socket" msgstr "Kann keinen UNIX-Socket erzeugen" #: lib/socket.c:273 msgid "Connecting unix socket failed" msgstr "Verbindung vom UNIX-Socket fehlgeschlagen" #: lib/socket.c:305 #, fuzzy, c-format msgid "Cannot resolve address of localhost: %s" msgstr "Kann Adresse von %s nicht auflösen: %s" #: lib/socket.c:345 msgid "Cannot create inet server socket" msgstr "Kann keinen Inet-Serversocket erzeugen" #: lib/socket.c:375 #, c-format msgid "Cannot bind inet socket: %s" msgstr "Kann Socket nicht binden: %s" #: lib/socket.c:385 lib/socket.c:421 msgid "Cannot put socket into listening mode" msgstr "Kann Socket nicht in Lauschmodus schalten" #: lib/socket.c:401 msgid "Cannot create unix server socket" msgstr "Kann keinen UNIX-Serversocket erzeugen" #: lib/socket.c:411 msgid "Could not bind socket" msgstr "Kann Socket nicht binden" #: lib/socket.c:478 #, fuzzy, c-format msgid "Sending data failed: %s" msgstr "Disk Auswerfen fehlgeschlagen: %s" #: lib/player_oa.c:122 #, c-format msgid "Got initial audio timestamp: %s" msgstr "Erster Audiozeitstempel erhalten: %s" #: lib/album_xml.c:226 #, c-format msgid "Couldn't open album file %s" msgstr "Konnte Albumdatei %s nicht öffnen" #: lib/encoder.c:183 #, fuzzy, c-format msgid "Created output file %s" msgstr "Kann Ausgabedatei %s nicht öffnen" #: lib/encoder.c:199 #, fuzzy, c-format msgid "Created temp file %s\n" msgstr "Kann Datei %s nicht öffnen" #: lib/encoder.c:651 msgid "Multipass encoding not supported by encoder plugin" msgstr "Multipassenkodierung wird vom Enkoderplugin nicht unterstützt" #: lib/gtk/infowindow.c:516 #, c-format msgid "Name:\t%s" msgstr "Name:\t%s" #: lib/gtk/infowindow.c:526 #, c-format msgid "Input plugin:\t%s" msgstr "Quellenplugin:\t%s" #: lib/gtk/infowindow.c:535 #, c-format msgid "Location:\t%s" msgstr "Ort:\t%s" #: lib/gtk/infowindow.c:543 #, c-format msgid "Track:\t%d" msgstr "Track:\t%d" #: lib/gtk/infowindow.c:590 #, c-format msgid "Audio stream %d/%d" msgstr "Audiostream %d/%d" #: lib/gtk/infowindow.c:605 #, c-format msgid "Subtitle stream %d/%d [%s]" msgstr "Untertitelstream %d/%d [%s]" #: lib/gtk/infowindow.c:620 #, c-format msgid "Video stream %d/%d" msgstr "Videostream %d/%d" #: lib/gtk/infowindow.c:706 lib/gtk/infowindow.c:725 lib/gtk/infowindow.c:744 msgid "Input format" msgstr "Quellenformat" #: lib/gtk/infowindow.c:772 msgid "Input plugin" msgstr "Quellenplugin" #: lib/gtk/infowindow.c:1040 msgid "Copy selected" msgstr "Kopiere Auswahl" #: lib/gtk/infowindow.c:1042 msgid "Copy all" msgstr "Kopiere Alles" #: lib/gtk/infowindow.c:1090 msgid "Gmerlin Track Info" msgstr "Gmerlin Track Info" #: lib/gtk/treewidget.c:958 msgid "Album name" msgstr "Albumname" #: lib/gtk/treewidget.c:966 lib/gtk/treewidget.c:2043 msgid "Rename album" msgstr "Album umbenennen" #: lib/gtk/treewidget.c:1130 msgid "Add device" msgstr "Gerät hinzufügen" #: lib/gtk/treewidget.c:1344 msgid "Expand all" msgstr "Alles ausklappen" #: lib/gtk/treewidget.c:1348 msgid "Collapse all" msgstr "Alles einklappen" #: lib/gtk/treewidget.c:1352 msgid "Tabbed mode" msgstr "Tabbed Modus" #: lib/gtk/treewidget.c:1356 msgid "Windowed mode" msgstr "Fenstermodus" #: lib/gtk/treewidget.c:1366 msgid "Open" msgstr "Öffnen" #: lib/gtk/treewidget.c:1370 msgid "Close" msgstr "Schließen" #: lib/gtk/treewidget.c:1374 msgid "New..." msgstr "Neu..." #: lib/gtk/treewidget.c:1378 msgid "New from directory..." msgstr "Neu von Verzeichnis..." #: lib/gtk/treewidget.c:1382 lib/gtk/albumwidget.c:1533 msgid "Rename..." msgstr "Umbenennen..." #: lib/gtk/treewidget.c:1395 msgid "Scan for devices" msgstr "Suche nach Geräten" #: lib/gtk/treewidget.c:1399 msgid "Add device..." msgstr "Füge Gerät hinzu..." #: lib/gtk/treewidget.c:1406 lib/gtk/albumwidget.c:1601 msgid "Album..." msgstr "Album..." #: lib/gtk/treewidget.c:1419 msgid "Tree..." msgstr "Baum..." #: lib/gtk/treewidget.c:2041 msgid "Delete album" msgstr "Lösche Album" #: lib/gtk/treewidget.c:2050 msgid "New album" msgstr "Neues Album" #: lib/gtk/logwindow.c:238 #, c-format msgid "%s messages" msgstr "%s Meldungen" #: lib/gtk/logwindow.c:333 msgid "Number of messages" msgstr "Zahl der Meldungen" #: lib/gtk/logwindow.c:336 msgid "Maximum number of messages hold in the window" msgstr "Maximale Zahl der Meldungen die im Fenster gehalten werden" #: lib/gtk/logwindow.c:340 msgid "Show info messages" msgstr "Zeige Informationsmeldungen" #: lib/gtk/logwindow.c:346 msgid "Show warning messages" msgstr "Zeige Warnungen" #: lib/gtk/logwindow.c:352 msgid "Show error messages" msgstr "Zeige Fehler" #: lib/gtk/logwindow.c:358 msgid "Show debug messages" msgstr "Zeige Debugmeldungen" #: lib/gtk/logwindow.c:364 msgid "Info foreground" msgstr "Info Vordergrund" #: lib/gtk/logwindow.c:367 msgid "Color for info messages" msgstr "Farbe für Infomeldungen" #: lib/gtk/logwindow.c:371 msgid "Warning foreground" msgstr "Warnung Vordergrund" #: lib/gtk/logwindow.c:374 msgid "Color for warning messages" msgstr "Farbe für Warnungen" #: lib/gtk/logwindow.c:381 msgid "Color for error messages" msgstr "Farbe für Fehlermeldungen" #: lib/gtk/logwindow.c:385 msgid "Debug foreground" msgstr "Debug Vordergrund" #: lib/gtk/logwindow.c:388 msgid "Color for debug messages" msgstr "Farbe für Debugmeldungen" #: lib/gtk/question.c:93 msgid "Question" msgstr "Frage" #: lib/gtk/plugin_multi.c:270 lib/gtk/plugin_single.c:372 msgid "Plugin info" msgstr "Plugininformation" #: lib/gtk/plugin_multi.c:273 lib/gtk/plugin_single.c:367 msgid "Plugin options" msgstr "Pluginoptionen" #: lib/gtk/fileselect.c:232 msgid "Recursive" msgstr "Rekursiv" #: lib/gtk/fileselect.c:240 msgid "Add subdirectories as subalbums" msgstr "Füge Unterverzeichnisse als Unteralben hinzu" #: lib/gtk/fileselect.c:245 #, fuzzy msgid "Watch directories" msgstr "Verzeichnis erstellt: %s" #: lib/gtk/chapterdialog.c:194 msgid "Time" msgstr "Zeit" #: lib/gtk/chapterdialog.c:222 lib/gtk/chapterdialog.c:362 msgid "Edit chapter" msgstr "Bearbeite Kapitel" #: lib/gtk/chapterdialog.c:360 msgid "Add new chapter" msgstr "Neues Kapitel hinzufügen" #: lib/gtk/chapterdialog.c:364 msgid "Delete chapter" msgstr "Lösche Kapitel" #: lib/gtk/cfg_time.c:216 #, c-format msgid "%s (Hours)" msgstr "%s (Stunden)" #: lib/gtk/cfg_time.c:220 #, c-format msgid "%s (Minutes)" msgstr "%s (Minuten)" #: lib/gtk/cfg_time.c:224 #, c-format msgid "%s (Seconds)" msgstr "%s (Sekunden)" #: lib/gtk/cfg_time.c:228 #, c-format msgid "%s (Milliseconds)" msgstr "%s (Millisekunden)" #: lib/gtk/cfg_time.c:252 msgid "h:" msgstr "h:" #: lib/gtk/cfg_time.c:257 msgid "m:" msgstr "m:" #: lib/gtk/cfg_time.c:261 msgid "s:" msgstr "s:" #: lib/gtk/cfg_time.c:265 msgid "ms:" msgstr "ms:" #: lib/gtk/fileentry.c:85 msgid "Select a directory" msgstr "Wähle ein Verzeichnis" #: lib/gtk/fileentry.c:97 msgid "Select a file" msgstr "Wähle eine Datei" #: lib/gtk/fileentry.c:161 lib/gtk/cfg_font.c:196 msgid "Browse..." msgstr "Durchsuchen..." #: lib/gtk/pluginmenu.c:36 msgid "Auto Select" msgstr "Automatisch" #: lib/gtk/pluginmenu.c:107 msgid "Plugin: " msgstr "Plugin: " #: lib/gtk/presetmenu.c:183 #, fuzzy msgid "New preset" msgstr "Nächstes Pixel" #: lib/gtk/presetmenu.c:190 #, fuzzy msgid "Save preset" msgstr "Speichere Profil" #: lib/gtk/presetmenu.c:323 #, fuzzy msgid "Save new..." msgstr "Speichern unter..." #: lib/gtk/presetmenu.c:326 #, fuzzy msgid "Load..." msgstr "Befehle..." #: lib/gtk/presetmenu.c:332 #, fuzzy msgid "Save to..." msgstr "Speichern unter..." #: lib/gtk/presetmenu.c:338 #, fuzzy msgid "Delete..." msgstr "Ausgewählte..." #: lib/gtk/presetmenu.c:349 #, fuzzy msgid "Preset" msgstr "Nächstes Pixel" #: lib/gtk/urlselect.c:179 msgid "URL:" msgstr "URL:" #: lib/gtk/albumwidget.c:1130 msgid "Track name" msgstr "Trackname" #: lib/gtk/albumwidget.c:1141 msgid "Rename entry" msgstr "Eintrag umbenennen" #: lib/gtk/albumwidget.c:1153 #, c-format msgid "Add files to album %s" msgstr "Füge Dateien zum Album %s hinzu" #: lib/gtk/albumwidget.c:1179 #, c-format msgid "Add URLS to album %s" msgstr "Füge URLs zum Album %s hinzu" #: lib/gtk/albumwidget.c:1263 #, c-format msgid "Add albums to %s" msgstr "Füge Alben zu %s hinzu" #: lib/gtk/albumwidget.c:1455 msgid "URLs..." msgstr "URLs..." #: lib/gtk/albumwidget.c:1457 msgid "Albums..." msgstr "Alben..." #: lib/gtk/albumwidget.c:1469 msgid "Copy to favourites" msgstr "Kopiere zu Favoriten" #: lib/gtk/albumwidget.c:1478 msgid "Move to top" msgstr "Verschiebe ganz nach oben" #: lib/gtk/albumwidget.c:1486 msgid "Move to bottom" msgstr "Verschiebe ganz nach unten" #: lib/gtk/albumwidget.c:1522 msgid "Find..." msgstr "Suche..." #: lib/gtk/albumwidget.c:1536 msgid "Info..." msgstr "Info..." #: lib/gtk/albumwidget.c:1550 msgid "Refresh" msgstr "Neu Laden" #: lib/gtk/albumwidget.c:1553 msgid "Export as EDL" msgstr "Als EDL exportieren" #: lib/gtk/albumwidget.c:1566 msgid "Save as..." msgstr "Speichern unter..." #: lib/gtk/albumwidget.c:1570 msgid "Sort" msgstr "Sortieren" #: lib/gtk/albumwidget.c:1607 msgid "Select error tracks" msgstr "Wähle Fehlertracks aus" #: lib/gtk/albumwidget.c:1610 msgid "Show toolbar" msgstr "Zeige Werkzeugleiste" #: lib/gtk/albumwidget.c:2901 msgid "Add URLs" msgstr "Füge URLs hinzu" #: lib/gtk/albumwidget.c:2914 msgid "Close album and eject disc" msgstr "Schließe Album und werfe Disk aus" #: lib/gtk/albumwidget.c:2920 msgid "Copy selected tracks to favourites" msgstr "Kopiere ausgewählte Tracks zu Favoriten" #: lib/gtk/albumwidget.c:2923 msgid "Rename selected track" msgstr "Benenne ausgewählten Track um" #: lib/gtk/albumwidget.c:2926 msgid "Show track info" msgstr "Zeige Trackinformationen" #: lib/gtk/albumwidget.c:2929 msgid "Find tracks" msgstr "Suche Tracks" #: lib/gtk/albumwidget.c:3130 msgid "Backward search hit top, continuing at bottom" msgstr "Rückwärtssuche hat Angang erreicht, mache am Ende weiter" #: lib/gtk/albumwidget.c:3139 msgid "Backward search: No tracks found" msgstr "Rückwärtssuche: Keine Tracks gefunden" #: lib/gtk/albumwidget.c:3158 msgid "Forward search hit bottom, continuing at top" msgstr "Vorwärtssuche hat Ende erreicht. Mache am Anfang weiter" #: lib/gtk/albumwidget.c:3167 msgid "Forward search: No tracks found" msgstr "Vorwärtssuche: Keine Tracks gefunden" #: lib/gtk/albumwidget.c:3291 msgid "Exact match" msgstr "Genaue Übereinstimmung" #: lib/gtk/albumwidget.c:3292 msgid "String is an exact substring" msgstr "String ist ein exakter Teilstring" #: lib/gtk/albumwidget.c:3296 msgid "Match case" msgstr "Groß/Kleinschreibung beachten" #: lib/gtk/albumwidget.c:3297 msgid "Match upper and lower case" msgstr "Groß/Kleinschreibung beachten" #: lib/gtk/aboutwindow.c:119 msgid "" "Get the latest source version from http://gmerlin.sourceforge.net * * * If " "you installed gmerlin from a binary package, you might have limited features" msgstr "" "Hole den neuesten Quellcode von http://gmerlin.sourceforge.net * * * Wenn Du " "gmerlin als Binärpaket installiert hast, könnten die Features eingeschränkt " "sein" #: lib/gtk/aboutwindow.c:136 msgid "Visit homepage" msgstr "Besuche Homepage" #: lib/gtk/aboutwindow.c:170 #, fuzzy msgid "Copyright © 2001-2009 Members of the gmerlin project" msgstr "Copyright © 2001-2007 Mitglieder des gmerlin projekts" #: lib/gtk/aboutwindow.c:174 msgid "" "This is free software. You may redistribute copies of it under the terms " "of\n" "the GNU General Public License .\n" "There is NO WARRANTY." msgstr "" "Dies ist freie Software, die unter den Bedingungen der GNU General Public " "License\n" " weitergegeben werden kann.\n" "Es gibt KEINE HAFTUNG." #: lib/gtk/treewindow.c:177 msgid "Gmerlin Media Tree" msgstr "Gmerlin Media Tree" #: lib/gtk/cfg_multi_list.c:863 #, c-format msgid "Add %s" msgstr "%s hinzufügen" #: lib/gtk/multiinfo.c:142 #, c-format msgid "" "Name:\t %s\n" "Label:\t %s" msgstr "" "Name:\t %s\n" "Bezeichnung:\t %s" #: lib/gtk/multiinfo.c:149 msgid "Not available" msgstr "Nicht verfügbar" #: lib/gtk/driveselect.c:225 msgid "Drive:" msgstr "Laufwerk:" #: lib/gtk/cfg_dialog.c:502 msgid "No options here, choose subcategory" msgstr "Keine Optionen hier, gehe zu Unterkategorie" #: lib/gtk/cfg_dialog.c:682 msgid "No options available" msgstr "Keine Optionen verfügbar" #: lib/gtk/albumentry.c:51 #, c-format msgid "" "Name:\t %s\n" "Location:\t %s\n" "Track:\t %d/%d%s\n" "Plugin:\t %s\n" "Duration:\t %s\n" "Audio Streams:\t %d\n" "Video Streams:\t %d\n" "Subtitle Streams:\t %d" msgstr "" "Name:\t %s\n" "Ort:\t %s\n" "Track:\t %d/%d%s\n" "Plugin:\t %s\n" "Dauer:\t %s\n" "Audio Streams:\t %d\n" "Video Streams:\t %d\n" "Untertitel Streams:\t %d" #: lib/gtk/albumentry.c:56 msgid "Auto detect" msgstr "Automatisch" #: lib/gtk/cfg_position.c:150 msgid "X" msgstr "X" #: lib/gtk/cfg_position.c:155 msgid "Y" msgstr "Y" #: lib/gtk/plugininfo.c:155 msgid "Audio output" msgstr "Audioausgabe" #: lib/gtk/plugininfo.c:158 msgid "Video recorder" msgstr "Videoaufnahme" #: lib/gtk/plugininfo.c:159 msgid "Audio encoder" msgstr "Audioenkoder" #: lib/gtk/plugininfo.c:160 msgid "Video encoder" msgstr "Videoenkoder" #: lib/gtk/plugininfo.c:162 msgid "Overlay subtitle exporter" msgstr "Exporteur für Overlayuntertitel" #: lib/gtk/plugininfo.c:163 msgid "Audio/Video encoder" msgstr "Audio-/Videoenkoder" #: lib/gtk/plugininfo.c:164 msgid "Image reader" msgstr "Bildimporteur" #: lib/gtk/plugininfo.c:165 msgid "Image writer" msgstr "Bildexporteur" #: lib/gtk/plugininfo.c:166 msgid "Encoding postprocessor" msgstr "Weiterverarbeitung" #: lib/gtk/plugininfo.c:167 msgid "Audio filter" msgstr "Audiofilter" #: lib/gtk/plugininfo.c:168 msgid "Video filter" msgstr "Videofilter" #: lib/gtk/plugininfo.c:180 msgid "Removable Device" msgstr "Wechseldatenträger" #: lib/gtk/plugininfo.c:183 msgid "URL" msgstr "URL" #: lib/gtk/plugininfo.c:184 msgid "Playback" msgstr "Wiedergabe" #: lib/gtk/plugininfo.c:185 msgid "Tuner" msgstr "Tuner" #: lib/gtk/plugininfo.c:186 msgid "Filter with 1 input" msgstr "Filter mit einem Eingang" #: lib/gtk/plugininfo.c:187 msgid "Renders via gmerlin" msgstr "Rendert mit Gmerlin" #: lib/gtk/plugininfo.c:188 msgid "Renders via OpenGL" msgstr "Rendert mit OpenGL" #: lib/gtk/plugininfo.c:258 #, c-format msgid "" "Name:\t %s\n" "Long name:\t %s\n" "Type:\t %s\n" "Flags:\t %s\n" "Priority:\t %d\n" "DLL Filename:\t %s" msgstr "" "Name:\t %s\n" "Langer name:\t %s\n" "Typ:\t %s\n" "Flags:\t %s\n" "Priorität:\t %d\n" "DLL Dateiname:\t %s" #: lib/gtk/auth.c:73 msgid "Authentication" msgstr "Authentifizierung" #: lib/gtk/auth.c:103 msgid "Save user/password (can be dangerous!)" msgstr "Speichere Benutzer/Passwort (kann gefährlich sein!)" #: lib/gtk/auth.c:114 msgid "Enter username and password for" msgstr "Gib Benutzernamen und Passwort ein für" #: lib/gtk/auth.c:129 msgid "Username" msgstr "Benutzername" #: lib/gtk/auth.c:134 msgid "Password" msgstr "Passwort" #: lib/gtk/cfg_device.c:340 msgid "Delete" msgstr "Löschen" #: lib/gtk/message.c:87 msgid "Message" msgstr "Meldung" #: lib/recorder.c:52 #, fuzzy, c-format msgid "New track: %s" msgstr "Nächster Track" #: lib/recorder.c:502 #, fuzzy msgid "Output filename mask" msgstr "Ausgabedateien" #: lib/recorder.c:505 msgid "" "Extension is appended by the plugin\n" "For the date and time formatting, consult the documentation\n" "of the strftime(3) function" msgstr "" #: lib/recorder.c:511 #, fuzzy msgid "Snapshot directory" msgstr "Ausgabeverzeichnis" #: lib/recorder.c:517 msgid "Snapshot filename mask" msgstr "" #: lib/recorder.c:562 #, fuzzy msgid "Metadata mode" msgstr "Metadaten" #: lib/recorder.c:568 #, fuzzy msgid "Static" msgstr "Automatisch aufnehmen" #: lib/recorder.c:569 #, fuzzy msgid "From input" msgstr "Videoausgabe" #: lib/recorder.c:570 #, fuzzy msgid "From player" msgstr "Gmerlin Player" #: lib/recorder.c:731 #, fuzzy, c-format msgid "New track %s" msgstr "Nächster Track" #: lib/subprocess.c:168 #, c-format msgid "Created process: %s [%d]" msgstr "Prozess gestartet: %s [%d]" #: lib/subprocess.c:173 #, c-format msgid "Creating process failed: %s" msgstr "Starten eines Prozesses fehlgeschlagen: %s" #: lib/subprocess.c:206 #, c-format msgid "Finished process [%d] return value: %d" msgstr "Prozess [%d] beendet, Rückgabewert: %d" #: lib/player.c:65 msgid "Aspect ratio changed" msgstr "Aspektverhältnis geändert" #: lib/player.c:309 #, fuzzy msgid "Control loop interval" msgstr "Aufnahmeintervall" #: lib/player.c:315 #, fuzzy msgid "Time update interval" msgstr "Aufnahmeintervall" #: lib/player.c:318 #, fuzzy msgid "Seconds" msgstr "%s (Sekunden)" #: lib/player.c:318 #, fuzzy msgid "frames" msgstr "Neu Laden" #: lib/player.c:323 msgid "Report peak values for audio" msgstr "" #: lib/player.c:328 #, fuzzy msgid "Finish mode" msgstr "Dithermodus" #: lib/player.c:331 msgid "Change" msgstr "" #: lib/recorder_audio.c:87 #, fuzzy msgid "Record audio" msgstr "Kein Audio" #: lib/bgfrei0r.c:68 lib/bgfrei0r.c:76 lib/bgfrei0r.c:83 lib/bgfrei0r.c:90 #: lib/bgfrei0r.c:183 lib/bgfrei0r.c:475 lib/bgfrei0r.c:490 lib/bgfrei0r.c:496 #: lib/bgfrei0r.c:502 lib/bgfrei0r.c:508 #, c-format msgid "Cannot load frei0r plugin: %s" msgstr "Kann frei0r Plugin %s nicht laden" #: lib/bgfrei0r.c:207 #, c-format msgid "" "Author: %s\n" "%s" msgstr "" "Author: %s\n" "%s" #: lib/album.c:499 lib/album.c:545 msgid "Not exporting empty album" msgstr "" #: lib/album.c:506 lib/album.c:552 #, fuzzy, c-format msgid "Could not open %s: %s" msgstr "Kann %s nicht öffnen" #: lib/album.c:610 msgid "Unnamed disc" msgstr "Namenlose Disk" #: lib/album.c:713 #, c-format msgid "%s disappeared, updating album" msgstr "" #: lib/album.c:723 #, c-format msgid "%s appeared, updating album" msgstr "" #: lib/album.c:825 #, c-format msgid "Album %s already open" msgstr "Album %s ist bereits offen" #: lib/album.c:830 #, c-format msgid "Opening album %s" msgstr "Öffne Album %s" #: lib/album.c:975 #, c-format msgid "Not closing album %s (open_count > 0)" msgstr "Werde Album %s nicht schließen (open_count > 0)" #: lib/album.c:978 #, c-format msgid "Closing album %s" msgstr "Schließe Album %s" #: lib/album.c:2210 #, c-format msgid "Not loading %s (blacklisted extension)" msgstr "" #: lib/album.c:2221 #, fuzzy, c-format msgid "Not loading %s (blacklisted filename)" msgstr "Laden von %s fehlgeschlagen" #: lib/album.c:2251 #, c-format msgid "Loading %s" msgstr "Lade %s" #: lib/album.c:2295 #, c-format msgid "Loaded %s (track %d of %d)" msgstr "%s geladen (Track %d von %d)" #: lib/album.c:2497 msgid "Ejecting disc failed" msgstr "Datenträger auswerfen fehlgeschlagen" #: lib/album.c:2615 msgid "Invalid selection range given" msgstr "Ungültiger Auswahlbereich" #: lib/ovl2text.c:159 msgid "Plugin for writing the text subtitles" msgstr "" #: lib/ovl2text.c:233 #, fuzzy msgid "Overlay to text converter" msgstr "Exporteur für Overlayuntertitel" #: lib/ovl2text.c:234 #, fuzzy msgid "Exports overlay subtitles to a text format by performing an OCR." msgstr "" "Exportiert Overlay Untertitel im Format von spumux (http://dvdauthor." "sourceforge.net)" #: lib/edldec.c:642 msgid "EDL only works with seekable sources" msgstr "EDL funktioniert nur mit suchbaren Quellen" #: lib/edldec.c:1018 msgid "Unexpected EOF, clearing frame" msgstr "Unerwartetes Dateiende, lösche Bild" #: lib/edldec.c:1185 msgid "Seeked audio out of range" msgstr "Audiosuche reichte außerhalb des Bereichs" #: lib/edldec.c:1205 msgid "Seeked video out of range" msgstr "Videosuche reichte außerhalb des Bereichs" #: lib/edldec.c:1227 lib/edldec.c:1248 msgid "Seeked text subtitles out of range" msgstr "Textuntertitel-Suche reichte außerhalb des Bereichs" #: lib/edldec.c:1372 msgid "EDL decoder" msgstr "EDL decoder" #: lib/edldec.c:1373 #, fuzzy msgid "This metaplugin decodes an EDL as if it was a single file." msgstr "Dieses Metaplugin dekodiert eine EDL als wäre sie eine einzige Datei" #: lib/filters.c:193 msgid "Audio Filters" msgstr "Audiofilter" #: lib/filters.c:353 #, c-format msgid "Initialized audio filter %s" msgstr "Initialisierte Audiofilter %s" #: lib/filters.c:623 msgid "Video Filters" msgstr "Videofilter" #: lib/filters.c:778 #, c-format msgid "Initialized video filter %s" msgstr "Initialisierte Videofilter %s" #: lib/bglv.c:429 msgid "libvisual plugin" msgstr "libvisual Plugin" #: lib/bglv.c:434 #, c-format msgid "" "\n" "Author: %s" msgstr "" "\n" "Author: %s" #: lib/bglv.c:441 #, c-format msgid "" "\n" "Version: %s" msgstr "" "\n" "Version: %s" #: lib/bglv.c:448 #, c-format msgid "" "\n" "About: %s" msgstr "" "\n" "Über: %s" #: lib/bglv.c:455 #, c-format msgid "" "\n" "Help: %s" msgstr "" "\n" "Hilfe: %s" #: lib/bglv.c:462 #, c-format msgid "" "\n" "License: %s" msgstr "" "\n" "Lizenz: %s" #~ msgid "CD audio track" #~ msgstr "CD Audio Track" #, fuzzy #~ msgid "Failure" #~ msgstr "Datei" #~ msgid "Format: %s" #~ msgstr "Format: %s" #~ msgid "Audio stream: %s" #~ msgstr "Audiostream: %s" #~ msgid "Video stream: %s" #~ msgstr "Videostream: %s" #~ msgid "Subtitle stream: %s" #~ msgstr "Untertitelstream: %s" #~ msgid "Cannot open plugin %s" #~ msgstr "Kann Plugin %s nicht öffnen" #~ msgid "Cannot open %s with plugin %s" #~ msgstr "Kann %s nicht mit Plugin %s öffnen" #~ msgid "" #~ "For files, which contain edit decision lists and raw streams, this option " #~ "selects which one to decode. This setting is saved in the album once the " #~ "file is loaded." #~ msgstr "" #~ "Für Dateien, die EDLs und Rohstreams enthalten, letg diese Option fest, " #~ "welche von beiden abgespielt werden soll. Die Einstellung wird im Album " #~ "gespeichert, sobald die Datei geladen wurde." #~ msgid "Date" #~ msgstr "Datum" #~ msgid "Complete date or year only" #~ msgstr "Komplettes Datum oder nur das Jahr" #~ msgid "Author:\t %s\n" #~ msgstr "Autor:\t %s\n" #~ msgid "Artist:\t %s\n" #~ msgstr "Künstler:\t %s\n" #~ msgid "Title:\t %s\n" #~ msgstr "Titel:\t %s\n" #~ msgid "Album:\t %s\n" #~ msgstr "Album:\t %s\n" #~ msgid "Copyright:\t %s\n" #~ msgstr "Copyright:\t %s\n" #~ msgid "Genre:\t %s\n" #~ msgstr "Genre:\t %s\n" #~ msgid "Date:\t %s\n" #~ msgstr "Datum:\t %s\n" #~ msgid "Track:\t %d\n" #~ msgstr "Track:\t %d\n" #~ msgid "Comment:\t %s\n" #~ msgstr "Kommentar:\t %s\n" #~ msgid "" #~ "For files, which contain edit decision lists and raw streams, this option " #~ "selects which one to decode." #~ msgstr "" #~ "Für Dateien, die EDLs und Rohstreams enthalten, letg diese Option fest, " #~ "welche von beiden abgespielt werden soll." #~ msgid "Format:\t%s" #~ msgstr "Format:\t%s" #~ msgid "Stream type:\t%s" #~ msgstr "Streamtyp:\t%s" #~ msgid "Stream type" #~ msgstr "Streamtyp" #~ msgid "Inputs" #~ msgstr "Quellen" #, fuzzy #~ msgid "bg_plugin_ref (null): %d" #~ msgstr "bg_plugin_ref %s: %d" #, fuzzy #~ msgid "vloopback open failed: %s" #~ msgstr "vcdxgen fehlgeschlagen: %s" #~ msgid "Player finishing" #~ msgstr "Spieler beendet jetzt" #~ msgid "Shift" #~ msgstr "Umschalttaste" #~ msgid "Lock" #~ msgstr "Feststelltaste" #~ msgid "Control" #~ msgstr "Steuerung" #~ msgid "Mod1" #~ msgstr "Mod1" #~ msgid "Mod2" #~ msgstr "Mod2" #~ msgid "Mod3" #~ msgstr "Mod3" #~ msgid "Mod4" #~ msgstr "Mod4" #~ msgid "Mod5" #~ msgstr "Mod5" #~ msgid "Button1" #~ msgstr "Maustaste1" #~ msgid "Button2" #~ msgstr "Maustaste2" #~ msgid "Button3" #~ msgstr "Maustaste3" #~ msgid "Button4" #~ msgstr "Maustaste4" #~ msgid "Button5" #~ msgstr "Maustaste5" #~ msgid "Input plugins..." #~ msgstr "Quellenplugins..." #~ msgid "Select encoders" #~ msgstr "Wähle Enkoder" #~ msgid "Plugins" #~ msgstr "Plugins" #~ msgid "Plugins..." #~ msgstr "Plugins..." #~ msgid "" #~ "Change and configure plugins\n" #~ "for newly added tracks" #~ msgstr "Ändere und konfiguriere Plugins für neu hinzugefügte Tracks." #~ msgid "Fixed output samplerate" #~ msgstr "Feste Abtastrate für die Ausgabe" #~ msgid "Bypass" #~ msgstr "Umgehen" #~ msgid "Keep Running" #~ msgstr "Laufenlassen" #~ msgid "Can Sync" #~ msgstr "Kann synchronisieren" #~ msgid "Processed %s audio samples" #~ msgstr "%s Audiosamples verarbeitet" #~ msgid "Processed %s video frames" #~ msgstr "%s Videobilder verarbeitet" #~ msgid "Input options" #~ msgstr "Quellenoptionen" #~ msgid "Enable bypass mode" #~ msgstr "Aktiviere Umgehungsmodus" #~ msgid "" #~ "Use input plugins in bypass mode if they support it (Currently only the " #~ "audio CD player). This dramatically decreases CPU usage but doesn't work " #~ "on all hardware setups." #~ msgstr "" #~ "Benutze Quellenplugins im Umgehungsmodus wenn sie es unterstützen " #~ "(momentan nur der Audio-CD Spieler). Dies verringert die CPU-Belastung " #~ "erheblich aber funktioniert nicht mit allen Hardwarekonfigurationen." #~ msgid "Joining input thread..." #~ msgstr "Beende Quellenthread..." #~ msgid "Joining input thread done" #~ msgstr "Beenden des Quellenthreads abgeschlossen" #~ msgid "Joining audio thread..." #~ msgstr "Beende Audiothread..." #~ msgid "Joining audio thread done" #~ msgstr "Beenden des Audiothreads abgeschlossen" #~ msgid "Joining video thread..." #~ msgstr "Beende Videothread..." #~ msgid "Joining video thread done" #~ msgstr "Beenden des Videothreads abgeschlossen" #~ msgid "No known address space" #~ msgstr "Unbekannter Adressraum" #~ msgid "Multipass encoding not supported by codec" #~ msgstr "Multipassenkodierung wird vom Codec nicht unterstützt" #~ msgid "Audio stream %d -> file: %s" #~ msgstr "Audiostream %d -> Datei: %s" #~ msgid "Video stream %d -> file: %s" #~ msgstr "Videostream %d -> Datei: %s" #~ msgid "Output file: %s" #~ msgstr "Ausgabedatei: %s" #~ msgid "Could not start %s" #~ msgstr "Konnte %s nicht starten" #~ msgid "No video encoder found, check installation" #~ msgstr "Kein Enkoder für Video gefunden, prüfe Installation" #~ msgid "No audio encoder found, check installation" #~ msgstr "Kein Enkoder für Audio gefunden, prüfe Installation" #~ msgid "No encoder for text subtitles found, check installation" #~ msgstr "Kein Enkoder für Textuntertitel gefunden, prüfe Installation" #~ msgid "No encoder for overlay subtitles found, check installation" #~ msgstr "Kein Enkoder für Overlayuntertitel gefunden, prüfe Installation" #~ msgid "Play command failed. Disk missing?" #~ msgstr "Abspielbefehl fehlgeschlagen. Fehlt die Disk?" #~ msgid "Blur mode" #~ msgstr "Weichzeichenmodus" #~ msgid "Blur radius" #~ msgstr "Weichzeichenradius" #~ msgid "Fade factor" #~ msgstr "Ausblendfaktor" #~ msgid "yuvdeinterlace (1 field)" #~ msgstr "yuvdeinterlace (1 Feld)" #~ msgid "yuvdeinterlace (2 fields)" #~ msgstr "yuvdeinterlace (2 Felder)" #~ msgid "yuvdeinterlace (Antialiasing only)" #~ msgstr "yuvdeinterlace (nur Antialiasing)" #~ msgid "Motion compensating deinterlacer from the mjpegtools project" #~ msgstr "Deinterlacer mir Bewegungsausgleich vom mjpegtools Projekt." #~ msgid "" #~ "Lower quality means more speed. Values above 3 enable slow high quality " #~ "calculations." #~ msgstr "" #~ "Niedrige Qualität heißt höhere Geschwindigkeit. Werte über 3 aktivieren " #~ "langsame, hochqualitative Berechnungen." #~ msgid "Drop mode" #~ msgstr "Wegwerf-Modus" #~ msgid "" #~ "For modes, which take only one source field, specify which field to drop" #~ msgstr "" #~ "Für Methoden, die nur ein Feld verwenden, gib an, welches weggelassen " #~ "werden soll." #~ msgid "Unknown scale mode %s" #~ msgstr "Unbekannte Skaliermethode: %s" #~ msgid "Flip Image" #~ msgstr "Spiegeln" #~ msgid "Order for sinc scaling." #~ msgstr "Ordnung für sinc Skalierung" #~ msgid "Proxy Port" #~ msgstr "Proxy Port" #~ msgid "Interpolate nonexisting" #~ msgstr "Interpoliere fehlende" #~ msgid "Can't detect width or height" #~ msgstr "Kann Bild" #~ msgid "Pulse" #~ msgstr "Pause" #~ msgid "Force floating point" #~ msgstr "Erzwinge Fließkomma" #~ msgid "" #~ "Force floating point processing. This will inprove the quality but might " #~ "slow things down." #~ msgstr "" #~ "Erzwinge Fließkommaverarbeitung. Dies verbessert die Qualität, kann aber " #~ "die Wiedergabe auch bremsen." gmerlin-1.2.0~dfsg/po/LINGUAS0000644000175000017500000000000311764363410015532 0ustar alessioalessiode gmerlin-1.2.0~dfsg/po/ChangeLog0000644000175000017500000000071611764363410016272 0ustar alessioalessio2007-02-12 gettextize * Makefile.in.in: New file, from gettext-0.15. * Rules-quot: New file, from gettext-0.15. * boldquot.sed: New file, from gettext-0.15. * en@boldquot.header: New file, from gettext-0.15. * en@quot.header: New file, from gettext-0.15. * insert-header.sin: New file, from gettext-0.15. * quot.sed: New file, from gettext-0.15. * remove-potcdate.sin: New file, from gettext-0.15. * POTFILES.in: New file. gmerlin-1.2.0~dfsg/po/Makefile.in.in0000644000175000017500000003223211764363410017170 0ustar alessioalessio# Makefile for PO directory in any package using GNU gettext. # Copyright (C) 1995-1997, 2000-2006 by Ulrich Drepper # # This file can be copied and used freely without restrictions. It can # be used in projects which are not available under the GNU General Public # License but which still want to provide support for the GNU gettext # functionality. # Please note that the actual code of GNU gettext is covered by the GNU # General Public License and is *not* in the public domain. # # Origin: gettext-0.15 PACKAGE = @PACKAGE@ VERSION = @VERSION@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ SHELL = /bin/sh @SET_MAKE@ srcdir = @srcdir@ top_srcdir = @top_srcdir@ VPATH = @srcdir@ prefix = @prefix@ exec_prefix = @exec_prefix@ datarootdir = @datarootdir@ datadir = @datadir@ localedir = @localedir@ gettextsrcdir = $(datadir)/gettext/po INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ mkinstalldirs = $(SHELL) @install_sh@ -d mkdir_p = @mkdir_p@ GMSGFMT_ = @GMSGFMT@ GMSGFMT_no = @GMSGFMT@ GMSGFMT_yes = @GMSGFMT_015@ GMSGFMT = $(GMSGFMT_$(USE_MSGCTXT)) MSGFMT_ = @MSGFMT@ MSGFMT_no = @MSGFMT@ MSGFMT_yes = @MSGFMT_015@ MSGFMT = $(MSGFMT_$(USE_MSGCTXT)) XGETTEXT_ = @XGETTEXT@ XGETTEXT_no = @XGETTEXT@ XGETTEXT_yes = @XGETTEXT_015@ XGETTEXT = $(XGETTEXT_$(USE_MSGCTXT)) MSGMERGE = msgmerge MSGMERGE_UPDATE = @MSGMERGE@ --update MSGINIT = msginit MSGCONV = msgconv MSGFILTER = msgfilter POFILES = @POFILES@ GMOFILES = @GMOFILES@ UPDATEPOFILES = @UPDATEPOFILES@ DUMMYPOFILES = @DUMMYPOFILES@ DISTFILES.common = Makefile.in.in remove-potcdate.sin \ $(DISTFILES.common.extra1) $(DISTFILES.common.extra2) $(DISTFILES.common.extra3) DISTFILES = $(DISTFILES.common) Makevars POTFILES.in \ $(POFILES) $(GMOFILES) \ $(DISTFILES.extra1) $(DISTFILES.extra2) $(DISTFILES.extra3) POTFILES = \ CATALOGS = @CATALOGS@ # Makevars gets inserted here. (Don't remove this line!) .SUFFIXES: .SUFFIXES: .po .gmo .mo .sed .sin .nop .po-create .po-update .po.mo: @echo "$(MSGFMT) -c -o $@ $<"; \ $(MSGFMT) -c -o t-$@ $< && mv t-$@ $@ .po.gmo: @lang=`echo $* | sed -e 's,.*/,,'`; \ test "$(srcdir)" = . && cdcmd="" || cdcmd="cd $(srcdir) && "; \ echo "$${cdcmd}rm -f $${lang}.gmo && $(GMSGFMT) -c --statistics -o $${lang}.gmo $${lang}.po"; \ cd $(srcdir) && rm -f $${lang}.gmo && $(GMSGFMT) -c --statistics -o t-$${lang}.gmo $${lang}.po && mv t-$${lang}.gmo $${lang}.gmo .sin.sed: sed -e '/^#/d' $< > t-$@ mv t-$@ $@ all: all-@USE_NLS@ all-yes: stamp-po all-no: # $(srcdir)/$(DOMAIN).pot is only created when needed. When xgettext finds no # internationalized messages, no $(srcdir)/$(DOMAIN).pot is created (because # we don't want to bother translators with empty POT files). We assume that # LINGUAS is empty in this case, i.e. $(POFILES) and $(GMOFILES) are empty. # In this case, stamp-po is a nop (i.e. a phony target). # stamp-po is a timestamp denoting the last time at which the CATALOGS have # been loosely updated. Its purpose is that when a developer or translator # checks out the package via CVS, and the $(DOMAIN).pot file is not in CVS, # "make" will update the $(DOMAIN).pot and the $(CATALOGS), but subsequent # invocations of "make" will do nothing. This timestamp would not be necessary # if updating the $(CATALOGS) would always touch them; however, the rule for # $(POFILES) has been designed to not touch files that don't need to be # changed. stamp-po: $(srcdir)/$(DOMAIN).pot test ! -f $(srcdir)/$(DOMAIN).pot || \ test -z "$(GMOFILES)" || $(MAKE) $(GMOFILES) @test ! -f $(srcdir)/$(DOMAIN).pot || { \ echo "touch stamp-po" && \ echo timestamp > stamp-poT && \ mv stamp-poT stamp-po; \ } # Note: Target 'all' must not depend on target '$(DOMAIN).pot-update', # otherwise packages like GCC can not be built if only parts of the source # have been downloaded. # This target rebuilds $(DOMAIN).pot; it is an expensive operation. # Note that $(DOMAIN).pot is not touched if it doesn't need to be changed. $(DOMAIN).pot-update: $(POTFILES) $(srcdir)/POTFILES.in remove-potcdate.sed if test -n '$(MSGID_BUGS_ADDRESS)' || test '$(PACKAGE_BUGREPORT)' = '@'PACKAGE_BUGREPORT'@'; then \ msgid_bugs_address='$(MSGID_BUGS_ADDRESS)'; \ else \ msgid_bugs_address='$(PACKAGE_BUGREPORT)'; \ fi; \ $(XGETTEXT) --default-domain=$(DOMAIN) --directory=$(top_srcdir) \ --add-comments=TRANSLATORS: $(XGETTEXT_OPTIONS) \ --files-from=$(srcdir)/POTFILES.in \ --copyright-holder='$(COPYRIGHT_HOLDER)' \ --msgid-bugs-address="$$msgid_bugs_address" test ! -f $(DOMAIN).po || { \ if test -f $(srcdir)/$(DOMAIN).pot; then \ sed -f remove-potcdate.sed < $(srcdir)/$(DOMAIN).pot > $(DOMAIN).1po && \ sed -f remove-potcdate.sed < $(DOMAIN).po > $(DOMAIN).2po && \ if cmp $(DOMAIN).1po $(DOMAIN).2po >/dev/null 2>&1; then \ rm -f $(DOMAIN).1po $(DOMAIN).2po $(DOMAIN).po; \ else \ rm -f $(DOMAIN).1po $(DOMAIN).2po $(srcdir)/$(DOMAIN).pot && \ mv $(DOMAIN).po $(srcdir)/$(DOMAIN).pot; \ fi; \ else \ mv $(DOMAIN).po $(srcdir)/$(DOMAIN).pot; \ fi; \ } # This rule has no dependencies: we don't need to update $(DOMAIN).pot at # every "make" invocation, only create it when it is missing. # Only "make $(DOMAIN).pot-update" or "make dist" will force an update. $(srcdir)/$(DOMAIN).pot: $(MAKE) $(DOMAIN).pot-update # This target rebuilds a PO file if $(DOMAIN).pot has changed. # Note that a PO file is not touched if it doesn't need to be changed. $(POFILES): $(srcdir)/$(DOMAIN).pot @lang=`echo $@ | sed -e 's,.*/,,' -e 's/\.po$$//'`; \ if test -f "$(srcdir)/$${lang}.po"; then \ test "$(srcdir)" = . && cdcmd="" || cdcmd="cd $(srcdir) && "; \ echo "$${cdcmd}$(MSGMERGE_UPDATE) $${lang}.po $(DOMAIN).pot"; \ cd $(srcdir) && $(MSGMERGE_UPDATE) $${lang}.po $(DOMAIN).pot; \ else \ $(MAKE) $${lang}.po-create; \ fi install: install-exec install-data install-exec: install-data: install-data-@USE_NLS@ if test "$(PACKAGE)" = "gettext-tools"; then \ $(mkdir_p) $(DESTDIR)$(gettextsrcdir); \ for file in $(DISTFILES.common) Makevars.template; do \ $(INSTALL_DATA) $(srcdir)/$$file \ $(DESTDIR)$(gettextsrcdir)/$$file; \ done; \ for file in Makevars; do \ rm -f $(DESTDIR)$(gettextsrcdir)/$$file; \ done; \ else \ : ; \ fi install-data-no: all install-data-yes: all $(mkdir_p) $(DESTDIR)$(datadir) @catalogs='$(CATALOGS)'; \ for cat in $$catalogs; do \ cat=`basename $$cat`; \ lang=`echo $$cat | sed -e 's/\.gmo$$//'`; \ dir=$(localedir)/$$lang/LC_MESSAGES; \ $(mkdir_p) $(DESTDIR)$$dir; \ if test -r $$cat; then realcat=$$cat; else realcat=$(srcdir)/$$cat; fi; \ $(INSTALL_DATA) $$realcat $(DESTDIR)$$dir/$(DOMAIN).mo; \ echo "installing $$realcat as $(DESTDIR)$$dir/$(DOMAIN).mo"; \ for lc in '' $(EXTRA_LOCALE_CATEGORIES); do \ if test -n "$$lc"; then \ if (cd $(DESTDIR)$(localedir)/$$lang && LC_ALL=C ls -l -d $$lc 2>/dev/null) | grep ' -> ' >/dev/null; then \ link=`cd $(DESTDIR)$(localedir)/$$lang && LC_ALL=C ls -l -d $$lc | sed -e 's/^.* -> //'`; \ mv $(DESTDIR)$(localedir)/$$lang/$$lc $(DESTDIR)$(localedir)/$$lang/$$lc.old; \ mkdir $(DESTDIR)$(localedir)/$$lang/$$lc; \ (cd $(DESTDIR)$(localedir)/$$lang/$$lc.old && \ for file in *; do \ if test -f $$file; then \ ln -s ../$$link/$$file $(DESTDIR)$(localedir)/$$lang/$$lc/$$file; \ fi; \ done); \ rm -f $(DESTDIR)$(localedir)/$$lang/$$lc.old; \ else \ if test -d $(DESTDIR)$(localedir)/$$lang/$$lc; then \ :; \ else \ rm -f $(DESTDIR)$(localedir)/$$lang/$$lc; \ mkdir $(DESTDIR)$(localedir)/$$lang/$$lc; \ fi; \ fi; \ rm -f $(DESTDIR)$(localedir)/$$lang/$$lc/$(DOMAIN).mo; \ ln -s ../LC_MESSAGES/$(DOMAIN).mo $(DESTDIR)$(localedir)/$$lang/$$lc/$(DOMAIN).mo 2>/dev/null || \ ln $(DESTDIR)$(localedir)/$$lang/LC_MESSAGES/$(DOMAIN).mo $(DESTDIR)$(localedir)/$$lang/$$lc/$(DOMAIN).mo 2>/dev/null || \ cp -p $(DESTDIR)$(localedir)/$$lang/LC_MESSAGES/$(DOMAIN).mo $(DESTDIR)$(localedir)/$$lang/$$lc/$(DOMAIN).mo; \ echo "installing $$realcat link as $(DESTDIR)$(localedir)/$$lang/$$lc/$(DOMAIN).mo"; \ fi; \ done; \ done install-strip: install installdirs: installdirs-exec installdirs-data installdirs-exec: installdirs-data: installdirs-data-@USE_NLS@ if test "$(PACKAGE)" = "gettext-tools"; then \ $(mkdir_p) $(DESTDIR)$(gettextsrcdir); \ else \ : ; \ fi installdirs-data-no: installdirs-data-yes: $(mkdir_p) $(DESTDIR)$(datadir) @catalogs='$(CATALOGS)'; \ for cat in $$catalogs; do \ cat=`basename $$cat`; \ lang=`echo $$cat | sed -e 's/\.gmo$$//'`; \ dir=$(localedir)/$$lang/LC_MESSAGES; \ $(mkdir_p) $(DESTDIR)$$dir; \ for lc in '' $(EXTRA_LOCALE_CATEGORIES); do \ if test -n "$$lc"; then \ if (cd $(DESTDIR)$(localedir)/$$lang && LC_ALL=C ls -l -d $$lc 2>/dev/null) | grep ' -> ' >/dev/null; then \ link=`cd $(DESTDIR)$(localedir)/$$lang && LC_ALL=C ls -l -d $$lc | sed -e 's/^.* -> //'`; \ mv $(DESTDIR)$(localedir)/$$lang/$$lc $(DESTDIR)$(localedir)/$$lang/$$lc.old; \ mkdir $(DESTDIR)$(localedir)/$$lang/$$lc; \ (cd $(DESTDIR)$(localedir)/$$lang/$$lc.old && \ for file in *; do \ if test -f $$file; then \ ln -s ../$$link/$$file $(DESTDIR)$(localedir)/$$lang/$$lc/$$file; \ fi; \ done); \ rm -f $(DESTDIR)$(localedir)/$$lang/$$lc.old; \ else \ if test -d $(DESTDIR)$(localedir)/$$lang/$$lc; then \ :; \ else \ rm -f $(DESTDIR)$(localedir)/$$lang/$$lc; \ mkdir $(DESTDIR)$(localedir)/$$lang/$$lc; \ fi; \ fi; \ fi; \ done; \ done # Define this as empty until I found a useful application. installcheck: uninstall: uninstall-exec uninstall-data uninstall-exec: uninstall-data: uninstall-data-@USE_NLS@ if test "$(PACKAGE)" = "gettext-tools"; then \ for file in $(DISTFILES.common) Makevars.template; do \ rm -f $(DESTDIR)$(gettextsrcdir)/$$file; \ done; \ else \ : ; \ fi uninstall-data-no: uninstall-data-yes: catalogs='$(CATALOGS)'; \ for cat in $$catalogs; do \ cat=`basename $$cat`; \ lang=`echo $$cat | sed -e 's/\.gmo$$//'`; \ for lc in LC_MESSAGES $(EXTRA_LOCALE_CATEGORIES); do \ rm -f $(DESTDIR)$(localedir)/$$lang/$$lc/$(DOMAIN).mo; \ done; \ done check: all info dvi ps pdf html tags TAGS ctags CTAGS ID: mostlyclean: rm -f remove-potcdate.sed rm -f stamp-poT rm -f core core.* $(DOMAIN).po $(DOMAIN).1po $(DOMAIN).2po *.new.po rm -fr *.o clean: mostlyclean distclean: clean rm -f Makefile Makefile.in POTFILES *.mo maintainer-clean: distclean @echo "This command is intended for maintainers to use;" @echo "it deletes files that may require special tools to rebuild." rm -f stamp-po $(GMOFILES) distdir = $(top_builddir)/$(PACKAGE)-$(VERSION)/$(subdir) dist distdir: $(MAKE) update-po @$(MAKE) dist2 # This is a separate target because 'update-po' must be executed before. dist2: stamp-po $(DISTFILES) dists="$(DISTFILES)"; \ if test "$(PACKAGE)" = "gettext-tools"; then \ dists="$$dists Makevars.template"; \ fi; \ if test -f $(srcdir)/$(DOMAIN).pot; then \ dists="$$dists $(DOMAIN).pot stamp-po"; \ fi; \ if test -f $(srcdir)/ChangeLog; then \ dists="$$dists ChangeLog"; \ fi; \ for i in 0 1 2 3 4 5 6 7 8 9; do \ if test -f $(srcdir)/ChangeLog.$$i; then \ dists="$$dists ChangeLog.$$i"; \ fi; \ done; \ if test -f $(srcdir)/LINGUAS; then dists="$$dists LINGUAS"; fi; \ for file in $$dists; do \ if test -f $$file; then \ cp -p $$file $(distdir) || exit 1; \ else \ cp -p $(srcdir)/$$file $(distdir) || exit 1; \ fi; \ done update-po: Makefile $(MAKE) $(DOMAIN).pot-update test -z "$(UPDATEPOFILES)" || $(MAKE) $(UPDATEPOFILES) $(MAKE) update-gmo # General rule for creating PO files. .nop.po-create: @lang=`echo $@ | sed -e 's/\.po-create$$//'`; \ echo "File $$lang.po does not exist. If you are a translator, you can create it through 'msginit'." 1>&2; \ exit 1 # General rule for updating PO files. .nop.po-update: @lang=`echo $@ | sed -e 's/\.po-update$$//'`; \ if test "$(PACKAGE)" = "gettext-tools"; then PATH=`pwd`/../src:$$PATH; fi; \ tmpdir=`pwd`; \ echo "$$lang:"; \ test "$(srcdir)" = . && cdcmd="" || cdcmd="cd $(srcdir) && "; \ echo "$${cdcmd}$(MSGMERGE) $$lang.po $(DOMAIN).pot -o $$lang.new.po"; \ cd $(srcdir); \ if $(MSGMERGE) $$lang.po $(DOMAIN).pot -o $$tmpdir/$$lang.new.po; then \ if cmp $$lang.po $$tmpdir/$$lang.new.po >/dev/null 2>&1; then \ rm -f $$tmpdir/$$lang.new.po; \ else \ if mv -f $$tmpdir/$$lang.new.po $$lang.po; then \ :; \ else \ echo "msgmerge for $$lang.po failed: cannot move $$tmpdir/$$lang.new.po to $$lang.po" 1>&2; \ exit 1; \ fi; \ fi; \ else \ echo "msgmerge for $$lang.po failed!" 1>&2; \ rm -f $$tmpdir/$$lang.new.po; \ fi $(DUMMYPOFILES): update-gmo: Makefile $(GMOFILES) @: Makefile: Makefile.in.in Makevars $(top_builddir)/config.status @POMAKEFILEDEPS@ cd $(top_builddir) \ && $(SHELL) ./config.status $(subdir)/$@.in po-directories force: # Tell versions [3.59,3.63) of GNU make not to export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: gmerlin-1.2.0~dfsg/po/Rules-quot0000644000175000017500000000337611764363410016530 0ustar alessioalessio# Special Makefile rules for English message catalogs with quotation marks. DISTFILES.common.extra1 = quot.sed boldquot.sed en@quot.header en@boldquot.header insert-header.sin Rules-quot .SUFFIXES: .insert-header .po-update-en en@quot.po-create: $(MAKE) en@quot.po-update en@boldquot.po-create: $(MAKE) en@boldquot.po-update en@quot.po-update: en@quot.po-update-en en@boldquot.po-update: en@boldquot.po-update-en .insert-header.po-update-en: @lang=`echo $@ | sed -e 's/\.po-update-en$$//'`; \ if test "$(PACKAGE)" = "gettext"; then PATH=`pwd`/../src:$$PATH; GETTEXTLIBDIR=`cd $(top_srcdir)/src && pwd`; export GETTEXTLIBDIR; fi; \ tmpdir=`pwd`; \ echo "$$lang:"; \ ll=`echo $$lang | sed -e 's/@.*//'`; \ LC_ALL=C; export LC_ALL; \ cd $(srcdir); \ if $(MSGINIT) -i $(DOMAIN).pot --no-translator -l $$ll -o - 2>/dev/null | sed -f $$tmpdir/$$lang.insert-header | $(MSGCONV) -t UTF-8 | $(MSGFILTER) sed -f `echo $$lang | sed -e 's/.*@//'`.sed 2>/dev/null > $$tmpdir/$$lang.new.po; then \ if cmp $$lang.po $$tmpdir/$$lang.new.po >/dev/null 2>&1; then \ rm -f $$tmpdir/$$lang.new.po; \ else \ if mv -f $$tmpdir/$$lang.new.po $$lang.po; then \ :; \ else \ echo "creation of $$lang.po failed: cannot move $$tmpdir/$$lang.new.po to $$lang.po" 1>&2; \ exit 1; \ fi; \ fi; \ else \ echo "creation of $$lang.po failed!" 1>&2; \ rm -f $$tmpdir/$$lang.new.po; \ fi en@quot.insert-header: insert-header.sin sed -e '/^#/d' -e 's/HEADER/en@quot.header/g' $(srcdir)/insert-header.sin > en@quot.insert-header en@boldquot.insert-header: insert-header.sin sed -e '/^#/d' -e 's/HEADER/en@boldquot.header/g' $(srcdir)/insert-header.sin > en@boldquot.insert-header mostlyclean: mostlyclean-quot mostlyclean-quot: rm -f *.insert-header gmerlin-1.2.0~dfsg/po/POTFILES.in0000644000175000017500000002343311764363415016303 0ustar alessioalessioutils/cpuinfo.c plugins/jack/oa_jack.c plugins/jack/i_jack.c plugins/jack/jack_common.c plugins/jack/jack_common.h plugins/pulseaudio/oa_pulse.c plugins/pulseaudio/pulseaudio_common.c plugins/pulseaudio/i_pulse.c plugins/pulseaudio/pulseaudio_common.h plugins/subwriters/e_subtext.c plugins/esd/i_esd.c plugins/esd/oa_esd.c plugins/v4l/pwc.c plugins/v4l/pwc.h plugins/v4l/i_v4l.c plugins/v4l/pwc-ioctl.h plugins/image/targa.h plugins/image/ir_tga.c plugins/image/ir_bmp.c plugins/image/iw_tga.c plugins/image/ir_pnm.c plugins/image/iw_bmp.c plugins/image/targa.c plugins/image/iw_pnm.c plugins/x11/ov_x11.c plugins/x11/i_x11.c plugins/oss/oss_common.h plugins/oss/i_oss.c plugins/oss/oa_oss.c plugins/oss/oss_common.c plugins/visualization/vis_scope.c plugins/audiofilters/fa_sampleformat.c plugins/audiofilters/fa_volume.c plugins/alsa/i_alsa.c plugins/alsa/oa_alsa.c plugins/alsa/alsa_common.c plugins/alsa/alsa_common.h plugins/postprocessors/cdrdao_common.c plugins/postprocessors/cdrdao_common.h plugins/postprocessors/e_pp_cdrdao.c plugins/postprocessors/e_pp_vcdimager.c plugins/videofilters/fv_colormatrix_yuv.c plugins/videofilters/fv_deinterlace.c plugins/videofilters/fv_transform.c plugins/videofilters/fv_swapfields.c plugins/videofilters/fv_textlogo.c plugins/videofilters/colormatrix.c plugins/videofilters/fv_cropscale.c plugins/videofilters/bgyadif.c plugins/videofilters/bgyadif.h plugins/videofilters/fv_pixelformat.c plugins/videofilters/fv_tcdisplay.c plugins/videofilters/fv_zoom.c plugins/videofilters/deinterlace.h plugins/videofilters/fv_tlp.c plugins/videofilters/fv_tctweak.c plugins/videofilters/fv_interlace.c plugins/videofilters/fv_colorbalance.c plugins/videofilters/fv_flip.c plugins/videofilters/fv_framerate.c plugins/videofilters/fv_oldcolor.c plugins/videofilters/fv_colormatrix_rgb.c plugins/videofilters/fv_decimate.c plugins/videofilters/fv_blur.c plugins/videofilters/colormatrix.h plugins/videofilters/fv_invert_rgb.c plugins/videofilters/fv_bitshift.c plugins/videofilters/fv_equalizer.c plugins/gavl/ir_gavl.c plugins/gavl/iw_gavl.c plugins/mikmod/i_mikmod.c plugins/cdaudio/sha1.h plugins/cdaudio/cddb.c plugins/cdaudio/cdaudio_xml.c plugins/cdaudio/cdparanoia.c plugins/cdaudio/sha1.c plugins/cdaudio/cdtext.c plugins/cdaudio/cdaudio.c plugins/cdaudio/cdaudio.h plugins/cdaudio/i_cdaudio.c plugins/cdaudio/musicbrainz.c plugins/png/e_spumux.c plugins/png/ir_png.c plugins/png/pngwriter.h plugins/png/iw_png.c plugins/png/pngwriter.c plugins/v4l2/i_v4l2.c plugins/v4l2/convert.c plugins/v4l2/ov_v4l2.c plugins/v4l2/v4l2_common.h plugins/v4l2/convert.h plugins/v4l2/v4l2_common.c plugins/lqt/i_lqt.c plugins/lqt/lqt_common.h plugins/lqt/lqt_common.c plugins/lqt/lqtgavl.c plugins/lqt/lqtgavl.h plugins/lqt/e_lqt.c plugins/tiff/iw_tiff.c plugins/tiff/ir_tiff.c plugins/jpeg/iw_jpeg.c plugins/jpeg/ir_jpeg.c plugins/jpeg/exif.h plugins/jpeg/exif.c plugins/wavwrite/e_wav.c plugins/edl/i_edl.c include/ladspa.h include/registry_priv.h include/visualize_priv.h include/ovl2text.h include/playerprivate.h include/player_thread.h include/recorder_private.h include/gui_gtk/message.h include/gui_gtk/question.h include/gui_gtk/textview.h include/gui_gtk/chapterdialog.h include/gui_gtk/fileentry.h include/gui_gtk/urllink.h include/gui_gtk/logwindow.h include/gui_gtk/gtkutils.h include/gui_gtk/urlselect.h include/gui_gtk/auth.h include/gui_gtk/tree.h include/gui_gtk/plugin.h include/gui_gtk/driveselect.h include/gui_gtk/infowindow.h include/gui_gtk/display.h include/gui_gtk/multiinfo.h include/gui_gtk/presetmenu.h include/gui_gtk/fileselect.h include/gui_gtk/button.h include/gui_gtk/aboutwindow.h include/gui_gtk/albumentry.h include/gui_gtk/audio.h include/gui_gtk/slider.h include/gui_gtk/scrolltext.h include/treeprivate.h include/x11/x11.h include/x11/x11_window_private.h include/bglv.h include/frei0r.h include/pluginreg_priv.h include/gmerlin/cmdline.h include/gmerlin/msgqueue.h include/gmerlin/ov.h include/gmerlin/transcoder_track.h include/gmerlin/transcoder.h include/gmerlin/visualize.h include/gmerlin/pluginregistry.h include/gmerlin/ocr.h include/gmerlin/bggavl.h include/gmerlin/transcodermsg.h include/gmerlin/mediafiledevice.h include/gmerlin/player.h include/gmerlin/accelerator.h include/gmerlin/log.h include/gmerlin/playermsg.h include/gmerlin/osd.h include/gmerlin/parameter.h include/gmerlin/singlepic.h include/gmerlin/tree.h include/gmerlin/plugin.h include/gmerlin/textrenderer.h include/gmerlin/encoder.h include/gmerlin/filters.h include/gmerlin/cfg_dialog.h include/gmerlin/lcdproc.h include/gmerlin/keycodes.h include/gmerlin/charset.h include/gmerlin/bgsocket.h include/gmerlin/cfg_registry.h include/gmerlin/bg_sem.h include/gmerlin/subprocess.h include/gmerlin/utils.h include/gmerlin/remote.h include/gmerlin/serialize.h include/gmerlin/preset.h include/gmerlin/pluginfuncs.h include/gmerlin/converters.h include/gmerlin/xmlutils.h include/gmerlin/fileformat.h include/gmerlin/translation.h include/gmerlin/recorder.h include/gmerlin/edl.h include/gmerlin/streaminfo.h include/bgfrei0r.h include/language_table.h include/bgfreetype.h include/float_cast.h include/bgladspa.h include/md5.h apps/player/gmerlin.h apps/player/skinbrowser.c apps/player/gmerlin.c apps/player/player_remote.h apps/player/skin.c apps/player/main.c apps/player/remote.c apps/player/cfgdialog.c apps/player/display.h apps/player/mainmenu.c apps/player/playerwindow.c apps/player/display.c apps/player/playerwindow.h apps/player/gmerlin_remote.c apps/plugincfg/gmerlin_plugincfg.c apps/cmdlinerecorder/gmerlin-record.c apps/camelot/vloopback.h apps/camelot/webcam.c apps/camelot/vloopback.c apps/camelot/webcam_priv.h apps/camelot/webcam.h apps/camelot/main.c apps/camelot/webcam_window.c apps/camelot/webcam_window.h apps/transcoder/tracklist.h apps/transcoder/trackdialog.h apps/transcoder/transcoder_window.h apps/transcoder/transcoder_window.c apps/transcoder/main.c apps/transcoder/ppwidget.c apps/transcoder/gmerlin_transcoder_remote.c apps/transcoder/transcoder_remote.h apps/transcoder/tracklist.c apps/transcoder/ppwidget.h apps/transcoder/trackdialog.c apps/visualizer/gmerlin_visualizer.c apps/cmdlineplayer/gmerlin_play.c apps/kbd/kbd_daemon.c apps/kbd/keys_xml.c apps/kbd/kbd_config.c apps/kbd/kbd.h apps/kbd/kbd_remote.h apps/kbd/kbd_remote.c apps/kbd/keys.c apps/kbd/kbd.c apps/alsamixer/mixer.c apps/alsamixer/g_card.c apps/alsamixer/g_mixer.c apps/alsamixer/main.c apps/alsamixer/card.c apps/alsamixer/alsamixer.h apps/alsamixer/g_control.c apps/alsamixer/gui.h apps/nmjedit/file.c apps/nmjedit/bgalbum.c apps/nmjedit/nmjedit.h apps/nmjedit/nmjedit.c apps/nmjedit/dir.c apps/nmjedit/create.c apps/nmjedit/song.c apps/nmjedit/album.c apps/nmjedit/gmerlin-nmjedit.c apps/recorder/gmerlin_recorder.c apps/recorder/recorder_window.c apps/recorder/recorder_window.h apps/thumbnailer/gmerlin-video-thumbnailer.c tests/gmerlin_vpsnr.c tests/scrolltext.c tests/vumeter.c tests/question.c tests/album2pls.c tests/v4ltest.c tests/thumbnail.c tests/ladspa.c tests/imgconvert.c tests/album2m3u.c tests/chapter.c tests/insertchannel.c tests/playtree.c tests/gmerlin_vanalyze.c tests/server.c tests/textrenderer.c tests/ocrtest.c tests/fvtest.c tests/v4ldump.c tests/dump_plugins.c tests/client.c tests/cfgtest.c tests/extractchannel.c tests/msgtest.c tests/gmerlin_imgdiff.c tests/audioplayer1.c tests/auth.c tests/visualization.c tests/gmerlin_psnr.c tests/gmerlin_ssim.c tests/message.c tests/videoplayer1.c tests/gmerlin_visualize.c lib/pluginreg_xml.c lib/md5.c lib/recorder_video.c lib/utf8.c lib/transcoder_track_xml.c lib/bggavl.c lib/player_subtitle.c lib/transcoder_pp.c lib/cfg_registry.c lib/player_video.c lib/serialize.c lib/preset.c lib/bgladspa.c lib/searchpath.c lib/parameter_xml.c lib/pluginregistry.c lib/visualize_slave.c lib/visualize.c lib/thumbnail.c lib/formats.c lib/log.c lib/cmdline.c lib/ov.c lib/converters.c lib/mediafiledevice.c lib/lcdproc.c lib/player_thread.c lib/language_table.c lib/fileformat.c lib/player_loop.c lib/charset.c lib/transcoder.c lib/preset_xml.c lib/player_time.c lib/x11/xvideo.c lib/x11/overlay.c lib/x11/x11_video.c lib/x11/ximage.c lib/x11/x11_window.c lib/x11/glvideo.c lib/x11/icon.c lib/x11/x11_gl.c lib/x11/grab.c lib/x11/screensaver.c lib/x11/x11_event.c lib/x11/shm.c lib/textrenderer.c lib/streaminfo.c lib/cfg_xml.c lib/tree.c lib/chapterlist_xml.c lib/singlepic.c lib/hexdump.c lib/cfg_item.c lib/metadata.c lib/edl.c lib/uthread_sem.c lib/bgxml.c lib/accelerator.c lib/player_audio.c lib/transcoder_track.c lib/osd.c lib/msgqueue.c lib/remote.c lib/player_input.c lib/player_ov.c lib/parameter.c lib/device.c lib/chapterlist.c lib/stringutils.c lib/ocr.c lib/metadata_xml.c lib/pluginfuncs.c lib/urilist.c lib/socket.c lib/player_oa.c lib/album_xml.c lib/encoder.c lib/gtk/cfg_multi_menu.c lib/gtk/infowindow.c lib/gtk/gtkutils.c lib/gtk/urllink.c lib/gtk/albumwindow.c lib/gtk/scrolltext.c lib/gtk/treewidget.c lib/gtk/vumeter.c lib/gtk/logwindow.c lib/gtk/question.c lib/gtk/cfg_file.c lib/gtk/cfg_checkbutton.c lib/gtk/cfg_color.c lib/gtk/plugin_multi.c lib/gtk/fileselect.c lib/gtk/chapterdialog.c lib/gtk/slider.c lib/gtk/button.c lib/gtk/cfg_time.c lib/gtk/fileentry.c lib/gtk/textview.c lib/gtk/cfg_stringlist.c lib/gtk/pluginmenu.c lib/gtk/presetmenu.c lib/gtk/cfg_spinbutton.c lib/gtk/urlselect.c lib/gtk/cfg_font.c lib/gtk/albumwidget.c lib/gtk/aboutwindow.c lib/gtk/cfg_slider.c lib/gtk/treewindow.c lib/gtk/cfg_multi_list.c lib/gtk/multiinfo.c lib/gtk/textwindow.c lib/gtk/driveselect.c lib/gtk/display.c lib/gtk/cfg_button.c lib/gtk/cfg_dialog.c lib/gtk/albumentry.c lib/gtk/plugin_single.c lib/gtk/cfg_position.c lib/gtk/plugininfo.c lib/gtk/auth.c lib/gtk/gtk_dialog.h lib/gtk/cfg_device.c lib/gtk/message.c lib/gtk/cfg_string.c lib/threadpool.c lib/edl_xml.c lib/recorder.c lib/cfg_section.c lib/subprocess.c lib/player.c lib/recorder_audio.c lib/bgfrei0r.c lib/album.c lib/ovl2text.c lib/edldec.c lib/playercmd.c lib/tree_xml.c lib/filters.c lib/translation.c lib/bglv.c gmerlin-1.2.0~dfsg/po/gmerlin.pot0000644000175000017500000051314411764363440016710 0ustar alessioalessio# SOME DESCRIPTIVE TITLE. # Copyright (C) YEAR Members of the gmerlin project # This file is distributed under the same license as the PACKAGE package. # FIRST AUTHOR , YEAR. # #, fuzzy msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: gmerlin-general@lists.sourceforge.net\n" "POT-Creation-Date: 2012-06-08 13:50+0200\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" #: plugins/jack/oa_jack.c:256 plugins/jack/i_jack.c:189 msgid "Jack" msgstr "" #: plugins/jack/oa_jack.c:257 msgid "Jack output plugin" msgstr "" #: plugins/jack/i_jack.c:58 #, c-format msgid "Dropping %d samples" msgstr "" #: plugins/jack/i_jack.c:190 msgid "Jack recorder" msgstr "" #: plugins/jack/jack_common.c:32 msgid "Connect ports" msgstr "" #: plugins/jack/jack_common.c:35 msgid "Autoconnect ports" msgstr "" #: plugins/jack/jack_common.c:184 #, c-format msgid "Connecting %s with %s failed" msgstr "" #: plugins/pulseaudio/oa_pulse.c:86 plugins/pulseaudio/i_pulse.c:155 msgid "PulseAudio" msgstr "" #: plugins/pulseaudio/oa_pulse.c:87 msgid "PulseAudio output" msgstr "" #: plugins/pulseaudio/pulseaudio_common.c:186 #, c-format msgid "Connection to Pulseaudio failed: %s" msgstr "" #: plugins/pulseaudio/i_pulse.c:70 plugins/oss/i_oss.c:57 #: plugins/alsa/i_alsa.c:49 lib/mediafiledevice.c:100 msgid "Channel Mode" msgstr "" #: plugins/pulseaudio/i_pulse.c:74 plugins/oss/i_oss.c:61 #: plugins/alsa/i_alsa.c:53 lib/mediafiledevice.c:104 msgid "Mono" msgstr "" #: plugins/pulseaudio/i_pulse.c:74 plugins/oss/i_oss.c:61 #: plugins/alsa/i_alsa.c:53 lib/mediafiledevice.c:104 msgid "Stereo" msgstr "" #: plugins/pulseaudio/i_pulse.c:78 plugins/oss/i_oss.c:65 #: plugins/alsa/i_alsa.c:57 msgid "Bits" msgstr "" #: plugins/pulseaudio/i_pulse.c:85 plugins/oss/i_oss.c:72 #: plugins/alsa/i_alsa.c:64 lib/mediafiledevice.c:108 msgid "Samplerate [Hz]" msgstr "" #: plugins/pulseaudio/i_pulse.c:93 plugins/cdaudio/i_cdaudio.c:588 #: plugins/cdaudio/i_cdaudio.c:630 msgid "Server" msgstr "" #: plugins/pulseaudio/i_pulse.c:95 msgid "Server to connect to. Leave empty for default." msgstr "" #: plugins/pulseaudio/i_pulse.c:99 msgid "Source" msgstr "" #: plugins/pulseaudio/i_pulse.c:101 msgid "Source to open. Use the PulseAudio manager for available Sources." msgstr "" #: plugins/pulseaudio/i_pulse.c:156 msgid "" "PulseAudio capture. You can specify the source, where we'll get the audio." msgstr "" #: plugins/subwriters/e_subtext.c:75 msgid "Ignoring empty subtitle" msgstr "" #: plugins/subwriters/e_subtext.c:265 plugins/image/iw_pnm.c:194 #: plugins/postprocessors/e_pp_vcdimager.c:110 plugins/lqt/e_lqt.c:703 msgid "Format" msgstr "" #: plugins/subwriters/e_subtext.c:269 msgid "Subrip (.srt)" msgstr "" #: plugins/subwriters/e_subtext.c:269 msgid "MPlayer mpsub" msgstr "" #: plugins/subwriters/e_subtext.c:308 lib/gtk/plugininfo.c:161 msgid "Text subtitle exporter" msgstr "" #: plugins/subwriters/e_subtext.c:309 msgid "" "Plugin for exporting text subtitles. Supported formats are MPSub and SRT" msgstr "" #: plugins/esd/i_esd.c:58 plugins/esd/oa_esd.c:47 msgid "Host (empty: local)" msgstr "" #: plugins/esd/i_esd.c:63 msgid "Input Mode" msgstr "" #: plugins/esd/i_esd.c:67 apps/recorder/recorder_window.c:622 msgid "Record" msgstr "" #: plugins/esd/i_esd.c:67 apps/camelot/webcam_window.c:584 #: apps/recorder/recorder_window.c:759 msgid "Monitor" msgstr "" #: plugins/esd/i_esd.c:172 msgid "Cannot connect to daemon" msgstr "" #: plugins/esd/i_esd.c:235 plugins/esd/i_esd.c:236 msgid "EsounD input driver" msgstr "" #: plugins/esd/oa_esd.c:172 plugins/esd/oa_esd.c:173 msgid "EsounD output driver" msgstr "" #: plugins/v4l/pwc.c:70 msgid "PWC General" msgstr "" #: plugins/v4l/pwc.c:75 include/gmerlin/bggavl.h:186 #: include/gmerlin/bggavl.h:204 lib/visualize.c:356 msgid "Framerate" msgstr "" #: plugins/v4l/pwc.c:83 plugins/tiff/iw_tiff.c:188 msgid "Compression" msgstr "" #: plugins/v4l/pwc.c:87 plugins/videofilters/fv_deinterlace.c:146 #: plugins/tiff/iw_tiff.c:191 include/gmerlin/bggavl.h:229 #: include/gmerlin/bggavl.h:324 include/gmerlin/bggavl.h:633 #: include/gmerlin/bggavl.h:657 msgid "None" msgstr "" #: plugins/v4l/pwc.c:88 msgid "Low" msgstr "" #: plugins/v4l/pwc.c:89 msgid "Medium" msgstr "" #: plugins/v4l/pwc.c:90 msgid "High" msgstr "" #: plugins/v4l/pwc.c:100 msgid "Gain control (-1 = Auto)" msgstr "" #: plugins/v4l/pwc.c:109 msgid "Shutter speed (-1 = Auto)" msgstr "" #: plugins/v4l/pwc.c:118 msgid "Sharpness (-1 = Auto)" msgstr "" #: plugins/v4l/pwc.c:127 msgid "Backlight compensation" msgstr "" #: plugins/v4l/pwc.c:134 msgid "Flicker compensation" msgstr "" #: plugins/v4l/pwc.c:141 msgid "PWC Whitebalance" msgstr "" #: plugins/v4l/pwc.c:146 msgid "White balance" msgstr "" #: plugins/v4l/pwc.c:156 msgid "Indoor" msgstr "" #: plugins/v4l/pwc.c:157 msgid "Outdoor" msgstr "" #: plugins/v4l/pwc.c:158 msgid "Fluorescent lighting" msgstr "" #: plugins/v4l/pwc.c:159 msgid "Manual" msgstr "" #: plugins/v4l/pwc.c:160 plugins/videofilters/fv_cropscale.c:431 #: plugins/cdaudio/cdparanoia.c:195 include/gmerlin/bggavl.h:289 #: include/gmerlin/bggavl.h:308 include/gmerlin/bggavl.h:323 #: include/gmerlin/bggavl.h:657 include/gmerlin/bggavl.h:670 #: lib/x11/x11_window.c:1195 msgid "Auto" msgstr "" #: plugins/v4l/pwc.c:165 msgid "Manual red gain" msgstr "" #: plugins/v4l/pwc.c:174 msgid "Manual blue gain" msgstr "" #: plugins/v4l/pwc.c:183 msgid "Auto speed" msgstr "" #: plugins/v4l/pwc.c:192 msgid "Auto delay" msgstr "" #: plugins/v4l/pwc.c:201 msgid "PWC LED" msgstr "" #: plugins/v4l/pwc.c:206 msgid "LED on time (secs)" msgstr "" #: plugins/v4l/pwc.c:215 msgid "LED off time (secs)" msgstr "" #: plugins/v4l/i_v4l.c:206 #, c-format msgid "Cannot open device %s: %s" msgstr "" #: plugins/v4l/i_v4l.c:215 msgid "Phillips webcam detected" msgstr "" #: plugins/v4l/i_v4l.c:221 apps/camelot/vloopback.c:541 #, c-format msgid "VIDIOCGPICT failed: %s" msgstr "" #: plugins/v4l/i_v4l.c:245 apps/camelot/vloopback.c:551 #, c-format msgid "VIDIOCSPICT failed: %s" msgstr "" #: plugins/v4l/i_v4l.c:255 #, c-format msgid "VIDIOCGWIN failed: %s" msgstr "" #: plugins/v4l/i_v4l.c:268 #, c-format msgid "VIDIOCSWIN failed: %s (invalaid picture dimensions?)" msgstr "" #: plugins/v4l/i_v4l.c:298 #, c-format msgid "VIDIOCGMBUF failed: %s" msgstr "" #: plugins/v4l/i_v4l.c:306 plugins/v4l2/ov_v4l2.c:298 #, c-format msgid "mmap failed: %s" msgstr "" #: plugins/v4l/i_v4l.c:406 plugins/oss/i_oss.c:51 plugins/oss/oa_oss.c:67 #: plugins/postprocessors/cdrdao_common.h:37 plugins/v4l2/i_v4l2.c:711 #: plugins/v4l2/ov_v4l2.c:100 apps/camelot/vloopback.c:730 #: lib/gtk/treewidget.c:1119 msgid "Device" msgstr "" #: plugins/v4l/i_v4l.c:411 msgid "V4L Device" msgstr "" #: plugins/v4l/i_v4l.c:417 plugins/v4l/i_v4l.c:422 plugins/v4l2/i_v4l2.c:729 #: plugins/v4l2/i_v4l2.c:734 apps/camelot/vloopback.c:746 msgid "Resolution" msgstr "" #: plugins/v4l/i_v4l.c:433 plugins/v4l2/i_v4l2.c:745 #: apps/camelot/vloopback.c:757 msgid "QSIF (160x112)" msgstr "" #: plugins/v4l/i_v4l.c:434 plugins/v4l2/i_v4l2.c:746 #: apps/camelot/vloopback.c:758 msgid "QCIF (176x144)" msgstr "" #: plugins/v4l/i_v4l.c:435 plugins/v4l2/i_v4l2.c:747 #: apps/camelot/vloopback.c:759 msgid "QVGA (320x240)" msgstr "" #: plugins/v4l/i_v4l.c:436 plugins/v4l2/i_v4l2.c:748 #: apps/camelot/vloopback.c:760 msgid "SIF(352x240)" msgstr "" #: plugins/v4l/i_v4l.c:437 plugins/v4l2/i_v4l2.c:749 #: apps/camelot/vloopback.c:761 msgid "CIF (352x288)" msgstr "" #: plugins/v4l/i_v4l.c:438 plugins/v4l2/i_v4l2.c:750 #: apps/camelot/vloopback.c:762 msgid "VGA (640x480)" msgstr "" #: plugins/v4l/i_v4l.c:439 plugins/videofilters/fv_cropscale.c:227 #: plugins/v4l2/i_v4l2.c:751 include/gmerlin/bggavl.h:171 #: include/gmerlin/bggavl.h:464 apps/camelot/vloopback.c:763 msgid "User defined" msgstr "" #: plugins/v4l/i_v4l.c:444 plugins/videofilters/fv_cropscale.c:259 #: plugins/v4l2/i_v4l2.c:756 include/gmerlin/bggavl.h:390 #: apps/camelot/vloopback.c:769 msgid "User defined width" msgstr "" #: plugins/v4l/i_v4l.c:452 plugins/videofilters/fv_cropscale.c:270 #: plugins/v4l2/i_v4l2.c:764 include/gmerlin/bggavl.h:401 #: apps/camelot/vloopback.c:778 msgid "User defined height" msgstr "" #: plugins/v4l/i_v4l.c:460 msgid "Settings" msgstr "" #: plugins/v4l/i_v4l.c:465 plugins/videofilters/fv_equalizer.c:426 msgid "Brightness" msgstr "" #: plugins/v4l/i_v4l.c:474 plugins/videofilters/fv_equalizer.c:456 msgid "Hue" msgstr "" #: plugins/v4l/i_v4l.c:483 msgid "Colour" msgstr "" #: plugins/v4l/i_v4l.c:492 plugins/videofilters/fv_equalizer.c:436 msgid "Contrast" msgstr "" #: plugins/v4l/i_v4l.c:501 msgid "Whiteness" msgstr "" #: plugins/v4l/i_v4l.c:697 msgid "V4L" msgstr "" #: plugins/v4l/i_v4l.c:698 msgid "video4linux recording plugin. Supports only video and no tuner decives." msgstr "" #: plugins/image/ir_tga.c:103 msgid "Read tga failed" msgstr "" #: plugins/image/ir_tga.c:228 msgid "TGA reader" msgstr "" #: plugins/image/ir_tga.c:229 msgid "Reader for TGA images" msgstr "" #: plugins/image/ir_bmp.c:234 plugins/image/ir_pnm.c:108 lib/singlepic.c:1030 #, c-format msgid "Cannot open file %s: %s" msgstr "" #: plugins/image/ir_bmp.c:244 msgid "Cannot read File type" msgstr "" #: plugins/image/ir_bmp.c:249 msgid "File is no BMP" msgstr "" #: plugins/image/ir_bmp.c:290 msgid "Cannot detect image dimensions" msgstr "" #: plugins/image/ir_bmp.c:298 #, c-format msgid "Depth %d not supported" msgstr "" #: plugins/image/ir_bmp.c:760 msgid "BMP reader" msgstr "" #: plugins/image/ir_bmp.c:761 msgid "Reader for BMP images" msgstr "" #: plugins/image/iw_tga.c:140 plugins/image/iw_tga.c:143 #, c-format msgid "Cannot save %s: %s" msgstr "" #: plugins/image/iw_tga.c:160 msgid "Do RLE compression" msgstr "" #: plugins/image/iw_tga.c:192 msgid "TGA writer" msgstr "" #: plugins/image/iw_tga.c:193 msgid "Writer for TGA images" msgstr "" #: plugins/image/ir_pnm.c:127 msgid "Can't read File type" msgstr "" #: plugins/image/ir_pnm.c:142 msgid "File is no pnm" msgstr "" #: plugins/image/ir_pnm.c:168 plugins/image/ir_pnm.c:241 #, c-format msgid "File is no pnm (%.1s%.1s%.1s)" msgstr "" #: plugins/image/ir_pnm.c:185 msgid "Cannot read width" msgstr "" #: plugins/image/ir_pnm.c:198 msgid "Cannot read height" msgstr "" #: plugins/image/ir_pnm.c:211 msgid "Cannot read maxval" msgstr "" #: plugins/image/ir_pnm.c:235 msgid "PAM format not suported" msgstr "" #: plugins/image/ir_pnm.c:310 msgid "PBMascii" msgstr "" #: plugins/image/ir_pnm.c:344 msgid "PBMbin" msgstr "" #: plugins/image/ir_pnm.c:382 msgid "PGMascii" msgstr "" #: plugins/image/ir_pnm.c:409 msgid "PGMascii_16" msgstr "" #: plugins/image/ir_pnm.c:438 msgid "PGMbin" msgstr "" #: plugins/image/ir_pnm.c:461 msgid "PGMbin_16" msgstr "" #: plugins/image/ir_pnm.c:486 msgid "PPMascii" msgstr "" #: plugins/image/ir_pnm.c:529 msgid "PPMascii_16" msgstr "" #: plugins/image/ir_pnm.c:607 msgid "PPMbin_16" msgstr "" #: plugins/image/ir_pnm.c:655 msgid "PNM reader" msgstr "" #: plugins/image/ir_pnm.c:656 msgid "Reader for PBM/PGM/PPM images" msgstr "" #: plugins/image/iw_bmp.c:129 plugins/image/iw_pnm.c:115 #: plugins/oss/i_oss.c:202 plugins/oss/oa_oss.c:144 plugins/oss/oa_oss.c:154 #: plugins/oss/oa_oss.c:164 plugins/png/pngwriter.c:56 #: plugins/tiff/iw_tiff.c:98 plugins/jpeg/iw_jpeg.c:115 #, c-format msgid "Cannot open %s: %s" msgstr "" #: plugins/image/iw_bmp.c:229 msgid "BMP writer" msgstr "" #: plugins/image/iw_bmp.c:230 msgid "Writer for BMP images" msgstr "" #: plugins/image/iw_pnm.c:197 msgid "Binary" msgstr "" #: plugins/image/iw_pnm.c:197 msgid "ASCII" msgstr "" #: plugins/image/iw_pnm.c:203 lib/metadata.c:101 msgid "Comment" msgstr "" #: plugins/image/iw_pnm.c:207 msgid "Comment which will be written in front of every file" msgstr "" #: plugins/image/iw_pnm.c:243 msgid "PPM/PGM writer" msgstr "" #: plugins/image/iw_pnm.c:244 msgid "Writer for PPM/PGM images" msgstr "" #: plugins/x11/ov_x11.c:551 #, c-format msgid "Got window size: %d %d" msgstr "" #: plugins/x11/ov_x11.c:919 plugins/x11/i_x11.c:96 msgid "X11" msgstr "" #: plugins/x11/ov_x11.c:920 msgid "" "X11 display driver with support for XVideo, XImage and OpenGL. Shared memory " "(XShm) is used where available." msgstr "" #: plugins/x11/i_x11.c:97 msgid "X11 grabber" msgstr "" #: plugins/oss/i_oss.c:174 msgid "Invalid number of bits" msgstr "" #: plugins/oss/i_oss.c:189 msgid "Invalid number of channels" msgstr "" #: plugins/oss/i_oss.c:212 plugins/oss/oa_oss.c:178 plugins/oss/oa_oss.c:190 #: plugins/oss/oa_oss.c:202 #, c-format msgid "Cannot set sampleformat for %s" msgstr "" #: plugins/oss/i_oss.c:220 plugins/oss/oa_oss.c:215 #, c-format msgid "Device %s doesn't support %d channel sound" msgstr "" #: plugins/oss/i_oss.c:229 plugins/oss/oa_oss.c:253 plugins/oss/oa_oss.c:265 #: plugins/oss/oa_oss.c:278 #, c-format msgid "Samplerate %f kHz not supported by device %s" msgstr "" #: plugins/oss/i_oss.c:282 plugins/oss/oa_oss.c:569 msgid "OSS" msgstr "" #: plugins/oss/i_oss.c:283 msgid "OSS Recorder" msgstr "" #: plugins/oss/oa_oss.c:53 msgid "Multichannel Mode" msgstr "" #: plugins/oss/oa_oss.c:60 msgid "None (Downmix)" msgstr "" #: plugins/oss/oa_oss.c:61 msgid "Multiple devices" msgstr "" #: plugins/oss/oa_oss.c:62 msgid "Creative Multichannel" msgstr "" #: plugins/oss/oa_oss.c:73 msgid "Use Rear Device" msgstr "" #: plugins/oss/oa_oss.c:79 msgid "Rear Device" msgstr "" #: plugins/oss/oa_oss.c:85 msgid "Use Center/LFE Device" msgstr "" #: plugins/oss/oa_oss.c:91 msgid "Center/LFE Device" msgstr "" #: plugins/oss/oa_oss.c:227 plugins/oss/oa_oss.c:240 #, c-format msgid "Device %s supports no %d-channel sound" msgstr "" #: plugins/oss/oa_oss.c:462 plugins/oss/oa_oss.c:469 plugins/oss/oa_oss.c:477 #, c-format msgid "Write failed: %s" msgstr "" #: plugins/oss/oa_oss.c:509 msgid "SNDCTL_DSP_GETODELAY ioctl failed" msgstr "" #: plugins/oss/oa_oss.c:570 msgid "OSS output driver" msgstr "" #: plugins/visualization/vis_scope.c:705 msgid "Scope" msgstr "" #: plugins/visualization/vis_scope.c:706 msgid "Scope plugin" msgstr "" #: plugins/audiofilters/fa_sampleformat.c:70 include/gmerlin/bggavl.h:640 msgid "Sampleformat" msgstr "" #: plugins/audiofilters/fa_sampleformat.c:200 include/gmerlin/bggavl.h:628 msgid "Force sampleformat" msgstr "" #: plugins/audiofilters/fa_sampleformat.c:201 msgid "" "This forces a sampleformat as input for the next filter. Its mainly used for " "testing." msgstr "" #: plugins/audiofilters/fa_volume.c:68 msgid "Volume" msgstr "" #: plugins/audiofilters/fa_volume.c:156 msgid "Volume control" msgstr "" #: plugins/audiofilters/fa_volume.c:157 msgid "Simple volume control" msgstr "" #: plugins/alsa/i_alsa.c:72 plugins/alsa/oa_alsa.c:95 msgid "Buffer time" msgstr "" #: plugins/alsa/i_alsa.c:77 msgid "" "Set the buffer time (in milliseconds). Larger values improve recording " "performance on slow systems under load." msgstr "" #: plugins/alsa/i_alsa.c:82 plugins/alsa/oa_alsa.c:88 msgid "User device" msgstr "" #: plugins/alsa/i_alsa.c:84 msgid "" "Enter a custom device to use for recording. Leave empty to use the settings " "above" msgstr "" #: plugins/alsa/i_alsa.c:271 msgid "Dropping samples" msgstr "" #: plugins/alsa/i_alsa.c:275 msgid "snd_pcm_prepare failed" msgstr "" #: plugins/alsa/i_alsa.c:282 msgid "Unknown error" msgstr "" #: plugins/alsa/i_alsa.c:343 plugins/alsa/oa_alsa.c:472 msgid "Alsa" msgstr "" #: plugins/alsa/i_alsa.c:344 msgid "Alsa recorder" msgstr "" #: plugins/alsa/oa_alsa.c:60 msgid "Enable 4.0 Surround" msgstr "" #: plugins/alsa/oa_alsa.c:63 msgid "Use the surround 4.0 (aka quadrophonic) device" msgstr "" #: plugins/alsa/oa_alsa.c:67 msgid "Enable 4.1 Surround" msgstr "" #: plugins/alsa/oa_alsa.c:70 msgid "Use the surround 4.1 device" msgstr "" #: plugins/alsa/oa_alsa.c:74 msgid "Enable 5.0 Surround" msgstr "" #: plugins/alsa/oa_alsa.c:77 msgid "Use the surround 5.0 device" msgstr "" #: plugins/alsa/oa_alsa.c:81 msgid "Enable 5.1 Surround" msgstr "" #: plugins/alsa/oa_alsa.c:84 msgid "Use the surround 5.1 device" msgstr "" #: plugins/alsa/oa_alsa.c:90 msgid "" "Enter a custom device to use for playback. Leave empty to use the settings " "above" msgstr "" #: plugins/alsa/oa_alsa.c:100 msgid "" "Set the buffer time (in milliseconds). Larger values improve playback " "performance on slow systems under load. Smaller values decrease the latency " "of the volume control." msgstr "" #: plugins/alsa/oa_alsa.c:387 #, c-format msgid "snd_pcm_write returned %s" msgstr "" #: plugins/alsa/oa_alsa.c:473 msgid "Alsa output plugin with support for channel configurations up to 5.1" msgstr "" #: plugins/alsa/alsa_common.c:62 #, c-format msgid "snd_pcm_open failed for device %s (%s)" msgstr "" #: plugins/alsa/alsa_common.c:73 msgid "snd_pcm_hw_params_malloc failed" msgstr "" #: plugins/alsa/alsa_common.c:78 msgid "snd_pcm_hw_params_any failed" msgstr "" #: plugins/alsa/alsa_common.c:87 msgid "snd_pcm_hw_params_set_access failed" msgstr "" #: plugins/alsa/alsa_common.c:106 plugins/alsa/alsa_common.c:120 #: plugins/alsa/alsa_common.c:145 plugins/alsa/alsa_common.c:184 msgid "snd_pcm_hw_params_set_format failed" msgstr "" #: plugins/alsa/alsa_common.c:218 plugins/alsa/alsa_common.c:232 #, c-format msgid "snd_pcm_hw_params_set_channels failed (Format has %d channels)" msgstr "" #: plugins/alsa/alsa_common.c:249 msgid "snd_pcm_hw_params_set_rate_near failed" msgstr "" #: plugins/alsa/alsa_common.c:255 #, c-format msgid "Samplerate %d not supported by device %s, using %d" msgstr "" #: plugins/alsa/alsa_common.c:286 msgid "snd_pcm_hw_params_set_period_size failed" msgstr "" #: plugins/alsa/alsa_common.c:295 msgid "snd_pcm_hw_params_set_buffer_size failed" msgstr "" #: plugins/alsa/alsa_common.c:307 msgid "snd_pcm_hw_params failed" msgstr "" #: plugins/alsa/alsa_common.c:318 msgid "Alsa initialization failed" msgstr "" #: plugins/alsa/alsa_common.c:381 msgid "Card" msgstr "" #: plugins/alsa/alsa_common.c:389 msgid "No soundcards found" msgstr "" #: plugins/alsa/alsa_common.c:396 msgid "Default" msgstr "" #: plugins/alsa/alsa_common.c:405 #, c-format msgid "control open failed (%i): %s" msgstr "" #: plugins/alsa/alsa_common.c:412 #, c-format msgid "control hardware info failed (%i): %s" msgstr "" #: plugins/alsa/alsa_common.c:425 msgid "snd_ctl_pcm_next_device failed" msgstr "" #: plugins/alsa/alsa_common.c:441 #, c-format msgid "control digital audio info failed (%i): %s" msgstr "" #: plugins/postprocessors/cdrdao_common.c:111 msgid "Not running cdrdao (disabled by user)" msgstr "" #: plugins/postprocessors/cdrdao_common.c:116 msgid "cdrdao executable not found" msgstr "" #: plugins/postprocessors/cdrdao_common.c:181 #: plugins/postprocessors/cdrdao_common.c:186 #: plugins/postprocessors/cdrdao_common.c:194 #: plugins/postprocessors/cdrdao_common.c:209 #: plugins/postprocessors/cdrdao_common.c:212 #: plugins/postprocessors/e_pp_vcdimager.c:225 #, c-format msgid "%s" msgstr "" #: plugins/postprocessors/cdrdao_common.h:26 msgid "Burn options" msgstr "" #: plugins/postprocessors/cdrdao_common.h:31 msgid "Run cdrdao" msgstr "" #: plugins/postprocessors/cdrdao_common.h:40 msgid "" "Device to use as burner. Type \"cdrdao scanbus\" at the commandline for " "available devices. Leave this empty to use the default /dev/cdrecorder." msgstr "" #: plugins/postprocessors/cdrdao_common.h:44 msgid "Driver" msgstr "" #: plugins/postprocessors/cdrdao_common.h:47 msgid "" "Driver to use. Check the cdrdao manual page and the cdrdao README for " "available drivers/options. Leave this empty to attempt autodetection." msgstr "" #: plugins/postprocessors/cdrdao_common.h:51 msgid "Eject after burning" msgstr "" #: plugins/postprocessors/cdrdao_common.h:57 msgid "Simulate" msgstr "" #: plugins/postprocessors/cdrdao_common.h:63 plugins/cdaudio/cdparanoia.c:192 msgid "Speed" msgstr "" #: plugins/postprocessors/cdrdao_common.h:68 msgid "Set the writing speed. 0 means autodetect." msgstr "" #: plugins/postprocessors/cdrdao_common.h:72 msgid "No pause" msgstr "" #: plugins/postprocessors/cdrdao_common.h:75 msgid "Skip the 10 second pause before writing or simulating starts." msgstr "" #: plugins/postprocessors/e_pp_cdrdao.c:96 msgid "Audio CD options" msgstr "" #: plugins/postprocessors/e_pp_cdrdao.c:101 msgid "TOC file" msgstr "" #: plugins/postprocessors/e_pp_cdrdao.c:107 msgid "Gap between tracks" msgstr "" #: plugins/postprocessors/e_pp_cdrdao.c:110 msgid "" "Pre gap of each track in CD frames (1/75 seconds). Default is 150 (2 sec)." msgstr "" #: plugins/postprocessors/e_pp_cdrdao.c:114 msgid "Write CD-Text" msgstr "" #: plugins/postprocessors/e_pp_cdrdao.c:243 #, c-format msgid "Cannot get duration of file %s" msgstr "" #: plugins/postprocessors/e_pp_cdrdao.c:290 msgid "Skipping cdrdao run (no tracks)" msgstr "" #: plugins/postprocessors/e_pp_cdrdao.c:433 #, c-format msgid "Wrote %s" msgstr "" #: plugins/postprocessors/e_pp_cdrdao.c:443 #: plugins/postprocessors/e_pp_cdrdao.c:447 #: plugins/postprocessors/e_pp_vcdimager.c:365 #: plugins/postprocessors/e_pp_vcdimager.c:369 #: plugins/postprocessors/e_pp_vcdimager.c:376 #: plugins/postprocessors/e_pp_vcdimager.c:378 lib/tree.c:1478 lib/ocr.c:265 #, c-format msgid "Removing %s" msgstr "" #: plugins/postprocessors/e_pp_cdrdao.c:466 msgid "Audio CD generator/burner" msgstr "" #: plugins/postprocessors/e_pp_cdrdao.c:467 msgid "" "This is a frontend for generating audio CD images (optionally with CD-Text) " "for cdrdao (http://cdrdao.sourceforge.net). Optional burning is also " "supported." msgstr "" #: plugins/postprocessors/e_pp_vcdimager.c:105 msgid "VCD options" msgstr "" #: plugins/postprocessors/e_pp_vcdimager.c:114 msgid "VCD 1.1" msgstr "" #: plugins/postprocessors/e_pp_vcdimager.c:114 msgid "VCD 2.0" msgstr "" #: plugins/postprocessors/e_pp_vcdimager.c:114 msgid "SVCD" msgstr "" #: plugins/postprocessors/e_pp_vcdimager.c:114 msgid "HQSVCD" msgstr "" #: plugins/postprocessors/e_pp_vcdimager.c:118 msgid "ISO 9660 volume label" msgstr "" #: plugins/postprocessors/e_pp_vcdimager.c:124 msgid "Xml file" msgstr "" #: plugins/postprocessors/e_pp_vcdimager.c:130 msgid "Bin file" msgstr "" #: plugins/postprocessors/e_pp_vcdimager.c:136 msgid "Cue file" msgstr "" #: plugins/postprocessors/e_pp_vcdimager.c:254 #, c-format msgid "Scanning %s" msgstr "" #: plugins/postprocessors/e_pp_vcdimager.c:261 msgid "Writing image" msgstr "" #: plugins/postprocessors/e_pp_vcdimager.c:322 #, c-format msgid "vcdxgen failed: %s" msgstr "" #: plugins/postprocessors/e_pp_vcdimager.c:403 msgid "VCD image generator/burner" msgstr "" #: plugins/postprocessors/e_pp_vcdimager.c:404 msgid "" "This is a frontend for generating (S)VCD images with the vcdimager tools " "(http://www.vcdimager.org). Burning with cdrdao (http://cdrdao.sourceforge." "net) is also possible." msgstr "" #: plugins/videofilters/fv_colormatrix_yuv.c:90 msgid "Luminance" msgstr "" #: plugins/videofilters/fv_colormatrix_yuv.c:96 msgid "Luminance -> Luminance" msgstr "" #: plugins/videofilters/fv_colormatrix_yuv.c:106 msgid "Cb -> Luminance" msgstr "" #: plugins/videofilters/fv_colormatrix_yuv.c:116 msgid "Cr -> Luminance" msgstr "" #: plugins/videofilters/fv_colormatrix_yuv.c:126 msgid "Alpha -> Luminance" msgstr "" #: plugins/videofilters/fv_colormatrix_yuv.c:136 msgid "Luminance offset" msgstr "" #: plugins/videofilters/fv_colormatrix_yuv.c:148 msgid "Cb" msgstr "" #: plugins/videofilters/fv_colormatrix_yuv.c:154 msgid "Luminance -> Cb" msgstr "" #: plugins/videofilters/fv_colormatrix_yuv.c:164 msgid "Cb -> Cb" msgstr "" #: plugins/videofilters/fv_colormatrix_yuv.c:174 msgid "Cr -> Cb" msgstr "" #: plugins/videofilters/fv_colormatrix_yuv.c:184 msgid "Alpha -> Cb" msgstr "" #: plugins/videofilters/fv_colormatrix_yuv.c:194 msgid "Cb offset" msgstr "" #: plugins/videofilters/fv_colormatrix_yuv.c:206 msgid "Cr" msgstr "" #: plugins/videofilters/fv_colormatrix_yuv.c:212 msgid "Luminance -> Cr" msgstr "" #: plugins/videofilters/fv_colormatrix_yuv.c:222 msgid "Cb -> Cr" msgstr "" #: plugins/videofilters/fv_colormatrix_yuv.c:232 msgid "Cr -> Cr" msgstr "" #: plugins/videofilters/fv_colormatrix_yuv.c:242 msgid "Alpha -> Cr" msgstr "" #: plugins/videofilters/fv_colormatrix_yuv.c:252 msgid "Cr offset" msgstr "" #: plugins/videofilters/fv_colormatrix_yuv.c:264 #: plugins/videofilters/fv_colormatrix_rgb.c:268 msgid "Alpha" msgstr "" #: plugins/videofilters/fv_colormatrix_yuv.c:270 msgid "Luminance -> Alpha" msgstr "" #: plugins/videofilters/fv_colormatrix_yuv.c:280 msgid "Cb -> Alpha" msgstr "" #: plugins/videofilters/fv_colormatrix_yuv.c:290 msgid "Cr -> Alpha" msgstr "" #: plugins/videofilters/fv_colormatrix_yuv.c:300 #: plugins/videofilters/fv_colormatrix_rgb.c:304 msgid "Alpha -> Alpha" msgstr "" #: plugins/videofilters/fv_colormatrix_yuv.c:310 #: plugins/videofilters/fv_colormatrix_rgb.c:314 msgid "Alpha offset" msgstr "" #: plugins/videofilters/fv_colormatrix_yuv.c:320 #: plugins/videofilters/fv_colormatrix_rgb.c:324 msgid "Misc" msgstr "" #: plugins/videofilters/fv_colormatrix_yuv.c:325 #: plugins/videofilters/fv_colormatrix_rgb.c:329 msgid "Force alpha" msgstr "" #: plugins/videofilters/fv_colormatrix_yuv.c:328 #: plugins/videofilters/fv_colormatrix_rgb.c:332 msgid "" "Create video with alpha channel even if the input format has no alpha " "channel. Use this to generate the alpha channel from other channels using " "the colormatrix." msgstr "" #: plugins/videofilters/fv_colormatrix_yuv.c:460 msgid "Y'CbCr(A) Colormatrix" msgstr "" #: plugins/videofilters/fv_colormatrix_yuv.c:461 msgid "" "Generic colormatrix (Y'CbCrA). You pass the coefficients in Y'CbCr(A) " "coordinates, but the processing will work in RGB(A) as well." msgstr "" #: plugins/videofilters/fv_deinterlace.c:133 msgid "Method" msgstr "" #: plugins/videofilters/fv_deinterlace.c:147 msgid "Scanline doubler" msgstr "" #: plugins/videofilters/fv_deinterlace.c:148 msgid "Scaler (hardware)" msgstr "" #: plugins/videofilters/fv_deinterlace.c:149 msgid "Scaler (software)" msgstr "" #: plugins/videofilters/fv_deinterlace.c:150 msgid "Blend" msgstr "" #: plugins/videofilters/fv_deinterlace.c:151 msgid "Yadif" msgstr "" #: plugins/videofilters/fv_deinterlace.c:152 msgid "Yadif (fast)" msgstr "" #: plugins/videofilters/fv_deinterlace.c:154 #: plugins/videofilters/fv_tctweak.c:87 msgid "Do nothing" msgstr "" #: plugins/videofilters/fv_deinterlace.c:155 msgid "Simply double all scanlines. Very fast but low image quality" msgstr "" #: plugins/videofilters/fv_deinterlace.c:157 msgid "" "Drop one field and change the pixel aspect ratio such that a subsequent " "hardware scaler will scale the image to the original height" msgstr "" #: plugins/videofilters/fv_deinterlace.c:158 msgid "Drop one field and scale the image to the original height" msgstr "" #: plugins/videofilters/fv_deinterlace.c:159 msgid "yadif" msgstr "" #: plugins/videofilters/fv_deinterlace.c:160 msgid "yadif (fast mode)" msgstr "" #: plugins/videofilters/fv_deinterlace.c:165 include/gmerlin/bggavl.h:244 msgid "Force deinterlacing" msgstr "" #: plugins/videofilters/fv_deinterlace.c:172 msgid "Output mode" msgstr "" #: plugins/videofilters/fv_deinterlace.c:176 msgid "" "Specify which field to output. Outputting both fields is not always " "supported." msgstr "" #: plugins/videofilters/fv_deinterlace.c:178 msgid "Top field" msgstr "" #: plugins/videofilters/fv_deinterlace.c:179 msgid "Bottom field" msgstr "" #: plugins/videofilters/fv_deinterlace.c:180 msgid "First field" msgstr "" #: plugins/videofilters/fv_deinterlace.c:181 msgid "Second field" msgstr "" #: plugins/videofilters/fv_deinterlace.c:182 msgid "Both fields" msgstr "" #: plugins/videofilters/fv_deinterlace.c:510 msgid "Deinterlacer" msgstr "" #: plugins/videofilters/fv_deinterlace.c:511 msgid "Deinterlace with various algorithms" msgstr "" #: plugins/videofilters/fv_transform.c:166 #: plugins/videofilters/fv_textlogo.c:86 #: plugins/videofilters/fv_tcdisplay.c:81 plugins/cdaudio/i_cdaudio.c:541 #: apps/player/cfgdialog.c:104 apps/transcoder/transcoder_window.c:1304 #: apps/transcoder/transcoder_window.c:1331 #: apps/transcoder/transcoder_window.c:1354 apps/transcoder/trackdialog.c:87 #: apps/transcoder/trackdialog.c:226 apps/transcoder/trackdialog.c:296 #: apps/transcoder/trackdialog.c:382 apps/transcoder/trackdialog.c:450 #: apps/visualizer/gmerlin_visualizer.c:890 #: apps/recorder/recorder_window.c:724 apps/recorder/recorder_window.c:743 #: lib/player_subtitle.c:117 lib/pluginregistry.c:2114 #: lib/x11/x11_window.c:1112 lib/transcoder_track.c:1326 msgid "General" msgstr "" #: plugins/videofilters/fv_transform.c:171 msgid "Transformation mode" msgstr "" #: plugins/videofilters/fv_transform.c:178 #: plugins/videofilters/fv_transform.c:208 msgid "Rotate" msgstr "" #: plugins/videofilters/fv_transform.c:179 #: plugins/videofilters/fv_transform.c:223 msgid "Generic affine" msgstr "" #: plugins/videofilters/fv_transform.c:180 #: plugins/videofilters/fv_transform.c:290 msgid "Perspective" msgstr "" #: plugins/videofilters/fv_transform.c:181 #: plugins/videofilters/fv_transform.c:331 msgid "Lens effect" msgstr "" #: plugins/videofilters/fv_transform.c:182 #: plugins/videofilters/fv_transform.c:367 msgid "Pinch/whirl" msgstr "" #: plugins/videofilters/fv_transform.c:185 msgid "" "Choose Transformation method. Each method can be configured in it's section." msgstr "" #: plugins/videofilters/fv_transform.c:190 msgid "Interpolation mode" msgstr "" #: plugins/videofilters/fv_transform.c:197 msgid "" "Choose interpolation method. Auto means to choose based on the conversion " "quality. Nearest is fastest, Bicubic is slowest." msgstr "" #: plugins/videofilters/fv_transform.c:201 plugins/videofilters/fv_zoom.c:160 #: plugins/lqt/e_lqt.c:948 include/gmerlin/bggavl.h:367 #: lib/x11/x11_window.c:1170 lib/ocr.c:152 msgid "Background color" msgstr "" #: plugins/videofilters/fv_transform.c:213 #: plugins/videofilters/fv_transform.c:400 msgid "Angle" msgstr "" #: plugins/videofilters/fv_transform.c:228 msgid "X -> X" msgstr "" #: plugins/videofilters/fv_transform.c:238 msgid "X -> Y" msgstr "" #: plugins/videofilters/fv_transform.c:248 msgid "Y -> X" msgstr "" #: plugins/videofilters/fv_transform.c:258 msgid "Y -> Y" msgstr "" #: plugins/videofilters/fv_transform.c:268 msgid "X Offset" msgstr "" #: plugins/videofilters/fv_transform.c:275 msgid "Normalized X offset. 1 corresponds to image with." msgstr "" #: plugins/videofilters/fv_transform.c:279 msgid "Y Offset" msgstr "" #: plugins/videofilters/fv_transform.c:286 msgid "Normalized Y offset. 1 corresponds to image height." msgstr "" #: plugins/videofilters/fv_transform.c:295 msgid "Top left" msgstr "" #: plugins/videofilters/fv_transform.c:300 msgid "Top left corner in normalized image coordinates" msgstr "" #: plugins/videofilters/fv_transform.c:304 msgid "Top right" msgstr "" #: plugins/videofilters/fv_transform.c:309 msgid "Top right corner in normalized image coordinates" msgstr "" #: plugins/videofilters/fv_transform.c:313 msgid "Bottom left" msgstr "" #: plugins/videofilters/fv_transform.c:318 msgid "Bottom left corner in normalized image coordinates" msgstr "" #: plugins/videofilters/fv_transform.c:322 msgid "Bottom right" msgstr "" #: plugins/videofilters/fv_transform.c:327 msgid "Bottom right corner in normalized image coordinates" msgstr "" #: plugins/videofilters/fv_transform.c:336 msgid "Position" msgstr "" #: plugins/videofilters/fv_transform.c:341 msgid "Center of the lens" msgstr "" #: plugins/videofilters/fv_transform.c:345 msgid "Diameter" msgstr "" #: plugins/videofilters/fv_transform.c:352 msgid "Diamater of the lens (1 is image size)" msgstr "" #: plugins/videofilters/fv_transform.c:356 plugins/videofilters/fv_zoom.c:378 msgid "Zoom" msgstr "" #: plugins/videofilters/fv_transform.c:363 msgid "Zoom factor" msgstr "" #: plugins/videofilters/fv_transform.c:372 #: plugins/videofilters/fv_textlogo.c:136 #: plugins/videofilters/fv_textlogo.c:145 #: plugins/videofilters/fv_tcdisplay.c:132 #: plugins/videofilters/fv_tcdisplay.c:141 lib/textrenderer.c:98 #: lib/textrenderer.c:107 lib/osd.c:121 lib/osd.c:129 msgid "Center" msgstr "" #: plugins/videofilters/fv_transform.c:380 msgid "Radius" msgstr "" #: plugins/videofilters/fv_transform.c:390 msgid "Pinch" msgstr "" #: plugins/videofilters/fv_transform.c:1262 msgid "Transform" msgstr "" #: plugins/videofilters/fv_transform.c:1263 msgid "Transform the image with different methods" msgstr "" #: plugins/videofilters/fv_swapfields.c:137 msgid "Unsupported interlace mode, need top-first or bottom-first" msgstr "" #: plugins/videofilters/fv_swapfields.c:258 msgid "Swap fields" msgstr "" #: plugins/videofilters/fv_swapfields.c:259 msgid "Swap field order" msgstr "" #: plugins/videofilters/fv_textlogo.c:91 msgid "Text" msgstr "" #: plugins/videofilters/fv_textlogo.c:94 msgid "Text to display" msgstr "" #: plugins/videofilters/fv_textlogo.c:98 #: plugins/videofilters/fv_tcdisplay.c:94 lib/textrenderer.c:60 msgid "Render options" msgstr "" #: plugins/videofilters/fv_textlogo.c:103 #: plugins/videofilters/fv_tcdisplay.c:99 plugins/lqt/e_lqt.c:942 #: lib/textrenderer.c:65 msgid "Text color" msgstr "" #: plugins/videofilters/fv_textlogo.c:110 #: plugins/videofilters/fv_cropscale.c:317 #: plugins/videofilters/fv_tcdisplay.c:106 lib/textrenderer.c:72 lib/osd.c:101 msgid "Border color" msgstr "" #: plugins/videofilters/fv_textlogo.c:116 #: plugins/videofilters/fv_tcdisplay.c:112 lib/textrenderer.c:78 lib/osd.c:107 msgid "Border width" msgstr "" #: plugins/videofilters/fv_textlogo.c:126 #: plugins/videofilters/fv_tcdisplay.c:122 apps/player/display.c:110 #: apps/transcoder/transcoder_window.c:195 lib/textrenderer.c:88 msgid "Font" msgstr "" #: plugins/videofilters/fv_textlogo.c:132 #: plugins/videofilters/fv_tcdisplay.c:128 lib/textrenderer.c:94 lib/osd.c:117 msgid "Horizontal justify" msgstr "" #: plugins/videofilters/fv_textlogo.c:136 #: plugins/videofilters/fv_tcdisplay.c:132 lib/textrenderer.c:98 lib/osd.c:121 msgid "Left" msgstr "" #: plugins/videofilters/fv_textlogo.c:136 #: plugins/videofilters/fv_tcdisplay.c:132 lib/textrenderer.c:98 lib/osd.c:121 msgid "Right" msgstr "" #: plugins/videofilters/fv_textlogo.c:141 #: plugins/videofilters/fv_tcdisplay.c:137 lib/textrenderer.c:103 #: lib/osd.c:125 msgid "Vertical justify" msgstr "" #: plugins/videofilters/fv_textlogo.c:145 #: plugins/videofilters/fv_tcdisplay.c:141 lib/textrenderer.c:107 #: lib/osd.c:129 msgid "Top" msgstr "" #: plugins/videofilters/fv_textlogo.c:145 #: plugins/videofilters/fv_tcdisplay.c:141 lib/textrenderer.c:107 #: lib/osd.c:129 msgid "Bottom" msgstr "" #: plugins/videofilters/fv_textlogo.c:149 #: plugins/videofilters/fv_tcdisplay.c:145 lib/textrenderer.c:111 msgid "Cache size" msgstr "" #: plugins/videofilters/fv_textlogo.c:156 #: plugins/videofilters/fv_tcdisplay.c:152 lib/textrenderer.c:117 msgid "" "Specify, how many different characters are cached for faster rendering. For " "European languages, this never needs to be larger than 255." msgstr "" #: plugins/videofilters/fv_textlogo.c:160 #: plugins/videofilters/fv_tcdisplay.c:156 lib/textrenderer.c:121 #: lib/osd.c:133 msgid "Left border" msgstr "" #: plugins/videofilters/fv_textlogo.c:165 #: plugins/videofilters/fv_tcdisplay.c:161 lib/textrenderer.c:126 #: lib/osd.c:138 msgid "Distance from the left text border to the image border" msgstr "" #: plugins/videofilters/fv_textlogo.c:169 #: plugins/videofilters/fv_tcdisplay.c:165 lib/textrenderer.c:130 #: lib/osd.c:142 msgid "Right border" msgstr "" #: plugins/videofilters/fv_textlogo.c:174 #: plugins/videofilters/fv_tcdisplay.c:170 lib/textrenderer.c:135 #: lib/osd.c:147 msgid "Distance from the right text border to the image border" msgstr "" #: plugins/videofilters/fv_textlogo.c:178 #: plugins/videofilters/fv_tcdisplay.c:174 lib/textrenderer.c:139 #: lib/osd.c:151 msgid "Top border" msgstr "" #: plugins/videofilters/fv_textlogo.c:183 #: plugins/videofilters/fv_tcdisplay.c:179 lib/textrenderer.c:144 #: lib/osd.c:156 msgid "Distance from the top text border to the image border" msgstr "" #: plugins/videofilters/fv_textlogo.c:192 #: plugins/videofilters/fv_tcdisplay.c:188 lib/textrenderer.c:153 #: lib/osd.c:165 msgid "Distance from the bottom text border to the image border" msgstr "" #: plugins/videofilters/fv_textlogo.c:196 #: plugins/videofilters/fv_textlogo.c:199 #: plugins/videofilters/fv_tcdisplay.c:192 #: plugins/videofilters/fv_tcdisplay.c:195 lib/textrenderer.c:157 #: lib/textrenderer.c:159 msgid "Ignore linebreaks" msgstr "" #: plugins/videofilters/fv_textlogo.c:314 msgid "Text logo" msgstr "" #: plugins/videofilters/fv_textlogo.c:315 msgid "Burn a static text onto video frames" msgstr "" #: plugins/videofilters/colormatrix.c:1434 #: plugins/videofilters/fv_colorbalance.c:610 #: plugins/videofilters/fv_equalizer.c:729 #, c-format msgid "Pixelformat: %s" msgstr "" #: plugins/videofilters/fv_cropscale.c:137 msgid "Crop" msgstr "" #: plugins/videofilters/fv_cropscale.c:142 msgid "Crop left" msgstr "" #: plugins/videofilters/fv_cropscale.c:150 msgid "Cut this many pixels from the left border of the source images." msgstr "" #: plugins/videofilters/fv_cropscale.c:154 msgid "Crop right" msgstr "" #: plugins/videofilters/fv_cropscale.c:162 msgid "Cut this many pixels from the right border of the source images." msgstr "" #: plugins/videofilters/fv_cropscale.c:166 msgid "Crop top" msgstr "" #: plugins/videofilters/fv_cropscale.c:174 msgid "Cut this many pixels from the top border of the source images." msgstr "" #: plugins/videofilters/fv_cropscale.c:178 msgid "Crop bottom" msgstr "" #: plugins/videofilters/fv_cropscale.c:186 msgid "Cut this many pixels from the bottom border of the source images." msgstr "" #: plugins/videofilters/fv_cropscale.c:189 #: plugins/videofilters/fv_cropscale.c:194 include/gmerlin/bggavl.h:495 #: include/gmerlin/bggavl.h:512 msgid "Image size" msgstr "" #: plugins/videofilters/fv_cropscale.c:226 #: plugins/videofilters/fv_cropscale.c:408 include/gmerlin/bggavl.h:193 msgid "From Source" msgstr "" #: plugins/videofilters/fv_cropscale.c:228 include/gmerlin/bggavl.h:465 msgid "PAL DVD D1 4:3 (720 x 576)" msgstr "" #: plugins/videofilters/fv_cropscale.c:229 include/gmerlin/bggavl.h:466 msgid "PAL DVD D1 16:9 (720 x 576)" msgstr "" #: plugins/videofilters/fv_cropscale.c:230 include/gmerlin/bggavl.h:467 msgid "PAL DV 4:3 (720 x 576)" msgstr "" #: plugins/videofilters/fv_cropscale.c:231 include/gmerlin/bggavl.h:468 msgid "PAL DV 16:9 (720 x 576)" msgstr "" #: plugins/videofilters/fv_cropscale.c:232 include/gmerlin/bggavl.h:469 msgid "PAL CVD (352 x 576)" msgstr "" #: plugins/videofilters/fv_cropscale.c:233 include/gmerlin/bggavl.h:470 msgid "PAL VCD (352 x 288)" msgstr "" #: plugins/videofilters/fv_cropscale.c:234 include/gmerlin/bggavl.h:471 msgid "PAL SVCD 4:3 (480 x 576)" msgstr "" #: plugins/videofilters/fv_cropscale.c:235 include/gmerlin/bggavl.h:472 msgid "PAL SVCD 16:9 (480 x 576)" msgstr "" #: plugins/videofilters/fv_cropscale.c:236 include/gmerlin/bggavl.h:473 msgid "NTSC DVD D1 4:3 (720 x 480)" msgstr "" #: plugins/videofilters/fv_cropscale.c:237 include/gmerlin/bggavl.h:474 msgid "NTSC DVD D1 16:9 (720 x 480)" msgstr "" #: plugins/videofilters/fv_cropscale.c:238 include/gmerlin/bggavl.h:475 msgid "NTSC DV 4:3 (720 x 480)" msgstr "" #: plugins/videofilters/fv_cropscale.c:239 include/gmerlin/bggavl.h:476 msgid "NTSC DV 16:9 (720 x 480)" msgstr "" #: plugins/videofilters/fv_cropscale.c:240 include/gmerlin/bggavl.h:477 msgid "NTSC CVD (352 x 480)" msgstr "" #: plugins/videofilters/fv_cropscale.c:241 include/gmerlin/bggavl.h:478 msgid "NTSC VCD (352 x 240)" msgstr "" #: plugins/videofilters/fv_cropscale.c:242 include/gmerlin/bggavl.h:479 msgid "NTSC SVCD 4:3 (480 x 480)" msgstr "" #: plugins/videofilters/fv_cropscale.c:243 include/gmerlin/bggavl.h:480 msgid "NTSC SVCD 16:9 (480 x 480)" msgstr "" #: plugins/videofilters/fv_cropscale.c:244 include/gmerlin/bggavl.h:481 msgid "HD 720p/i (1280x720)" msgstr "" #: plugins/videofilters/fv_cropscale.c:245 include/gmerlin/bggavl.h:482 msgid "HD 1080p/i (1920x1080)" msgstr "" #: plugins/videofilters/fv_cropscale.c:246 include/gmerlin/bggavl.h:483 msgid "VGA (640 x 480)" msgstr "" #: plugins/videofilters/fv_cropscale.c:247 include/gmerlin/bggavl.h:484 msgid "QVGA (320 x 240)" msgstr "" #: plugins/videofilters/fv_cropscale.c:248 include/gmerlin/bggavl.h:485 msgid "SQCIF (128 × 96)" msgstr "" #: plugins/videofilters/fv_cropscale.c:249 include/gmerlin/bggavl.h:486 msgid "QCIF (176 × 144)" msgstr "" #: plugins/videofilters/fv_cropscale.c:250 include/gmerlin/bggavl.h:487 msgid "CIF (352 × 288)" msgstr "" #: plugins/videofilters/fv_cropscale.c:251 include/gmerlin/bggavl.h:488 msgid "4CIF (704 × 576)" msgstr "" #: plugins/videofilters/fv_cropscale.c:252 include/gmerlin/bggavl.h:489 msgid "16CIF (1408 × 1152)" msgstr "" #: plugins/videofilters/fv_cropscale.c:255 include/gmerlin/bggavl.h:505 #: include/gmerlin/bggavl.h:524 msgid "" "Set the output image size. For a user defined size, you must specify the " "width and height as well as the pixel width and pixel height." msgstr "" #: plugins/videofilters/fv_cropscale.c:266 include/gmerlin/bggavl.h:397 msgid "" "User defined width in pixels. Only meaningful if you selected \"User defined" "\" for the image size." msgstr "" #: plugins/videofilters/fv_cropscale.c:277 include/gmerlin/bggavl.h:408 msgid "" "User defined height in pixels. Only meaningful if you selected \"User defined" "\" for the image size." msgstr "" #: plugins/videofilters/fv_cropscale.c:281 include/gmerlin/bggavl.h:412 msgid "User defined pixel width" msgstr "" #: plugins/videofilters/fv_cropscale.c:288 include/gmerlin/bggavl.h:419 msgid "" "User defined pixel width. Only meaningful if you selected \"User defined\" " "for the image size." msgstr "" #: plugins/videofilters/fv_cropscale.c:292 include/gmerlin/bggavl.h:423 msgid "User defined pixel height" msgstr "" #: plugins/videofilters/fv_cropscale.c:299 include/gmerlin/bggavl.h:430 msgid "" "User defined pixel height. Only meaningful if you selected \"User defined\" " "for the image size." msgstr "" #: plugins/videofilters/fv_cropscale.c:303 msgid "Image borders" msgstr "" #: plugins/videofilters/fv_cropscale.c:308 msgid "Maintain aspect ratio" msgstr "" #: plugins/videofilters/fv_cropscale.c:313 msgid "" "Let the aspect ratio appear the same as in the source, probably resulting in " "additional borders." msgstr "" #: plugins/videofilters/fv_cropscale.c:322 msgid "Color of the image borders." msgstr "" #: plugins/videofilters/fv_cropscale.c:346 #: plugins/videofilters/fv_cropscale.c:351 plugins/videofilters/fv_zoom.c:106 #: include/gmerlin/bggavl.h:332 lib/x11/x11_window.c:1184 msgid "Scale mode" msgstr "" #: plugins/videofilters/fv_cropscale.c:358 plugins/videofilters/fv_zoom.c:113 #: include/gmerlin/bggavl.h:339 lib/x11/x11_window.c:1205 msgid "" "Choose scaling method. Auto means to choose based on the conversion quality. " "Nearest is fastest, Sinc with Lanczos window is slowest." msgstr "" #: plugins/videofilters/fv_cropscale.c:362 plugins/videofilters/fv_zoom.c:117 #: include/gmerlin/bggavl.h:343 lib/x11/x11_window.c:1209 msgid "Scale order" msgstr "" #: plugins/videofilters/fv_cropscale.c:369 plugins/videofilters/fv_zoom.c:124 #: include/gmerlin/bggavl.h:350 lib/x11/x11_window.c:1214 msgid "Order for sinc scaling" msgstr "" #: plugins/videofilters/fv_cropscale.c:379 plugins/videofilters/fv_zoom.c:135 msgid "Specifies the antialiasing filter to be used when downscaling images." msgstr "" #: plugins/videofilters/fv_cropscale.c:390 plugins/videofilters/fv_zoom.c:146 msgid "" "Specifies how much blurring should be applied when downscaling. Smaller " "values can speed up scaling, but might result in strong aliasing." msgstr "" #: plugins/videofilters/fv_cropscale.c:395 msgid "Chroma output" msgstr "" #: plugins/videofilters/fv_cropscale.c:409 msgid "4:4:4" msgstr "" #: plugins/videofilters/fv_cropscale.c:410 msgid "4:2:2" msgstr "" #: plugins/videofilters/fv_cropscale.c:411 msgid "4:2:0 (MPEG-1)" msgstr "" #: plugins/videofilters/fv_cropscale.c:412 msgid "4:2:0 (MPEG-2)" msgstr "" #: plugins/videofilters/fv_cropscale.c:413 msgid "4:2:0 (DV PAL)" msgstr "" #: plugins/videofilters/fv_cropscale.c:414 msgid "4:1:1" msgstr "" #: plugins/videofilters/fv_cropscale.c:417 msgid "" "Set the output chroma format to that of the destination. This can save one " "chroma scaling operation at a later stage. It only works if the input " "pixelformat is otherwise compatible to the output." msgstr "" #: plugins/videofilters/fv_cropscale.c:421 #: plugins/videofilters/fv_cropscale.c:426 msgid "Deinterlace" msgstr "" #: plugins/videofilters/fv_cropscale.c:431 msgid "Never" msgstr "" #: plugins/videofilters/fv_cropscale.c:431 msgid "Always" msgstr "" #: plugins/videofilters/fv_cropscale.c:441 include/gmerlin/bggavl.h:239 msgid "Drop top field" msgstr "" #: plugins/videofilters/fv_cropscale.c:441 include/gmerlin/bggavl.h:239 msgid "Drop bottom field" msgstr "" #: plugins/videofilters/fv_cropscale.c:442 include/gmerlin/bggavl.h:240 msgid "Specifies which field the deinterlacer should drop." msgstr "" #: plugins/videofilters/fv_cropscale.c:1288 msgid "Crop & Scale" msgstr "" #: plugins/videofilters/fv_cropscale.c:1289 msgid "" "Crop and scale video images. Has lots of standard video formats as presets. " "Can also do chroma placement correction and simple deinterlacing" msgstr "" #: plugins/videofilters/fv_pixelformat.c:70 include/gmerlin/bggavl.h:254 #: apps/camelot/vloopback.c:787 msgid "Pixelformat" msgstr "" #: plugins/videofilters/fv_pixelformat.c:200 msgid "Force pixelformat" msgstr "" #: plugins/videofilters/fv_pixelformat.c:201 msgid "" "Forces a pixelformat as input for the next filter. Its mainly used for " "testing." msgstr "" #: plugins/videofilters/fv_tcdisplay.c:86 plugins/videofilters/fv_tctweak.c:88 msgid "Interpolate missing" msgstr "" #: plugins/videofilters/fv_tcdisplay.c:90 msgid "Interpolate missing timecodes" msgstr "" #: plugins/videofilters/fv_tcdisplay.c:347 msgid "Display timecodes" msgstr "" #: plugins/videofilters/fv_tcdisplay.c:348 msgid "Burn timecodes into video frames" msgstr "" #: plugins/videofilters/fv_zoom.c:85 msgid "Zoom horizontally" msgstr "" #: plugins/videofilters/fv_zoom.c:95 msgid "Zoom vertically" msgstr "" #: plugins/videofilters/fv_zoom.c:151 plugins/videofilters/fv_tlp.c:91 #: plugins/jpeg/iw_jpeg.c:265 msgid "Quality" msgstr "" #: plugins/videofilters/fv_zoom.c:379 msgid "Zoom horizontally and/or vertically" msgstr "" #: plugins/videofilters/fv_tlp.c:80 plugins/videofilters/fv_oldcolor.c:151 msgid "Strength" msgstr "" #: plugins/videofilters/fv_tlp.c:87 msgid "0 means no effect, 1 means maximum (= still image)" msgstr "" #: plugins/videofilters/fv_tlp.c:208 msgid "Temporal lowpass" msgstr "" #: plugins/videofilters/fv_tlp.c:209 msgid "Simple temporal lowpass" msgstr "" #: plugins/videofilters/fv_tctweak.c:78 plugins/videofilters/fv_blur.c:229 #: apps/camelot/vloopback.c:736 msgid "Mode" msgstr "" #: plugins/videofilters/fv_tctweak.c:89 msgid "Remove redundant" msgstr "" #: plugins/videofilters/fv_tctweak.c:90 msgid "Remove all" msgstr "" #: plugins/videofilters/fv_tctweak.c:91 msgid "Add new" msgstr "" #: plugins/videofilters/fv_tctweak.c:92 msgid "Add new (first only)" msgstr "" #: plugins/videofilters/fv_tctweak.c:103 msgid "Set the integer framerate used when adding new timecodes" msgstr "" #: plugins/videofilters/fv_tctweak.c:109 msgid "Set the if drop frame is used when adding new timecodes" msgstr "" #: plugins/videofilters/fv_tctweak.c:118 msgid "Set the start hours used when adding new timecodes" msgstr "" #: plugins/videofilters/fv_tctweak.c:127 msgid "Set the start minutes used when adding new timecodes" msgstr "" #: plugins/videofilters/fv_tctweak.c:136 msgid "Set the start seconds used when adding new timecodes" msgstr "" #: plugins/videofilters/fv_tctweak.c:145 msgid "Set the start frames used when adding new timecodes" msgstr "" #: plugins/videofilters/fv_tctweak.c:345 msgid "Tweak timecodes" msgstr "" #: plugins/videofilters/fv_tctweak.c:346 msgid "Replace/remove/interpolate timecodes" msgstr "" #: plugins/videofilters/fv_interlace.c:86 msgid "Output field order" msgstr "" #: plugins/videofilters/fv_interlace.c:90 msgid "Top first" msgstr "" #: plugins/videofilters/fv_interlace.c:91 msgid "Bottom first" msgstr "" #: plugins/videofilters/fv_interlace.c:246 msgid "Interlace" msgstr "" #: plugins/videofilters/fv_interlace.c:247 msgid "Interlace video images. Output has half the input framerate." msgstr "" #: plugins/videofilters/fv_colorbalance.c:164 #: plugins/videofilters/fv_oldcolor.c:161 msgid "Red gain" msgstr "" #: plugins/videofilters/fv_colorbalance.c:174 #: plugins/videofilters/fv_oldcolor.c:171 msgid "Green gain" msgstr "" #: plugins/videofilters/fv_colorbalance.c:184 #: plugins/videofilters/fv_oldcolor.c:181 msgid "Blue gain" msgstr "" #: plugins/videofilters/fv_colorbalance.c:194 msgid "Normalize" msgstr "" #: plugins/videofilters/fv_colorbalance.c:197 msgid "Normalize for constant luminance." msgstr "" #: plugins/videofilters/fv_colorbalance.c:639 msgid "Colorbalance" msgstr "" #: plugins/videofilters/fv_colorbalance.c:640 msgid "" "Apply gain for red, green and blue. RGB formats are processed directly, " "Y'CbCr formats are processed by the colormatrix." msgstr "" #: plugins/videofilters/fv_flip.c:70 msgid "Flip horizontally" msgstr "" #: plugins/videofilters/fv_flip.c:76 msgid "Flip vertically" msgstr "" #: plugins/videofilters/fv_flip.c:180 msgid "Flip image" msgstr "" #: plugins/videofilters/fv_flip.c:181 msgid "Flip video images horizontally and/or vertically" msgstr "" #: plugins/videofilters/fv_framerate.c:162 msgid "Force framerate" msgstr "" #: plugins/videofilters/fv_framerate.c:163 msgid "" "Forces a framerate as input for the next filter. Its mainly used for testing." msgstr "" #: plugins/videofilters/fv_oldcolor.c:128 msgid "Style" msgstr "" #: plugins/videofilters/fv_oldcolor.c:347 msgid "Old color" msgstr "" #: plugins/videofilters/fv_oldcolor.c:348 msgid "Simulate old color- and B/W movies" msgstr "" #: plugins/videofilters/fv_colormatrix_rgb.c:94 msgid "Red" msgstr "" #: plugins/videofilters/fv_colormatrix_rgb.c:100 msgid "Red -> Red" msgstr "" #: plugins/videofilters/fv_colormatrix_rgb.c:110 msgid "Green -> Red" msgstr "" #: plugins/videofilters/fv_colormatrix_rgb.c:120 msgid "Blue -> Red" msgstr "" #: plugins/videofilters/fv_colormatrix_rgb.c:130 msgid "Alpha -> Red" msgstr "" #: plugins/videofilters/fv_colormatrix_rgb.c:140 msgid "Red offset" msgstr "" #: plugins/videofilters/fv_colormatrix_rgb.c:152 msgid "Green" msgstr "" #: plugins/videofilters/fv_colormatrix_rgb.c:158 msgid "Red -> Green" msgstr "" #: plugins/videofilters/fv_colormatrix_rgb.c:168 msgid "Green -> Green" msgstr "" #: plugins/videofilters/fv_colormatrix_rgb.c:178 msgid "Blue -> Green" msgstr "" #: plugins/videofilters/fv_colormatrix_rgb.c:188 msgid "Alpha -> Green" msgstr "" #: plugins/videofilters/fv_colormatrix_rgb.c:198 msgid "Green offset" msgstr "" #: plugins/videofilters/fv_colormatrix_rgb.c:210 msgid "Blue" msgstr "" #: plugins/videofilters/fv_colormatrix_rgb.c:216 msgid "Red -> Blue" msgstr "" #: plugins/videofilters/fv_colormatrix_rgb.c:226 msgid "Green -> Blue" msgstr "" #: plugins/videofilters/fv_colormatrix_rgb.c:236 msgid "Blue -> Blue" msgstr "" #: plugins/videofilters/fv_colormatrix_rgb.c:246 msgid "Alpha -> Blue" msgstr "" #: plugins/videofilters/fv_colormatrix_rgb.c:256 msgid "Blue offset" msgstr "" #: plugins/videofilters/fv_colormatrix_rgb.c:274 msgid "Red -> Alpha" msgstr "" #: plugins/videofilters/fv_colormatrix_rgb.c:284 msgid "Green -> Alpha" msgstr "" #: plugins/videofilters/fv_colormatrix_rgb.c:294 msgid "Blue -> Alpha" msgstr "" #: plugins/videofilters/fv_colormatrix_rgb.c:454 msgid "RGB Colormatrix" msgstr "" #: plugins/videofilters/fv_colormatrix_rgb.c:455 msgid "" "Generic colormatrix (RGBA). You pass the coefficients in RGB(A) coordinates, " "but the processing will work in Y'CbCr(A) as well." msgstr "" #: plugins/videofilters/fv_decimate.c:147 msgid "Block threshold" msgstr "" #: plugins/videofilters/fv_decimate.c:153 msgid "" "Specifies how much a block may differ from the last non-skipped block. 0 " "means identical blocks, 1 means completely different blocks. Note that the " "meaning of \"completely different\" depends on the colorspace." msgstr "" #: plugins/videofilters/fv_decimate.c:157 msgid "Total threshold" msgstr "" #: plugins/videofilters/fv_decimate.c:163 msgid "" "Specifies how much a frame may differ from the last non-skipped frame. 0 " "means identical frames, 1 means completely different frames. Note that the " "meaning of \"completely different\" depends on the colorspace." msgstr "" #: plugins/videofilters/fv_decimate.c:167 msgid "Maximum skipped frames" msgstr "" #: plugins/videofilters/fv_decimate.c:173 msgid "Maximum number of consecutive skipped frames" msgstr "" #: plugins/videofilters/fv_decimate.c:177 msgid "Report results" msgstr "" #: plugins/videofilters/fv_decimate.c:180 msgid "Log reports about skipped frames" msgstr "" #: plugins/videofilters/fv_decimate.c:477 #, c-format msgid "Skipped %d frames" msgstr "" #: plugins/videofilters/fv_decimate.c:487 msgid "Decimate" msgstr "" #: plugins/videofilters/fv_decimate.c:488 msgid "Skip almost identical frames" msgstr "" #: plugins/videofilters/fv_blur.c:235 msgid "Gauss" msgstr "" #: plugins/videofilters/fv_blur.c:236 include/gmerlin/bggavl.h:658 msgid "Triangular" msgstr "" #: plugins/videofilters/fv_blur.c:237 include/gmerlin/bggavl.h:657 msgid "Rectangular" msgstr "" #: plugins/videofilters/fv_blur.c:242 msgid "Horizontal radius" msgstr "" #: plugins/videofilters/fv_blur.c:252 msgid "Vertical radius" msgstr "" #: plugins/videofilters/fv_blur.c:407 msgid "Blur" msgstr "" #: plugins/videofilters/fv_blur.c:408 msgid "Blur filter based on gavl. Supports triangular, box and gauss blur." msgstr "" #: plugins/videofilters/fv_invert_rgb.c:103 msgid "Invert red" msgstr "" #: plugins/videofilters/fv_invert_rgb.c:110 msgid "Invert green" msgstr "" #: plugins/videofilters/fv_invert_rgb.c:117 msgid "Invert blue" msgstr "" #: plugins/videofilters/fv_invert_rgb.c:124 msgid "Invert alpha" msgstr "" #: plugins/videofilters/fv_invert_rgb.c:563 msgid "Invert RGBA" msgstr "" #: plugins/videofilters/fv_invert_rgb.c:564 msgid "" "Invert single color channels. RGB(A) formats are processed directly, Y'CbCr" "(A) formats are processed with the colormatrix." msgstr "" #: plugins/videofilters/fv_bitshift.c:67 msgid "Bits to shift" msgstr "" #: plugins/videofilters/fv_bitshift.c:184 msgid "Shift image" msgstr "" #: plugins/videofilters/fv_bitshift.c:185 msgid "Upshift 16 bit images, where only some lower bits are used" msgstr "" #: plugins/videofilters/fv_equalizer.c:446 msgid "Saturation" msgstr "" #: plugins/videofilters/fv_equalizer.c:758 msgid "Equalizer" msgstr "" #: plugins/videofilters/fv_equalizer.c:759 msgid "" "Control hue, saturation, contrast and brightness. For Y'CbCr, it uses " "routines based on the vf_eq and vf_hue filters from the MPlayer project. For " "RGB formats, it uses the colormatrix." msgstr "" #: plugins/gavl/ir_gavl.c:124 msgid "GAVL image reader" msgstr "" #: plugins/gavl/ir_gavl.c:125 msgid "Reader for GAVL images" msgstr "" #: plugins/gavl/iw_gavl.c:115 msgid "gavl image writer" msgstr "" #: plugins/gavl/iw_gavl.c:116 msgid "Writer for GAVL images" msgstr "" #: plugins/mikmod/i_mikmod.c:125 msgid "Cannot find mikmod executable" msgstr "" #: plugins/mikmod/i_mikmod.c:204 msgid "Unrecognized fileformat" msgstr "" #: plugins/mikmod/i_mikmod.c:254 lib/gtk/infowindow.c:711 #: lib/gtk/infowindow.c:730 lib/gtk/infowindow.c:749 msgid "Output format" msgstr "" #: plugins/mikmod/i_mikmod.c:257 msgid "Mono 8bit" msgstr "" #: plugins/mikmod/i_mikmod.c:257 msgid "Stereo 8bit" msgstr "" #: plugins/mikmod/i_mikmod.c:257 msgid "Mono 16bit" msgstr "" #: plugins/mikmod/i_mikmod.c:257 msgid "Stereo 16bit" msgstr "" #: plugins/mikmod/i_mikmod.c:263 include/gmerlin/bggavl.h:531 #: include/gmerlin/bggavl.h:537 msgid "Samplerate" msgstr "" #: plugins/mikmod/i_mikmod.c:272 msgid "Look for hidden patterns in module" msgstr "" #: plugins/mikmod/i_mikmod.c:278 msgid "Use surround mixing" msgstr "" #: plugins/mikmod/i_mikmod.c:284 msgid "Force volume fade at the end of module" msgstr "" #: plugins/mikmod/i_mikmod.c:290 msgid "Use interpolate mixing" msgstr "" #: plugins/mikmod/i_mikmod.c:345 msgid "mikmod input plugin" msgstr "" #: plugins/mikmod/i_mikmod.c:346 msgid "Simple wrapper, which calls the mikmod program" msgstr "" #: plugins/cdaudio/cdparanoia.c:187 msgid "Cdparanoia" msgstr "" #: plugins/cdaudio/cdparanoia.c:204 msgid "Maximum retries" msgstr "" #: plugins/cdaudio/cdparanoia.c:209 msgid "Maximum number of retries, 0 = infinite" msgstr "" #: plugins/cdaudio/cdparanoia.c:213 msgid "Disable paranoia" msgstr "" #: plugins/cdaudio/cdparanoia.c:216 msgid "Disable all data verification and correction features." msgstr "" #: plugins/cdaudio/cdparanoia.c:220 msgid "Disable extra paranoia" msgstr "" #: plugins/cdaudio/cdparanoia.c:223 msgid "" "Disables intra-read data verification; only overlap checking atread " "boundaries is performed. It can wedge if errors occur in the attempted " "overlap area. Not recommended." msgstr "" #: plugins/cdaudio/cdaudio.c:168 #, c-format msgid "cdio_close_tray failed: %s" msgstr "" #: plugins/cdaudio/cdaudio.c:171 msgid "cdio_close_tray failed" msgstr "" #: plugins/cdaudio/cdaudio.c:250 #, c-format msgid "DVD Writer (%s)" msgstr "" #: plugins/cdaudio/cdaudio.c:254 #, c-format msgid "CD Writer (%s)" msgstr "" #: plugins/cdaudio/cdaudio.c:258 #, c-format msgid "DVD Drive (%s)" msgstr "" #: plugins/cdaudio/cdaudio.c:260 #, c-format msgid "CD-ROM Drive (%s)" msgstr "" #: plugins/cdaudio/i_cdaudio.c:243 msgid "Got metadata from CD-Text" msgstr "" #: plugins/cdaudio/i_cdaudio.c:260 #, c-format msgid "Got metadata from gmerlin cache (%s)" msgstr "" #: plugins/cdaudio/i_cdaudio.c:276 #, c-format msgid "Got metadata from musicbrainz (%s)" msgstr "" #: plugins/cdaudio/i_cdaudio.c:295 #, c-format msgid "Got metadata from CDDB (%s)" msgstr "" #: plugins/cdaudio/i_cdaudio.c:321 #, c-format msgid "Audio CD track %02d" msgstr "" #: plugins/cdaudio/i_cdaudio.c:546 msgid "Trackname template" msgstr "" #: plugins/cdaudio/i_cdaudio.c:549 msgid "" "Template for track name generation from metadata\n" "%p: Artist\n" "%a: Album\n" "%g: Genre\n" "%t: Track name\n" "%n: Track number (d = number of digits, 1-9)\n" "%y: Year\n" "%c: Comment" msgstr "" #: plugins/cdaudio/i_cdaudio.c:560 msgid "Use CD-Text" msgstr "" #: plugins/cdaudio/i_cdaudio.c:563 msgid "Try to get CD metadata from CD-Text" msgstr "" #: plugins/cdaudio/i_cdaudio.c:567 msgid "Use locally saved metadata" msgstr "" #: plugins/cdaudio/i_cdaudio.c:570 msgid "" "Whenever we obtain CD metadata from the internet, we save them into $HOME/." "gmerlin/cdaudio_metadata. If you got wrong metadata for a CD, disabling this " "option will retrieve the metadata again and overwrite the saved data." msgstr "" #: plugins/cdaudio/i_cdaudio.c:577 msgid "Musicbrainz" msgstr "" #: plugins/cdaudio/i_cdaudio.c:582 msgid "Use Musicbrainz" msgstr "" #: plugins/cdaudio/i_cdaudio.c:594 plugins/cdaudio/i_cdaudio.c:636 #: lib/lcdproc.c:118 msgid "Port" msgstr "" #: plugins/cdaudio/i_cdaudio.c:602 plugins/cdaudio/i_cdaudio.c:650 msgid "Proxy" msgstr "" #: plugins/cdaudio/i_cdaudio.c:604 plugins/cdaudio/i_cdaudio.c:652 msgid "Proxy server (leave empty for direct connection)" msgstr "" #: plugins/cdaudio/i_cdaudio.c:608 plugins/cdaudio/i_cdaudio.c:613 #: plugins/cdaudio/i_cdaudio.c:656 plugins/cdaudio/i_cdaudio.c:661 msgid "Proxy port" msgstr "" #: plugins/cdaudio/i_cdaudio.c:619 msgid "Cddb" msgstr "" #: plugins/cdaudio/i_cdaudio.c:624 msgid "Use Cddb" msgstr "" #: plugins/cdaudio/i_cdaudio.c:644 msgid "Path" msgstr "" #: plugins/cdaudio/i_cdaudio.c:665 msgid "Proxy username" msgstr "" #: plugins/cdaudio/i_cdaudio.c:667 msgid "" "User name for proxy (leave empty for poxies, which don't require " "authentication)" msgstr "" #: plugins/cdaudio/i_cdaudio.c:671 msgid "Proxy password" msgstr "" #: plugins/cdaudio/i_cdaudio.c:673 msgid "Password for proxy" msgstr "" #: plugins/cdaudio/i_cdaudio.c:677 msgid "Timeout" msgstr "" #: plugins/cdaudio/i_cdaudio.c:682 msgid "Timeout (in seconds) for connections to the CDDB server" msgstr "" #: plugins/cdaudio/i_cdaudio.c:766 #, c-format msgid "Ejecting disk failed: %s" msgstr "" #: plugins/cdaudio/i_cdaudio.c:768 msgid "Ejecting disk failed" msgstr "" #: plugins/cdaudio/i_cdaudio.c:792 msgid "Audio CD player/ripper" msgstr "" #: plugins/cdaudio/i_cdaudio.c:793 msgid "" "Plugin for audio CDs. Supports both playing with direct connection from the " "CD-drive to the souncard and ripping with cdparanoia. Metadata are obtained " "from Musicbrainz, freedb or CD-text. Metadata are cached in $HOME/.gmerlin/" "cdaudio_metadata." msgstr "" #: plugins/png/e_spumux.c:224 plugins/png/iw_png.c:96 msgid "Compression level" msgstr "" #: plugins/png/e_spumux.c:246 msgid "spumux overlay exporter" msgstr "" #: plugins/png/e_spumux.c:247 msgid "" "Exports overlay subtitles into the format used by spumux (http://dvdauthor." "sourceforge.net)" msgstr "" #: plugins/png/ir_png.c:311 msgid "PNG reader" msgstr "" #: plugins/png/ir_png.c:312 msgid "Reader for PNG images" msgstr "" #: plugins/png/iw_png.c:104 msgid "Bits per channel" msgstr "" #: plugins/png/iw_png.c:108 msgid "" "If you select auto, the depth will be chosen according to the input format" msgstr "" #: plugins/png/iw_png.c:131 msgid "PNG writer" msgstr "" #: plugins/png/iw_png.c:132 msgid "Writer for PNG images" msgstr "" #: plugins/v4l2/i_v4l2.c:108 plugins/v4l2/i_v4l2.c:153 msgid "Out of memory" msgstr "" #: plugins/v4l2/i_v4l2.c:131 plugins/v4l2/ov_v4l2.c:254 #, c-format msgid "%s does not support memory mapping" msgstr "" #: plugins/v4l2/i_v4l2.c:137 plugins/v4l2/ov_v4l2.c:260 #, c-format msgid "VIDIOC_REQBUFS failed: %s" msgstr "" #: plugins/v4l2/i_v4l2.c:144 plugins/v4l2/ov_v4l2.c:267 #, c-format msgid "Insufficient buffer memory on %s" msgstr "" #: plugins/v4l2/i_v4l2.c:169 plugins/v4l2/ov_v4l2.c:284 #, c-format msgid "VIDIOC_QUERYBUF failed: %s" msgstr "" #: plugins/v4l2/i_v4l2.c:195 plugins/v4l2/i_v4l2.c:617 #: plugins/v4l2/ov_v4l2.c:359 #, c-format msgid "VIDIOC_QBUF failed: %s" msgstr "" #: plugins/v4l2/i_v4l2.c:206 plugins/v4l2/ov_v4l2.c:372 #, c-format msgid "VIDIOC_STREAMON failed: %s" msgstr "" #: plugins/v4l2/i_v4l2.c:229 plugins/v4l2/ov_v4l2.c:192 #, c-format msgid "VIDIOC_ENUM_FMT failed: %s" msgstr "" #: plugins/v4l2/i_v4l2.c:261 plugins/v4l2/i_v4l2.c:370 #: plugins/v4l2/i_v4l2.c:400 #, c-format msgid "VIDIOC_G_FMT failed: %s" msgstr "" #: plugins/v4l2/i_v4l2.c:301 plugins/v4l2/ov_v4l2.c:453 #, c-format msgid "Device name: %s" msgstr "" #: plugins/v4l2/i_v4l2.c:305 plugins/v4l2/ov_v4l2.c:458 msgid "Trying mmap i/o" msgstr "" #: plugins/v4l2/i_v4l2.c:310 msgid "Trying read i/o" msgstr "" #: plugins/v4l2/i_v4l2.c:348 msgid "Trying v4lconvert" msgstr "" #: plugins/v4l2/i_v4l2.c:356 msgid "Got no supported pixelformat" msgstr "" #: plugins/v4l2/i_v4l2.c:383 plugins/v4l2/ov_v4l2.c:485 #, c-format msgid "VIDIOC_S_FMT failed: %s" msgstr "" #: plugins/v4l2/i_v4l2.c:457 plugins/v4l2/ov_v4l2.c:322 #, c-format msgid "VIDIOC_STREAMOFF failed: %s" msgstr "" #: plugins/v4l2/i_v4l2.c:537 plugins/v4l2/i_v4l2.c:549 #, c-format msgid "read failed: %s" msgstr "" #: plugins/v4l2/i_v4l2.c:579 plugins/v4l2/ov_v4l2.c:539 #, c-format msgid "VIDIOC_DQBUF failed: %s" msgstr "" #: plugins/v4l2/i_v4l2.c:651 #, c-format msgid "Select failed: %s" msgstr "" #: plugins/v4l2/i_v4l2.c:657 msgid "Select timeout" msgstr "" #: plugins/v4l2/i_v4l2.c:716 plugins/v4l2/ov_v4l2.c:105 msgid "V4L2 Device" msgstr "" #: plugins/v4l2/i_v4l2.c:722 msgid "Force read" msgstr "" #: plugins/v4l2/i_v4l2.c:725 plugins/v4l2/ov_v4l2.c:114 msgid "Don't use memory mapping" msgstr "" #: plugins/v4l2/i_v4l2.c:892 plugins/v4l2/ov_v4l2.c:613 msgid "V4L2" msgstr "" #: plugins/v4l2/i_v4l2.c:893 msgid "" "video4linux 2 recording plugin. Supports only video and no tuner decives." msgstr "" #: plugins/v4l2/convert.c:84 msgid "Initializing libv4lconvert failed" msgstr "" #: plugins/v4l2/convert.c:94 msgid "Initializing libv4lconvert failed (resolution not directly supported)" msgstr "" #: plugins/v4l2/ov_v4l2.c:111 msgid "Force write" msgstr "" #: plugins/v4l2/ov_v4l2.c:341 #, c-format msgid "write failed: %s" msgstr "" #: plugins/v4l2/ov_v4l2.c:431 msgid "Forcing square pixels" msgstr "" #: plugins/v4l2/ov_v4l2.c:463 msgid "Trying write i/o" msgstr "" #: plugins/v4l2/ov_v4l2.c:475 #, c-format msgid "Using %s" msgstr "" #: plugins/v4l2/ov_v4l2.c:614 msgid "V4L2 output driver" msgstr "" #: plugins/v4l2/v4l2_common.c:378 msgid "VIDIOC_S_CTRL Failed" msgstr "" #: plugins/v4l2/v4l2_common.c:414 msgid "VIDIOC_G_CTRL Failed" msgstr "" #: plugins/v4l2/v4l2_common.c:431 apps/camelot/vloopback.c:494 #, c-format msgid "Opening %s failed: %s" msgstr "" #: plugins/v4l2/v4l2_common.c:440 #, c-format msgid "%s is no V4L2 device" msgstr "" #: plugins/v4l2/v4l2_common.c:446 #, c-format msgid "VIDIOC_QUERYCAP failed: %s" msgstr "" #: plugins/v4l2/v4l2_common.c:454 #, c-format msgid "%s is no video %s device" msgstr "" #: plugins/lqt/i_lqt.c:46 apps/plugincfg/gmerlin_plugincfg.c:281 #: apps/transcoder/trackdialog.c:217 apps/recorder/recorder_window.c:722 #: lib/pluginregistry.c:2125 lib/pluginregistry.c:2609 lib/player_audio.c:181 #: lib/gtk/infowindow.c:697 msgid "Audio" msgstr "" #: plugins/lqt/i_lqt.c:52 msgid "Audio Codecs" msgstr "" #: plugins/lqt/i_lqt.c:53 msgid "Sort and configure audio codecs" msgstr "" #: plugins/lqt/i_lqt.c:57 apps/transcoder/trackdialog.c:288 #: apps/recorder/recorder_window.c:740 lib/player_video.c:134 #: lib/pluginregistry.c:2136 lib/pluginregistry.c:2616 #: lib/gtk/infowindow.c:716 msgid "Video" msgstr "" #: plugins/lqt/i_lqt.c:63 msgid "Video Codecs" msgstr "" #: plugins/lqt/i_lqt.c:64 msgid "Sort and configure video codecs" msgstr "" #: plugins/lqt/i_lqt.c:281 msgid "More than one chapter track found, using first one" msgstr "" #: plugins/lqt/i_lqt.c:572 msgid "libquicktime input plugin" msgstr "" #: plugins/lqt/i_lqt.c:573 msgid "Input plugin based on libquicktime" msgstr "" #: plugins/lqt/lqt_common.c:94 #, c-format msgid "%s Compatible with" msgstr "" #: plugins/lqt/e_lqt.c:41 msgid "Codec" msgstr "" #: plugins/lqt/e_lqt.c:183 #, c-format msgid "Cannot open file %s" msgstr "" #: plugins/lqt/e_lqt.c:478 #, c-format msgid "Audio codec %s cannot be written to AVI files" msgstr "" #: plugins/lqt/e_lqt.c:542 msgid "AVI subtitles not supported" msgstr "" #: plugins/lqt/e_lqt.c:590 #, c-format msgid "Omitting chapter %d: time (%f) > duration (%f)" msgstr "" #: plugins/lqt/e_lqt.c:629 msgid "Making streamable...." msgstr "" #: plugins/lqt/e_lqt.c:631 msgid "Making streamable....done" msgstr "" #: plugins/lqt/e_lqt.c:706 msgid "Quicktime" msgstr "" #: plugins/lqt/e_lqt.c:706 msgid "AVI" msgstr "" #: plugins/lqt/e_lqt.c:706 msgid "AVI (Opendml)" msgstr "" #: plugins/lqt/e_lqt.c:707 msgid "MP4" msgstr "" #: plugins/lqt/e_lqt.c:707 msgid "M4A" msgstr "" #: plugins/lqt/e_lqt.c:707 msgid "3GP" msgstr "" #: plugins/lqt/e_lqt.c:712 msgid "Make streamable" msgstr "" #: plugins/lqt/e_lqt.c:714 msgid "Make the file streamable afterwards (uses twice the diskspace)" msgstr "" #: plugins/lqt/e_lqt.c:718 msgid "Maximum RIFF size" msgstr "" #: plugins/lqt/e_lqt.c:723 msgid "" "Maximum RIFF size (in MB) for OpenDML AVIs. The default (1GB) is reasonable " "and should only be changed by people who know what they do." msgstr "" #: plugins/lqt/e_lqt.c:914 msgid "Text box (top)" msgstr "" #: plugins/lqt/e_lqt.c:921 msgid "Text box (left)" msgstr "" #: plugins/lqt/e_lqt.c:928 msgid "Text box (bottom)" msgstr "" #: plugins/lqt/e_lqt.c:935 msgid "Text box (right)" msgstr "" #: plugins/lqt/e_lqt.c:999 msgid "Quicktime encoder" msgstr "" #: plugins/lqt/e_lqt.c:1000 msgid "" "Encoder based on libquicktime (http://libquicktime.sourceforge.net) Writes " "Quicktime, AVI (optionally ODML), MP4, M4A and 3GPP. Supported codecs range " "from high quality uncompressed formats for professional applications to " "consumer level formats like H.264/AVC, AAC, MP3, Divx compatible etc. Also " "supported are chapters and text subtitles" msgstr "" #: plugins/tiff/iw_tiff.c:101 apps/cmdlineplayer/gmerlin_play.c:543 #: apps/thumbnailer/gmerlin-video-thumbnailer.c:192 #: tests/gmerlin_visualize.c:478 #, c-format msgid "Cannot open %s" msgstr "" #: plugins/tiff/iw_tiff.c:191 msgid "Packbits" msgstr "" #: plugins/tiff/iw_tiff.c:191 msgid "Deflate" msgstr "" #: plugins/tiff/iw_tiff.c:191 msgid "JPEG" msgstr "" #: plugins/tiff/iw_tiff.c:198 msgid "JPEG quality" msgstr "" #: plugins/tiff/iw_tiff.c:206 msgid "Deflate compression level" msgstr "" #: plugins/tiff/iw_tiff.c:253 msgid "TIFF writer" msgstr "" #: plugins/tiff/iw_tiff.c:254 msgid "Writer for TIFF images" msgstr "" #: plugins/tiff/ir_tiff.c:106 msgid "Seeked beyond buffer." msgstr "" #: plugins/tiff/ir_tiff.c:616 msgid "Unsupported compression for LOGL/LOGLUV" msgstr "" #: plugins/tiff/ir_tiff.c:660 plugins/tiff/ir_tiff.c:690 #: plugins/tiff/ir_tiff.c:722 msgid "Unsupported samples per pixel" msgstr "" #: plugins/tiff/ir_tiff.c:696 #, c-format msgid "Unsupported bits per sample (%d) for UINT" msgstr "" #: plugins/tiff/ir_tiff.c:703 msgid "Didn't get max sample value" msgstr "" #: plugins/tiff/ir_tiff.c:706 msgid "Didn't get min sample value" msgstr "" #: plugins/tiff/ir_tiff.c:728 #, c-format msgid "Unsupported depth %d for IEEE float" msgstr "" #: plugins/tiff/ir_tiff.c:738 msgid "Unsupported sampleformat" msgstr "" #: plugins/tiff/ir_tiff.c:743 #, c-format msgid "Unknown sampleformat %d" msgstr "" #: plugins/tiff/ir_tiff.c:869 msgid "BUG!!! convert_func == 0x0" msgstr "" #: plugins/tiff/ir_tiff.c:905 msgid "TIFF reader" msgstr "" #: plugins/tiff/ir_tiff.c:906 msgid "Reader for TIFF images" msgstr "" #: plugins/jpeg/iw_jpeg.c:186 #, c-format msgid "Illegal pixelformat: %s" msgstr "" #: plugins/jpeg/iw_jpeg.c:273 msgid "Chroma sampling" msgstr "" #: plugins/jpeg/iw_jpeg.c:325 msgid "JPEG writer" msgstr "" #: plugins/jpeg/iw_jpeg.c:326 msgid "Writer for JPEG images" msgstr "" #: plugins/jpeg/ir_jpeg.c:274 msgid "Illegal pixelformat" msgstr "" #: plugins/jpeg/ir_jpeg.c:295 msgid "JPEG reader" msgstr "" #: plugins/jpeg/ir_jpeg.c:296 msgid "Reader for JPEG images" msgstr "" #: plugins/wavwrite/e_wav.c:317 msgid "Bits per sample" msgstr "" #: plugins/wavwrite/e_wav.c:329 msgid "Write info chunk" msgstr "" #: plugins/wavwrite/e_wav.c:472 #, c-format msgid "Cannot open output file: %s" msgstr "" #: plugins/wavwrite/e_wav.c:643 msgid "Wave writer" msgstr "" #: plugins/wavwrite/e_wav.c:644 msgid "Simple writer for wave files, supports 8, 16, 24 and 32 bit PCM" msgstr "" #: plugins/edl/i_edl.c:89 msgid "Parser for gmerlin EDLs" msgstr "" #: plugins/edl/i_edl.c:90 msgid "" "This parses the XML file and exports an EDL, which can be played with the " "builtin EDL decoder." msgstr "" #: include/gmerlin/bggavl.h:128 msgid "Conversion Quality" msgstr "" #: include/gmerlin/bggavl.h:135 msgid "" "Set the conversion quality for format conversions. Lower quality means more " "speed. Values above 3 enable slow high quality calculations." msgstr "" #: include/gmerlin/bggavl.h:142 lib/singlepic.c:76 msgid "Timescale" msgstr "" #: include/gmerlin/bggavl.h:147 msgid "" "Timescale for user defined output framerate (Framerate = timescale / frame " "duration)." msgstr "" #: include/gmerlin/bggavl.h:151 lib/singlepic.c:84 msgid "Frame duration" msgstr "" #: include/gmerlin/bggavl.h:156 msgid "" "Frame duration for user defined output framerate (Framerate = timescale / " "frame duration)." msgstr "" #: include/gmerlin/bggavl.h:172 msgid "23.976 (NTSC encapsulated film rate)" msgstr "" #: include/gmerlin/bggavl.h:173 msgid "24 (Standard international cinema film rate)" msgstr "" #: include/gmerlin/bggavl.h:174 msgid "25 (PAL [625/50] video frame rate)" msgstr "" #: include/gmerlin/bggavl.h:175 msgid "29.970 (NTSC video frame rate)" msgstr "" #: include/gmerlin/bggavl.h:176 msgid "30 (NTSC drop-frame [525/60] video frame rate)" msgstr "" #: include/gmerlin/bggavl.h:177 msgid "50 (Double frame rate / progressive PAL)" msgstr "" #: include/gmerlin/bggavl.h:178 msgid "59.940 (Double frame rate NTSC)" msgstr "" #: include/gmerlin/bggavl.h:179 msgid "60 (Double frame rate drop-frame NTSC)" msgstr "" #: include/gmerlin/bggavl.h:196 include/gmerlin/bggavl.h:214 msgid "" "Output framerate. For user defined framerate, enter the timescale and frame " "duration below (framerate = timescale / frame duration)." msgstr "" #: include/gmerlin/bggavl.h:224 msgid "Deinterlace mode" msgstr "" #: include/gmerlin/bggavl.h:229 include/gmerlin/bggavl.h:589 #: apps/transcoder/tracklist.c:1269 lib/gtk/albumwidget.c:1508 #: lib/gtk/albumwidget.c:2906 msgid "Copy" msgstr "" #: include/gmerlin/bggavl.h:229 msgid "Scale" msgstr "" #: include/gmerlin/bggavl.h:248 msgid "" "Force deinterlacing if you want progressive output and the input format " "pretends to be progressive also." msgstr "" #: include/gmerlin/bggavl.h:267 msgid "Y'CbCr 8 bit" msgstr "" #: include/gmerlin/bggavl.h:267 msgid "Y'CbCrA 8 bit" msgstr "" #: include/gmerlin/bggavl.h:268 msgid "Y'CbCr 16 bit" msgstr "" #: include/gmerlin/bggavl.h:268 msgid "Y'CbCrA 16 bit" msgstr "" #: include/gmerlin/bggavl.h:269 msgid "Y'CbCr float" msgstr "" #: include/gmerlin/bggavl.h:269 msgid "Y'CbCrA float" msgstr "" #: include/gmerlin/bggavl.h:270 msgid "RGB 8 bit" msgstr "" #: include/gmerlin/bggavl.h:270 msgid "RGBA 8 bit" msgstr "" #: include/gmerlin/bggavl.h:271 msgid "RGB 16 bit" msgstr "" #: include/gmerlin/bggavl.h:271 msgid "RGBA 16 bit" msgstr "" #: include/gmerlin/bggavl.h:272 msgid "RGB float" msgstr "" #: include/gmerlin/bggavl.h:272 msgid "RGBA float" msgstr "" #: include/gmerlin/bggavl.h:274 msgid "Specify the pixelformat" msgstr "" #: include/gmerlin/bggavl.h:290 include/gmerlin/bggavl.h:309 #: lib/x11/x11_window.c:1196 msgid "Nearest" msgstr "" #: include/gmerlin/bggavl.h:291 include/gmerlin/bggavl.h:310 #: lib/x11/x11_window.c:1197 msgid "Bilinear" msgstr "" #: include/gmerlin/bggavl.h:292 include/gmerlin/bggavl.h:311 #: lib/x11/x11_window.c:1198 msgid "Quadratic" msgstr "" #: include/gmerlin/bggavl.h:293 include/gmerlin/bggavl.h:312 #: lib/x11/x11_window.c:1199 msgid "Cubic B-Spline" msgstr "" #: include/gmerlin/bggavl.h:294 lib/x11/x11_window.c:1200 msgid "Cubic Mitchell-Netravali" msgstr "" #: include/gmerlin/bggavl.h:295 lib/x11/x11_window.c:1201 msgid "Cubic Catmull-Rom" msgstr "" #: include/gmerlin/bggavl.h:296 lib/x11/x11_window.c:1202 msgid "Sinc with Lanczos window" msgstr "" #: include/gmerlin/bggavl.h:325 msgid "Widening" msgstr "" #: include/gmerlin/bggavl.h:326 msgid "Gaussian preblur" msgstr "" #: include/gmerlin/bggavl.h:356 msgid "Resample chroma" msgstr "" #: include/gmerlin/bggavl.h:360 msgid "" "Always perform chroma resampling if chroma subsampling factors or chroma " "placements are different. Usually, this is only done for qualities above 3." msgstr "" #: include/gmerlin/bggavl.h:371 msgid "" "Background color to use, when alpha mode above is \"Blend background color\"." msgstr "" #: include/gmerlin/bggavl.h:377 msgid "Alpha mode" msgstr "" #: include/gmerlin/bggavl.h:382 msgid "Ignore" msgstr "" #: include/gmerlin/bggavl.h:382 msgid "Blend background color" msgstr "" #: include/gmerlin/bggavl.h:383 msgid "" "This option is used if the source has an alpha (=transparency) channel, but " "the output supports no transparency. Either, the transparency is ignored, or " "the background color you specify below is blended in." msgstr "" #: include/gmerlin/bggavl.h:520 msgid "From source" msgstr "" #: include/gmerlin/bggavl.h:544 msgid "Fixed samplerate" msgstr "" #: include/gmerlin/bggavl.h:548 msgid "" "If disabled, the output samplerate is taken from the source. If enabled, the " "samplerate you specify below us used." msgstr "" #: include/gmerlin/bggavl.h:555 msgid "Front channels" msgstr "" #: include/gmerlin/bggavl.h:564 msgid "Rear channels" msgstr "" #: include/gmerlin/bggavl.h:573 lib/formats.c:195 msgid "LFE" msgstr "" #: include/gmerlin/bggavl.h:580 msgid "Front to rear mode" msgstr "" #: include/gmerlin/bggavl.h:588 msgid "Mute" msgstr "" #: include/gmerlin/bggavl.h:590 msgid "Diff" msgstr "" #: include/gmerlin/bggavl.h:592 msgid "" "Mix mode when the output format has rear channels, but the source doesn't." msgstr "" #: include/gmerlin/bggavl.h:597 msgid "Stereo to mono mode" msgstr "" #: include/gmerlin/bggavl.h:605 msgid "Choose left" msgstr "" #: include/gmerlin/bggavl.h:606 msgid "Choose right" msgstr "" #: include/gmerlin/bggavl.h:607 msgid "Mix" msgstr "" #: include/gmerlin/bggavl.h:609 msgid "Mix mode when downmixing Stereo to Mono." msgstr "" #: include/gmerlin/bggavl.h:616 msgid "Fixed channel setup" msgstr "" #: include/gmerlin/bggavl.h:620 msgid "" "If disabled, the output channel configuration is taken from the source. If " "enabled, the setup you specify below us used." msgstr "" #: include/gmerlin/bggavl.h:633 msgid "8 bit" msgstr "" #: include/gmerlin/bggavl.h:633 include/gmerlin/bggavl.h:645 msgid "16 bit" msgstr "" #: include/gmerlin/bggavl.h:633 include/gmerlin/bggavl.h:645 msgid "32 bit" msgstr "" #: include/gmerlin/bggavl.h:633 include/gmerlin/bggavl.h:645 msgid "Float" msgstr "" #: include/gmerlin/bggavl.h:633 include/gmerlin/bggavl.h:645 msgid "Double" msgstr "" #: include/gmerlin/bggavl.h:634 msgid "" "Force a sampleformat to be used for processing. None means to take the input " "format." msgstr "" #: include/gmerlin/bggavl.h:646 msgid "Sampleformat to be used for processing." msgstr "" #: include/gmerlin/bggavl.h:652 msgid "Dither mode" msgstr "" #: include/gmerlin/bggavl.h:658 msgid "Shaped" msgstr "" #: include/gmerlin/bggavl.h:659 msgid "" "Dither mode. Auto means to use the quality level. Subsequent options are " "ordered by increasing quality (i.e. decreasing speed)." msgstr "" #: include/gmerlin/bggavl.h:665 msgid "Resample mode" msgstr "" #: include/gmerlin/bggavl.h:670 msgid "Zero order hold" msgstr "" #: include/gmerlin/bggavl.h:670 msgid "Linear" msgstr "" #: include/gmerlin/bggavl.h:671 msgid "Sinc fast" msgstr "" #: include/gmerlin/bggavl.h:671 msgid "Sinc medium" msgstr "" #: include/gmerlin/bggavl.h:671 msgid "Sinc best" msgstr "" #: include/gmerlin/bggavl.h:672 msgid "" "Resample mode. Auto means to use the quality level. Subsequent options are " "ordered by increasing quality (i.e. decreasing speed)." msgstr "" #: include/gmerlin/bggavl.h:678 msgid "Number of threads" msgstr "" #: include/gmerlin/bggavl.h:683 msgid "" "Threads to launch for processing operations. Changing this requires program " "restart" msgstr "" #: include/gmerlin/pluginfuncs.h:40 msgid "Default timescale" msgstr "" #: include/gmerlin/pluginfuncs.h:43 msgid "" "For formats, which support only constant framerates, set the default " "timescale here" msgstr "" #: include/gmerlin/pluginfuncs.h:47 msgid "Default frame duration" msgstr "" #: include/gmerlin/pluginfuncs.h:50 msgid "" "For formats, which support only constant framerates, set the default frame " "duration here" msgstr "" #: apps/player/skinbrowser.c:315 #, c-format msgid "" "Installing skin from\n" "%s\n" "failed" msgstr "" #: apps/player/skinbrowser.c:406 msgid "Skin browser" msgstr "" #: apps/player/gmerlin.c:305 msgid "Gmerlin player" msgstr "" #: apps/player/gmerlin.c:711 msgid "General Options" msgstr "" #: apps/player/gmerlin.c:717 msgid "Skip error tracks" msgstr "" #: apps/player/gmerlin.c:720 msgid "If a track cannot be opened, switch to the next one" msgstr "" #: apps/player/gmerlin.c:724 msgid "Don't advance" msgstr "" #: apps/player/gmerlin.c:730 msgid "Shuffle mode" msgstr "" #: apps/player/gmerlin.c:736 apps/player/mainmenu.c:751 msgid "Off" msgstr "" #: apps/player/gmerlin.c:737 msgid "Current album" msgstr "" #: apps/player/gmerlin.c:738 msgid "All open albums" msgstr "" #: apps/player/gmerlin.c:744 msgid "Show tooltips" msgstr "" #: apps/player/main.c:52 msgid "[options] [gmls ...]\n" msgstr "" #: apps/player/main.c:53 msgid "Gmerlin GUI Player" msgstr "" #: apps/player/main.c:58 apps/player/gmerlin_remote.c:567 #: apps/transcoder/main.c:74 apps/transcoder/gmerlin_transcoder_remote.c:179 msgid "Default port for the remote control" msgstr "" #: apps/player/main.c:63 apps/cmdlinerecorder/gmerlin-record.c:321 #: apps/cmdlineplayer/gmerlin_play.c:842 apps/nmjedit/gmerlin-nmjedit.c:174 #: apps/thumbnailer/gmerlin-video-thumbnailer.c:98 tests/fvtest.c:179 msgid "Cache of the plugin registry (shared by all applicatons)" msgstr "" #: apps/player/main.c:65 msgid "" "Used for configuration data. Delete this file if you think you goofed " "something up." msgstr "" #: apps/player/main.c:67 msgid "" "Media tree is saved here. The albums are saved as separate files in the same " "directory." msgstr "" #: apps/player/cfgdialog.c:39 lib/gtk/plugin_single.c:379 msgid "Audio options" msgstr "" #: apps/player/cfgdialog.c:47 apps/plugincfg/gmerlin_plugincfg.c:399 msgid "Audio filters" msgstr "" #: apps/player/cfgdialog.c:56 lib/gtk/plugin_single.c:387 msgid "Video options" msgstr "" #: apps/player/cfgdialog.c:64 apps/plugincfg/gmerlin_plugincfg.c:413 msgid "Video filters" msgstr "" #: apps/player/cfgdialog.c:74 msgid "Subtitle options" msgstr "" #: apps/player/cfgdialog.c:83 apps/visualizer/gmerlin_visualizer.c:1110 #: lib/gtk/plugininfo.c:169 msgid "Visualization" msgstr "" #: apps/player/cfgdialog.c:86 lib/pluginregistry.c:2158 #: lib/pluginregistry.c:2623 msgid "Text subtitles" msgstr "" #: apps/player/cfgdialog.c:89 apps/transcoder/trackdialog.c:374 #: apps/transcoder/trackdialog.c:442 lib/gtk/infowindow.c:735 msgid "Subtitles" msgstr "" #: apps/player/cfgdialog.c:97 msgid "Gmerlin confiuration" msgstr "" #: apps/player/cfgdialog.c:114 apps/camelot/webcam_window.c:536 #: lib/gtk/plugininfo.c:154 msgid "Input" msgstr "" #: apps/player/cfgdialog.c:122 apps/plugincfg/gmerlin_plugincfg.c:273 #: apps/transcoder/transcoder_window.c:1391 msgid "Input plugins" msgstr "" #: apps/player/cfgdialog.c:130 apps/plugincfg/gmerlin_plugincfg.c:574 #: apps/transcoder/transcoder_window.c:1399 msgid "Image readers" msgstr "" #: apps/player/cfgdialog.c:140 msgid "OSD" msgstr "" #: apps/player/cfgdialog.c:151 apps/transcoder/transcoder_window.c:172 msgid "Display" msgstr "" #: apps/player/cfgdialog.c:161 apps/player/mainmenu.c:1009 msgid "Media Tree" msgstr "" #: apps/player/cfgdialog.c:171 msgid "Remote control" msgstr "" #: apps/player/cfgdialog.c:181 apps/player/mainmenu.c:1015 #: apps/camelot/webcam_window.c:803 apps/transcoder/transcoder_window.c:1432 #: apps/visualizer/gmerlin_visualizer.c:908 #: apps/recorder/recorder_window.c:803 msgid "Log window" msgstr "" #: apps/player/cfgdialog.c:191 msgid "LCDproc" msgstr "" #: apps/player/mainmenu.c:765 apps/player/mainmenu.c:802 #: apps/player/mainmenu.c:1192 msgid "Options..." msgstr "" #: apps/player/mainmenu.c:769 msgid "Filters..." msgstr "" #: apps/player/mainmenu.c:772 msgid "Output plugin..." msgstr "" #: apps/player/mainmenu.c:797 msgid "Enable visualizations" msgstr "" #: apps/player/mainmenu.c:806 lib/gtk/treewidget.c:1412 msgid "Plugin..." msgstr "" #: apps/player/mainmenu.c:941 #, c-format msgid "Chapter %d [%s]" msgstr "" #: apps/player/mainmenu.c:1012 msgid "Info window" msgstr "" #: apps/player/mainmenu.c:1022 apps/transcoder/transcoder_window.c:862 msgid "About..." msgstr "" #: apps/player/mainmenu.c:1024 apps/transcoder/transcoder_window.c:863 msgid "Userguide" msgstr "" #: apps/player/mainmenu.c:1045 apps/transcoder/transcoder_window.c:847 msgid "Preferences..." msgstr "" #: apps/player/mainmenu.c:1052 msgid "Skins..." msgstr "" #: apps/player/mainmenu.c:1056 msgid "Multimedia keys..." msgstr "" #: apps/player/mainmenu.c:1062 msgid "Seek forward" msgstr "" #: apps/player/mainmenu.c:1069 msgid "Seek backward" msgstr "" #: apps/player/mainmenu.c:1076 msgid "Increase volume" msgstr "" #: apps/player/mainmenu.c:1083 msgid "Decrease volume" msgstr "" #: apps/player/mainmenu.c:1089 apps/player/gmerlin_remote.c:414 msgid "Toggle mute" msgstr "" #: apps/player/mainmenu.c:1095 msgid "Next track" msgstr "" #: apps/player/mainmenu.c:1100 msgid "Previous track" msgstr "" #: apps/player/mainmenu.c:1105 msgid "Next chapter" msgstr "" #: apps/player/mainmenu.c:1111 msgid "Previous chapter" msgstr "" #: apps/player/mainmenu.c:1116 lib/gtk/treewidget.c:1336 #: lib/gtk/treewidget.c:2046 msgid "Goto current track" msgstr "" #: apps/player/mainmenu.c:1123 msgid "Copy current track to favourites" msgstr "" #: apps/player/mainmenu.c:1131 msgid "Seek to start" msgstr "" #: apps/player/mainmenu.c:1136 lib/player.c:331 msgid "Pause" msgstr "" #: apps/player/mainmenu.c:1141 msgid "Quit gmerlin" msgstr "" #: apps/player/mainmenu.c:1152 msgid "Transcoder" msgstr "" #: apps/player/mainmenu.c:1156 apps/visualizer/gmerlin_visualizer.c:899 msgid "Visualizer" msgstr "" #: apps/player/mainmenu.c:1160 msgid "Mixer" msgstr "" #: apps/player/mainmenu.c:1167 msgid "Audio..." msgstr "" #: apps/player/mainmenu.c:1171 msgid "Video..." msgstr "" #: apps/player/mainmenu.c:1175 msgid "Subtitles..." msgstr "" #: apps/player/mainmenu.c:1179 msgid "Chapters..." msgstr "" #: apps/player/mainmenu.c:1184 msgid "Visualization..." msgstr "" #: apps/player/mainmenu.c:1188 msgid "Windows..." msgstr "" #: apps/player/mainmenu.c:1196 msgid "Commands..." msgstr "" #: apps/player/mainmenu.c:1200 msgid "Accessories..." msgstr "" #: apps/player/mainmenu.c:1204 msgid "Help..." msgstr "" #: apps/player/display.c:67 msgid "Get colors from skin" msgstr "" #: apps/player/display.c:70 msgid "Take the display colors from the skin definition" msgstr "" #: apps/player/display.c:74 apps/transcoder/transcoder_window.c:189 msgid "Background" msgstr "" #: apps/player/display.c:80 msgid "Normal foreground" msgstr "" #: apps/player/display.c:86 apps/transcoder/transcoder_window.c:183 #: lib/gtk/logwindow.c:378 msgid "Error foreground" msgstr "" #: apps/player/display.c:92 msgid "Display mode" msgstr "" #: apps/player/display.c:101 msgid "Repeat mode" msgstr "" #: apps/player/gmerlin_remote.c:201 msgid "Option -addplay requires an argument\n" msgstr "" #: apps/player/gmerlin_remote.c:223 msgid "Option -add requires an argument\n" msgstr "" #: apps/player/gmerlin_remote.c:246 msgid "Option -openplay requires an argument\n" msgstr "" #: apps/player/gmerlin_remote.c:268 msgid "Option -open requires an argument\n" msgstr "" #: apps/player/gmerlin_remote.c:291 msgid "Option -volume requires an argument\n" msgstr "" #: apps/player/gmerlin_remote.c:314 msgid "Option -volume_rel requires an argument\n" msgstr "" #: apps/player/gmerlin_remote.c:339 msgid "Option -seek_rel requires an argument\n" msgstr "" #: apps/player/gmerlin_remote.c:364 msgid "Option -chapter requires an argument\n" msgstr "" #: apps/player/gmerlin_remote.c:389 msgid "Play current track" msgstr "" #: apps/player/gmerlin_remote.c:394 msgid "Switch to next track" msgstr "" #: apps/player/gmerlin_remote.c:399 msgid "Switch to previous track" msgstr "" #: apps/player/gmerlin_remote.c:404 msgid "Stop playback" msgstr "" #: apps/player/gmerlin_remote.c:409 msgid "Pause playback" msgstr "" #: apps/player/gmerlin_remote.c:419 apps/player/gmerlin_remote.c:425 msgid "" msgstr "" #: apps/player/gmerlin_remote.c:420 msgid "Add to the incoming album" msgstr "" #: apps/player/gmerlin_remote.c:426 msgid "Add to the incoming album and play it" msgstr "" #: apps/player/gmerlin_remote.c:431 apps/player/gmerlin_remote.c:437 msgid "" msgstr "" #: apps/player/gmerlin_remote.c:432 msgid "Open album for . Device must be a GML (e.g. dvd:///dev/hdd)." msgstr "" #: apps/player/gmerlin_remote.c:438 msgid "" "Open album for and play first track. Device must be a GML (e.g. " "dvd:///dev/hdd)." msgstr "" #: apps/player/gmerlin_remote.c:443 msgid "" msgstr "" #: apps/player/gmerlin_remote.c:444 msgid "Set player volume. is in dB, 0.0 is max" msgstr "" #: apps/player/gmerlin_remote.c:449 apps/player/gmerlin_remote.c:455 msgid "" msgstr "" #: apps/player/gmerlin_remote.c:450 msgid "In- or decrease player volume. is in dB" msgstr "" #: apps/player/gmerlin_remote.c:456 msgid "Seek relative. is in seconds." msgstr "" #: apps/player/gmerlin_remote.c:462 msgid "" "Go to the specified chapter. Use '+' and '-' to go to the next or previous " "chapter respectively" msgstr "" #: apps/player/gmerlin_remote.c:467 msgid "Print name of the current track" msgstr "" #: apps/player/gmerlin_remote.c:472 msgid "Print metadata of the current track" msgstr "" #: apps/player/gmerlin_remote.c:477 msgid "Print time of the current track" msgstr "" #: apps/player/gmerlin_remote.c:492 msgid "Option -host requires an argument" msgstr "" #: apps/player/gmerlin_remote.c:504 msgid "Option -port requires an argument" msgstr "" #: apps/player/gmerlin_remote.c:522 msgid "Host to connect to, default is localhost" msgstr "" #: apps/player/gmerlin_remote.c:528 msgid "Port to connect to" msgstr "" #: apps/player/gmerlin_remote.c:533 msgid "Launch new player if necessary" msgstr "" #: apps/player/gmerlin_remote.c:560 #: apps/transcoder/gmerlin_transcoder_remote.c:172 msgid "[options] command\n" msgstr "" #: apps/player/gmerlin_remote.c:561 msgid "Remote control command for the Gmerlin GUI Player\n" msgstr "" #: apps/player/gmerlin_remote.c:562 #: apps/transcoder/gmerlin_transcoder_remote.c:174 msgid "Global options" msgstr "" #: apps/player/gmerlin_remote.c:563 #: apps/transcoder/gmerlin_transcoder_remote.c:175 msgid "Commands" msgstr "" #: apps/player/gmerlin_remote.c:605 msgid "Cannot launch gmerlin process" msgstr "" #: apps/plugincfg/gmerlin_plugincfg.c:261 msgid "Gmerlin Plugin Configurator" msgstr "" #: apps/plugincfg/gmerlin_plugincfg.c:313 msgid "Encode audio into video file" msgstr "" #: apps/plugincfg/gmerlin_plugincfg.c:331 msgid "Encode text subtitles into video file" msgstr "" #: apps/plugincfg/gmerlin_plugincfg.c:351 msgid "Encode overlay subtitles into video file" msgstr "" #: apps/plugincfg/gmerlin_plugincfg.c:382 apps/transcoder/ppwidget.c:79 msgid "Enable postprocessing" msgstr "" #: apps/plugincfg/gmerlin_plugincfg.c:427 msgid "Visualizations" msgstr "" #: apps/plugincfg/gmerlin_plugincfg.c:453 msgid "Output" msgstr "" #: apps/plugincfg/gmerlin_plugincfg.c:536 #: apps/transcoder/transcoder_window.c:1383 #: apps/recorder/recorder_window.c:777 msgid "Encoders" msgstr "" #: apps/plugincfg/gmerlin_plugincfg.c:559 lib/gtk/plugininfo.c:181 msgid "Recorder" msgstr "" #: apps/plugincfg/gmerlin_plugincfg.c:607 msgid "Image writers" msgstr "" #: apps/cmdlinerecorder/gmerlin-record.c:315 apps/transcoder/main.c:68 #: apps/nmjedit/gmerlin-nmjedit.c:168 msgid "[options]\n" msgstr "" #: apps/cmdlinerecorder/gmerlin-record.c:316 msgid "Commandline recorder\n" msgstr "" #: apps/cmdlinerecorder/gmerlin-record.c:317 #: apps/transcoder/transcoder_window.c:1006 apps/transcoder/main.c:70 #: apps/cmdlineplayer/gmerlin_play.c:838 apps/nmjedit/gmerlin-nmjedit.c:170 #: apps/thumbnailer/gmerlin-video-thumbnailer.c:94 tests/imgconvert.c:97 #: tests/fvtest.c:175 tests/cfgtest.c:624 tests/visualization.c:78 #: tests/gmerlin_visualize.c:344 msgid "Options" msgstr "" #: apps/cmdlinerecorder/gmerlin-record.c:323 #: apps/cmdlineplayer/gmerlin_play.c:844 apps/nmjedit/gmerlin-nmjedit.c:176 #: apps/thumbnailer/gmerlin-video-thumbnailer.c:100 tests/fvtest.c:181 msgid "" "Default plugin parameters are read from there. Use gmerlin_plugincfg to " "change them." msgstr "" #: apps/camelot/webcam.c:52 apps/camelot/webcam.c:561 msgid "read_frame failed" msgstr "" #: apps/camelot/webcam.c:241 msgid "do_capture: No plugin loaded" msgstr "" #: apps/camelot/webcam.c:259 #, c-format msgid "Saving %s failed" msgstr "" #: apps/camelot/webcam.c:303 msgid "Opening monitor plugin failed" msgstr "" #: apps/camelot/webcam.c:391 #, c-format msgid "Initializing %s failed, check settings" msgstr "" #: apps/camelot/webcam.c:683 lib/player_video.c:249 msgid "Restarting playback due to changed video filters" msgstr "" #: apps/camelot/webcam.c:722 msgid "Restarting vloopback failed, close client and try again" msgstr "" #: apps/camelot/webcam.c:735 msgid "Video capture" msgstr "" #: apps/camelot/webcam.c:740 msgid "Maximum framerate" msgstr "" #: apps/camelot/vloopback.c:185 msgid "VIDIOCGCAP" msgstr "" #: apps/camelot/vloopback.c:201 msgid "VIDIOCGCHAN" msgstr "" #: apps/camelot/vloopback.c:216 msgid "VIDIOCSCHAN" msgstr "" #: apps/camelot/vloopback.c:226 #, c-format msgid "VIDIOCCAPTURE %d" msgstr "" #: apps/camelot/vloopback.c:242 #, c-format msgid "VIDIOCGPICT %d %d" msgstr "" #: apps/camelot/vloopback.c:251 msgid "VIDIOCSPICT" msgstr "" #: apps/camelot/vloopback.c:259 #, c-format msgid "unsupported pixel format (%d) is requested in VIDIOCSPICT" msgstr "" #: apps/camelot/vloopback.c:282 #, c-format msgid "VIDIOCGWIN %dx%d" msgstr "" #: apps/camelot/vloopback.c:291 msgid "VIDIOCSWIN" msgstr "" #: apps/camelot/vloopback.c:295 #, c-format msgid "width %d out of range" msgstr "" #: apps/camelot/vloopback.c:300 #, c-format msgid "height %d out of range" msgstr "" #: apps/camelot/vloopback.c:305 #, c-format msgid "invalid flags %08x in VIDIOCSWIN" msgstr "" #: apps/camelot/vloopback.c:318 msgid "VIDIOCSYNC" msgstr "" #: apps/camelot/vloopback.c:322 #, c-format msgid "frame %d out of range in VIDIOCSYNC" msgstr "" #: apps/camelot/vloopback.c:333 msgid "VIDIOCMCAPTURE" msgstr "" #: apps/camelot/vloopback.c:340 #, c-format msgid "VIDIOCMCAPTURE: requested capture size is too big: %dx%d" msgstr "" #: apps/camelot/vloopback.c:346 #, c-format msgid "VIDIOCMCAPTURE: requested capture size is too small: %dx%d" msgstr "" #: apps/camelot/vloopback.c:351 #, c-format msgid "VIDIOCMCAPTURE %dx%d, format: %d" msgstr "" #: apps/camelot/vloopback.c:364 #, c-format msgid "unsupported pixel format (%d) is requested in VIDIOCMCAPTURE" msgstr "" #: apps/camelot/vloopback.c:375 #, c-format msgid "Invalid frame (%d) in VIDIOCMCAPTURE" msgstr "" #: apps/camelot/vloopback.c:388 msgid "VIDIOCGMBUF" msgstr "" #: apps/camelot/vloopback.c:400 #, c-format msgid "Unknown ioctl %lx" msgstr "" #: apps/camelot/vloopback.c:535 #, c-format msgid "VIDIOCGCAP failed %s" msgstr "" #: apps/camelot/vloopback.c:557 msgid "ioctl VIDIOCGWIN failed" msgstr "" #: apps/camelot/vloopback.c:566 msgid "ioctl VIDIOCSWIN failed" msgstr "" #: apps/camelot/vloopback.c:574 msgid "Opened vloopback in write mode" msgstr "" #: apps/camelot/vloopback.c:585 #, c-format msgid "vloopback mmap failed: %s" msgstr "" #: apps/camelot/vloopback.c:592 msgid "Opened vloopback in ioctl mode" msgstr "" #: apps/camelot/vloopback.c:612 msgid "Closed vloopback" msgstr "" #: apps/camelot/vloopback.c:655 msgid "Client connected" msgstr "" #: apps/camelot/vloopback.c:670 msgid "Client disconnected" msgstr "" #: apps/camelot/vloopback.c:684 #, c-format msgid "ioctl %lx unsuccessfull." msgstr "" #: apps/camelot/vloopback.c:740 msgid "Write" msgstr "" #: apps/camelot/vloopback.c:740 msgid "ioctl" msgstr "" #: apps/camelot/vloopback.c:741 msgid "" "Set the operating mode. Ioctl is more flexible on the clients side but " "doesn't work with all applications. Write works with more applications but " "has a larger overhead" msgstr "" #: apps/camelot/vloopback.c:765 msgid "Fixed resolution for write mode" msgstr "" #: apps/camelot/vloopback.c:774 msgid "User defined width for write mode" msgstr "" #: apps/camelot/vloopback.c:783 msgid "User defined height for write mode" msgstr "" #: apps/camelot/vloopback.c:792 msgid "Y'CbCr 4:2:0" msgstr "" #: apps/camelot/vloopback.c:793 msgid "RGB (24 bit)" msgstr "" #: apps/camelot/vloopback.c:795 msgid "Pixelformat for write mode" msgstr "" #: apps/camelot/webcam_window.c:309 apps/recorder/recorder_window.c:441 #, c-format msgid "Framerate: %.2f fps" msgstr "" #: apps/camelot/webcam_window.c:434 apps/camelot/webcam_window.c:456 #: apps/camelot/webcam_window.c:494 lib/recorder_video.c:160 #: lib/recorder_video.c:284 lib/recorder_video.c:388 lib/singlepic.c:755 #: lib/transcoder_track.c:182 lib/recorder_audio.c:93 lib/ovl2text.c:157 msgid "Plugin" msgstr "" #: apps/camelot/webcam_window.c:442 msgid "Reopen" msgstr "" #: apps/camelot/webcam_window.c:448 msgid "Setup filters" msgstr "" #: apps/camelot/webcam_window.c:465 msgid "Take picture" msgstr "" #: apps/camelot/webcam_window.c:470 apps/camelot/webcam_window.c:844 msgid "Automatic capture" msgstr "" #: apps/camelot/webcam_window.c:483 msgid "Enable vloopback" msgstr "" #: apps/camelot/webcam_window.c:504 msgid "Enable Monitor" msgstr "" #: apps/camelot/webcam_window.c:527 msgid "Set" msgstr "" #: apps/camelot/webcam_window.c:567 apps/transcoder/transcoder_window.c:1315 #: apps/transcoder/transcoder_window.c:1341 apps/transcoder/trackdialog.c:234 #: apps/transcoder/trackdialog.c:304 apps/recorder/recorder_window.c:732 #: apps/recorder/recorder_window.c:751 msgid "Filters" msgstr "" #: apps/camelot/webcam_window.c:616 msgid "Cam" msgstr "" #: apps/camelot/webcam_window.c:640 msgid "Interval (sec)" msgstr "" #: apps/camelot/webcam_window.c:655 apps/alsamixer/card.c:231 msgid "Capture" msgstr "" #: apps/camelot/webcam_window.c:667 msgid "Directory" msgstr "" #: apps/camelot/webcam_window.c:684 lib/recorder.c:520 msgid "" "Extension is appended by the plugin\n" "%t Inserts time\n" "%d Inserts date\n" "%n Inserts Frame number with digits" msgstr "" #: apps/camelot/webcam_window.c:695 msgid "Filename base" msgstr "" #: apps/camelot/webcam_window.c:704 msgid "Frame counter" msgstr "" #: apps/camelot/webcam_window.c:721 apps/recorder/recorder_window.c:787 msgid "Output files" msgstr "" #: apps/camelot/webcam_window.c:737 apps/recorder/recorder_window.c:614 #: lib/gtk/aboutwindow.c:126 msgid "About" msgstr "" #: apps/camelot/webcam_window.c:738 apps/transcoder/transcoder_window.c:858 #: apps/recorder/recorder_window.c:616 msgid "Log messages" msgstr "" #: apps/camelot/webcam_window.c:739 apps/recorder/recorder_window.c:618 msgid "Preferences" msgstr "" #: apps/camelot/webcam_window.c:790 msgid "Camelot confiuration" msgstr "" #: apps/camelot/webcam_window.c:794 apps/camelot/webcam_window.c:880 msgid "vloopback" msgstr "" #: apps/camelot/webcam_window.c:837 msgid "Do monitor" msgstr "" #: apps/camelot/webcam_window.c:840 msgid "Enable monitoring of the webcam image" msgstr "" #: apps/camelot/webcam_window.c:847 msgid "Automatically capture in the specified capture interval" msgstr "" #: apps/camelot/webcam_window.c:851 msgid "Capture interval" msgstr "" #: apps/camelot/webcam_window.c:856 msgid "Capture interval (in seconds)" msgstr "" #: apps/camelot/webcam_window.c:860 lib/recorder.c:496 msgid "Output directory" msgstr "" #: apps/camelot/webcam_window.c:866 msgid "Output namebase" msgstr "" #: apps/camelot/webcam_window.c:869 msgid "" "Template for the output files. A mask \"%n\" inserts the frame number " "with digits (e.g. webcam-shot-%6n)" msgstr "" #: apps/camelot/webcam_window.c:873 msgid "Output framecounter" msgstr "" #: apps/camelot/webcam_window.c:886 msgid "vloopback_dev" msgstr "" #: apps/transcoder/transcoder_window.c:177 msgid "Foreground" msgstr "" #: apps/transcoder/transcoder_window.c:222 msgid "GUI" msgstr "" #: apps/transcoder/transcoder_window.c:227 msgid "Show Tooltips" msgstr "" #: apps/transcoder/transcoder_window.c:659 #: apps/transcoder/transcoder_window.c:968 msgid "Load task list" msgstr "" #: apps/transcoder/transcoder_window.c:669 #: apps/transcoder/transcoder_window.c:970 msgid "Save task list" msgstr "" #: apps/transcoder/transcoder_window.c:680 msgid "Load profile" msgstr "" #: apps/transcoder/transcoder_window.c:690 msgid "Save profile" msgstr "" #: apps/transcoder/transcoder_window.c:841 msgid "Load tasklist..." msgstr "" #: apps/transcoder/transcoder_window.c:842 msgid "Save tasklist..." msgstr "" #: apps/transcoder/transcoder_window.c:843 #: apps/visualizer/gmerlin_visualizer.c:1050 msgid "Quit" msgstr "" #: apps/transcoder/transcoder_window.c:848 msgid "Load profile..." msgstr "" #: apps/transcoder/transcoder_window.c:849 msgid "Save profile..." msgstr "" #: apps/transcoder/transcoder_window.c:853 #: apps/transcoder/transcoder_window.c:958 msgid "Start transcoding" msgstr "" #: apps/transcoder/transcoder_window.c:854 #: apps/transcoder/transcoder_window.c:961 msgid "Stop transcoding" msgstr "" #: apps/transcoder/transcoder_window.c:950 msgid "Gmerlin transcoder" msgstr "" #: apps/transcoder/transcoder_window.c:964 msgid "Set global options and track defaults" msgstr "" #: apps/transcoder/transcoder_window.c:966 msgid "Quit program" msgstr "" #: apps/transcoder/transcoder_window.c:1001 lib/gtk/plugininfo.c:182 msgid "File" msgstr "" #: apps/transcoder/transcoder_window.c:1011 msgid "Actions" msgstr "" #: apps/transcoder/transcoder_window.c:1016 #: apps/transcoder/transcoder_window.c:1075 msgid "Tasklist" msgstr "" #: apps/transcoder/transcoder_window.c:1021 msgid "Windows" msgstr "" #: apps/transcoder/transcoder_window.c:1026 msgid "Help" msgstr "" #: apps/transcoder/transcoder_window.c:1274 msgid "Transcoder configuration" msgstr "" #: apps/transcoder/transcoder_window.c:1279 msgid "Output options" msgstr "" #: apps/transcoder/transcoder_window.c:1290 msgid "Track defaults" msgstr "" #: apps/transcoder/transcoder_window.c:1299 msgid "Audio defaults" msgstr "" #: apps/transcoder/transcoder_window.c:1328 msgid "Video defaults" msgstr "" #: apps/transcoder/transcoder_window.c:1349 msgid "Text subtitle defaults" msgstr "" #: apps/transcoder/transcoder_window.c:1364 apps/transcoder/trackdialog.c:390 msgid "Textrenderer" msgstr "" #: apps/transcoder/transcoder_window.c:1375 msgid "Overlay subtitle defaults" msgstr "" #: apps/transcoder/transcoder_window.c:1410 msgid "Window" msgstr "" #: apps/transcoder/transcoder_window.c:1421 msgid "Remote" msgstr "" #: apps/transcoder/main.c:69 msgid "GTK multimedia transcoder\n" msgstr "" #: apps/transcoder/ppwidget.c:209 msgid "Postprocessing" msgstr "" #: apps/transcoder/gmerlin_transcoder_remote.c:173 msgid "Remote control command for the Gmerlin GUI transcoder\n" msgstr "" #: apps/transcoder/gmerlin_transcoder_remote.c:214 msgid "Cannot launch transcoder process" msgstr "" #: apps/transcoder/tracklist.c:832 msgid "Encoder configuration" msgstr "" #: apps/transcoder/tracklist.c:891 msgid "" "Use \"-\" to clear this field for all tracks. Empty string means to leave it " "unchanged for all tracks" msgstr "" #: apps/transcoder/tracklist.c:902 msgid "Mass tag" msgstr "" #: apps/transcoder/tracklist.c:951 lib/tree.c:1176 msgid "Format for track names" msgstr "" #: apps/transcoder/tracklist.c:953 lib/tree.c:1179 msgid "" "Format specifier for tracknames from\n" "metadata\n" "%p: Artist\n" "%a: Album\n" "%g: Genre\n" "%t: Track name\n" "%n: Track number with digits\n" "%y: Year\n" "%c: Comment" msgstr "" #: apps/transcoder/tracklist.c:1007 msgid "Auto rename" msgstr "" #: apps/transcoder/tracklist.c:1096 lib/gtk/albumwidget.c:2899 msgid "Add files" msgstr "" #: apps/transcoder/tracklist.c:1229 lib/gtk/albumwidget.c:1453 msgid "Files..." msgstr "" #: apps/transcoder/tracklist.c:1231 msgid "Urls..." msgstr "" #: apps/transcoder/tracklist.c:1233 msgid "Drives..." msgstr "" #: apps/transcoder/tracklist.c:1241 msgid "Move Up" msgstr "" #: apps/transcoder/tracklist.c:1243 msgid "Move Down" msgstr "" #: apps/transcoder/tracklist.c:1245 lib/gtk/treewidget.c:1386 #: lib/gtk/albumwidget.c:1494 msgid "Remove" msgstr "" #: apps/transcoder/tracklist.c:1247 msgid "Configure..." msgstr "" #: apps/transcoder/tracklist.c:1249 msgid "Edit chapters..." msgstr "" #: apps/transcoder/tracklist.c:1251 msgid "Mass tag..." msgstr "" #: apps/transcoder/tracklist.c:1253 msgid "Auto numbering" msgstr "" #: apps/transcoder/tracklist.c:1255 msgid "Auto rename..." msgstr "" #: apps/transcoder/tracklist.c:1257 msgid "Change encoders..." msgstr "" #: apps/transcoder/tracklist.c:1264 lib/gtk/albumwidget.c:1501 #: lib/gtk/albumwidget.c:2904 msgid "Cut" msgstr "" #: apps/transcoder/tracklist.c:1273 lib/gtk/albumwidget.c:1515 #: lib/gtk/albumwidget.c:2908 msgid "Paste" msgstr "" #: apps/transcoder/tracklist.c:1284 lib/gtk/albumwidget.c:1581 #: lib/gtk/cfg_device.c:339 msgid "Add..." msgstr "" #: apps/transcoder/tracklist.c:1290 lib/gtk/albumwidget.c:1595 msgid "Selected..." msgstr "" #: apps/transcoder/tracklist.c:1296 lib/gtk/albumwidget.c:1588 msgid "Edit..." msgstr "" #: apps/transcoder/tracklist.c:1302 msgid "Postprocess..." msgstr "" #: apps/transcoder/tracklist.c:1517 lib/gtk/albumwidget.c:2934 msgid "Total playback time" msgstr "" #: apps/transcoder/tracklist.c:1526 msgid "Append files to the task list" msgstr "" #: apps/transcoder/tracklist.c:1531 msgid "Append URLs to the task list" msgstr "" #: apps/transcoder/tracklist.c:1536 msgid "Append removable media to the task list" msgstr "" #: apps/transcoder/tracklist.c:1541 msgid "Delete selected tracks" msgstr "" #: apps/transcoder/tracklist.c:1546 msgid "Configure selected track" msgstr "" #: apps/transcoder/tracklist.c:1551 lib/gtk/chapterdialog.c:343 msgid "Edit chapters" msgstr "" #: apps/transcoder/tracklist.c:1556 msgid "Change encoder plugins for selected tracks" msgstr "" #: apps/transcoder/tracklist.c:1561 msgid "Copy selected tracks to clipboard" msgstr "" #: apps/transcoder/tracklist.c:1565 msgid "Cut selected tracks to clipboard" msgstr "" #: apps/transcoder/tracklist.c:1570 msgid "Paste tracks from clipboard" msgstr "" #: apps/transcoder/trackdialog.c:82 msgid "Track options" msgstr "" #: apps/transcoder/trackdialog.c:96 apps/recorder/recorder_window.c:795 #: lib/gtk/infowindow.c:692 lib/gtk/infowindow.c:701 lib/gtk/infowindow.c:720 #: lib/gtk/infowindow.c:739 msgid "Metadata" msgstr "" #: apps/transcoder/trackdialog.c:208 #, c-format msgid "Audio #%d: %s" msgstr "" #: apps/transcoder/trackdialog.c:210 #, c-format msgid "Audio #%d" msgstr "" #: apps/transcoder/trackdialog.c:215 #, c-format msgid "Audio: %s" msgstr "" #: apps/transcoder/trackdialog.c:243 apps/transcoder/trackdialog.c:313 #: apps/transcoder/trackdialog.c:459 msgid "Encode options" msgstr "" #: apps/transcoder/trackdialog.c:279 #, c-format msgid "Video #%d: %s" msgstr "" #: apps/transcoder/trackdialog.c:281 #, c-format msgid "Video #%d" msgstr "" #: apps/transcoder/trackdialog.c:286 #, c-format msgid "Video: %s" msgstr "" #: apps/transcoder/trackdialog.c:365 apps/transcoder/trackdialog.c:432 #, c-format msgid "Subtitles #%d: %s" msgstr "" #: apps/transcoder/trackdialog.c:367 apps/transcoder/trackdialog.c:435 #, c-format msgid "Subtitles #%d" msgstr "" #: apps/transcoder/trackdialog.c:372 apps/transcoder/trackdialog.c:440 #, c-format msgid "Subtitles: %s" msgstr "" #: apps/transcoder/trackdialog.c:399 msgid "Encode options (text)" msgstr "" #: apps/transcoder/trackdialog.c:412 msgid "Encode options (overlay)" msgstr "" #: apps/visualizer/gmerlin_visualizer.c:335 #: apps/visualizer/gmerlin_visualizer.c:361 msgid "Opening audio device failed, fix settings and click restart" msgstr "" #: apps/visualizer/gmerlin_visualizer.c:336 #: apps/visualizer/gmerlin_visualizer.c:362 msgid "No audio" msgstr "" #: apps/visualizer/gmerlin_visualizer.c:498 #, c-format msgid "Changed recording plugin to %s" msgstr "" #: apps/visualizer/gmerlin_visualizer.c:515 lib/gtk/plugininfo.c:157 msgid "Audio recorder" msgstr "" #: apps/visualizer/gmerlin_visualizer.c:525 lib/gtk/plugininfo.c:156 msgid "Video output" msgstr "" #: apps/visualizer/gmerlin_visualizer.c:887 msgid "Visualizer configuration" msgstr "" #: apps/visualizer/gmerlin_visualizer.c:1041 msgid "Gmerlin visualizer" msgstr "" #: apps/visualizer/gmerlin_visualizer.c:1044 msgid "Configure" msgstr "" #: apps/visualizer/gmerlin_visualizer.c:1046 msgid "Recording and display plugins" msgstr "" #: apps/visualizer/gmerlin_visualizer.c:1048 msgid "Restart visualization" msgstr "" #: apps/visualizer/gmerlin_visualizer.c:1052 #: apps/recorder/recorder_window.c:627 msgid "Fullscreen mode" msgstr "" #: apps/visualizer/gmerlin_visualizer.c:1054 #: apps/recorder/recorder_window.c:629 msgid "Leave fullscreen mode" msgstr "" #: apps/visualizer/gmerlin_visualizer.c:1058 msgid "Show log window" msgstr "" #: apps/visualizer/gmerlin_visualizer.c:1061 msgid "About Gmerlin visualizer" msgstr "" #: apps/visualizer/gmerlin_visualizer.c:1064 msgid "Launch help in a webwroswer" msgstr "" #: apps/cmdlineplayer/gmerlin_play.c:558 #, c-format msgid "No such track %d" msgstr "" #: apps/cmdlineplayer/gmerlin_play.c:600 #, c-format msgid "Got redirector %s (%d/%d)" msgstr "" #: apps/cmdlineplayer/gmerlin_play.c:687 #, c-format msgid "Name: %s" msgstr "" #: apps/cmdlineplayer/gmerlin_play.c:695 #, c-format msgid "Audio streams %d" msgstr "" #: apps/cmdlineplayer/gmerlin_play.c:700 #, c-format msgid "Video streams %d" msgstr "" #: apps/cmdlineplayer/gmerlin_play.c:705 #, c-format msgid "Subtitle streams %d" msgstr "" #: apps/cmdlineplayer/gmerlin_play.c:717 #, c-format msgid "" "Playing audio stream %d\n" "Input format:\n" "%s\n" "Output format:\n" "%s" msgstr "" #: apps/cmdlineplayer/gmerlin_play.c:732 #, c-format msgid "" "Playing video stream %d\n" "Input format:\n" "%s\n" "Output format:\n" "%s" msgstr "" #: apps/cmdlineplayer/gmerlin_play.c:759 msgid "Player cleaned up" msgstr "" #: apps/cmdlineplayer/gmerlin_play.c:776 msgid "Player now playing" msgstr "" #: apps/cmdlineplayer/gmerlin_play.c:780 msgid "Player now seeking" msgstr "" #: apps/cmdlineplayer/gmerlin_play.c:784 msgid "Player now changing" msgstr "" #: apps/cmdlineplayer/gmerlin_play.c:836 msgid "[options] gml...\n" msgstr "" #: apps/cmdlineplayer/gmerlin_play.c:837 msgid "Commandline Multimedia player\n" msgstr "" #: apps/kbd/kbd_daemon.c:97 #, c-format msgid "Grabbing key (Code: %d, modifiers: %s) failed" msgstr "" #: apps/kbd/kbd_daemon.c:132 msgid "Exiting" msgstr "" #: apps/kbd/kbd_daemon.c:200 #, c-format msgid "State %02x -> %02x\n" msgstr "" #: apps/kbd/kbd_daemon.c:239 msgid "Reloaded keys" msgstr "" #: apps/kbd/kbd_config.c:190 apps/kbd/kbd_config.c:625 msgid "Edit key" msgstr "" #: apps/kbd/kbd_config.c:196 msgid "Grab key" msgstr "" #: apps/kbd/kbd_config.c:227 apps/kbd/kbd_config.c:647 msgid "Scancode" msgstr "" #: apps/kbd/kbd_config.c:236 apps/kbd/kbd_config.c:656 msgid "Modifiers" msgstr "" #: apps/kbd/kbd_config.c:248 apps/kbd/kbd_config.c:664 msgid "Command" msgstr "" #: apps/kbd/kbd_config.c:507 msgid "Keyboard daemon not found" msgstr "" #: apps/kbd/kbd_config.c:609 msgid "Keyboard daemon configuration" msgstr "" #: apps/kbd/kbd_config.c:616 msgid "Daemon running" msgstr "" #: apps/kbd/kbd_config.c:619 msgid "" "Switch deamon on and off. If you want to start the daemon with each start of " "X, add \"gmerlin_kbd\" to your startup programs" msgstr "" #: apps/kbd/kbd_config.c:623 msgid "Add new key" msgstr "" #: apps/kbd/kbd_config.c:627 msgid "Delete key" msgstr "" #: apps/alsamixer/g_card.c:637 msgid "Card controls" msgstr "" #: apps/alsamixer/g_card.c:642 #, c-format msgid "Controls for %s" msgstr "" #: apps/alsamixer/main.c:33 msgid "" "Could not find any Alsa mixers.\n" "Check your setup!\n" msgstr "" #: apps/alsamixer/card.c:36 msgid "snd_hctl_elem_read failed" msgstr "" #: apps/alsamixer/card.c:47 msgid "snd_hctl_elem_write failed" msgstr "" #: apps/alsamixer/card.c:117 msgid "snd_hctl_open failed" msgstr "" #: apps/alsamixer/card.c:122 msgid "snd_hctl_load failed" msgstr "" #: apps/alsamixer/card.c:130 msgid "snd_ctl_card_info_malloc failed" msgstr "" #: apps/alsamixer/card.c:135 msgid "snd_ctl_card_info failed" msgstr "" #: apps/alsamixer/card.c:235 msgid "Unknown" msgstr "" #: apps/alsamixer/g_control.c:863 msgid "Tone" msgstr "" #: apps/alsamixer/g_control.c:894 msgid "Treble" msgstr "" #: apps/alsamixer/g_control.c:924 msgid "Bass" msgstr "" #: apps/alsamixer/g_control.c:1011 msgid "Rec" msgstr "" #: apps/alsamixer/g_control.c:1057 msgid "Play" msgstr "" #: apps/alsamixer/g_control.c:1405 #, c-format msgid "Type %s not handled for %s" msgstr "" #: apps/nmjedit/file.c:59 #, c-format msgid "Opening directory %s failed: %s" msgstr "" #: apps/nmjedit/bgalbum.c:51 tests/album2pls.c:75 lib/mediafiledevice.c:229 #, c-format msgid "Album file %s could not be opened" msgstr "" #: apps/nmjedit/bgalbum.c:60 tests/album2pls.c:85 lib/mediafiledevice.c:238 #, c-format msgid "Album file %s contains no entries" msgstr "" #: apps/nmjedit/bgalbum.c:71 #, c-format msgid "No directory found for location %s" msgstr "" #: apps/nmjedit/bgalbum.c:93 #, c-format msgid "Clearing existent playlist %s" msgstr "" #: apps/nmjedit/bgalbum.c:149 #, c-format msgid "Song %s not found" msgstr "" #: apps/nmjedit/nmjedit.c:47 #, c-format msgid "SQL query: \"%s\" failed: %s" msgstr "" #: apps/nmjedit/nmjedit.c:431 #, c-format msgid "Adding %s" msgstr "" #: apps/nmjedit/nmjedit.c:437 apps/nmjedit/nmjedit.c:488 #, c-format msgid "Scanned %d files" msgstr "" #: apps/nmjedit/nmjedit.c:484 #, c-format msgid "Updating %s" msgstr "" #: apps/nmjedit/nmjedit.c:500 #, c-format msgid "Found %d files in database" msgstr "" #: apps/nmjedit/nmjedit.c:571 #, c-format msgid "Directory %s exists" msgstr "" #: apps/nmjedit/nmjedit.c:576 apps/nmjedit/nmjedit.c:601 #, c-format msgid "Directory %s doesn't exist" msgstr "" #: apps/nmjedit/nmjedit.c:697 apps/thumbnailer/gmerlin-video-thumbnailer.c:266 #, c-format msgid "No plugin for %s" msgstr "" #: apps/nmjedit/nmjedit.c:705 apps/thumbnailer/gmerlin-video-thumbnailer.c:274 #: lib/tree.c:1120 lib/transcoder_track.c:820 lib/transcoder_track.c:831 #: lib/album.c:2270 #, c-format msgid "Loading %s failed" msgstr "" #: apps/nmjedit/nmjedit.c:714 apps/thumbnailer/gmerlin-video-thumbnailer.c:375 msgid "Writing image header failed" msgstr "" #: apps/nmjedit/nmjedit.c:729 apps/nmjedit/nmjedit.c:738 #: apps/thumbnailer/gmerlin-video-thumbnailer.c:393 #: apps/thumbnailer/gmerlin-video-thumbnailer.c:403 msgid "Writing image failed" msgstr "" #: apps/nmjedit/nmjedit.c:863 #, c-format msgid "Removing empty genre %s" msgstr "" #: apps/nmjedit/nmjedit.c:898 #, c-format msgid "Removing empty person %s" msgstr "" #: apps/nmjedit/dir.c:115 msgid "Either ID or path must be set in directory\n" msgstr "" #: apps/nmjedit/song.c:150 msgid "Either ID or path must be set in directory" msgstr "" #: apps/nmjedit/song.c:286 #, c-format msgid "Adding song %s" msgstr "" #: apps/nmjedit/song.c:442 #, c-format msgid "Deleting song %s" msgstr "" #: apps/nmjedit/album.c:129 #, c-format msgid "Adding album %s" msgstr "" #: apps/nmjedit/album.c:205 #, c-format msgid "Using thumbnail %s" msgstr "" #: apps/nmjedit/album.c:302 #, c-format msgid "Removing empty album %s" msgstr "" #: apps/nmjedit/album.c:318 #, c-format msgid "Removing thumbnail %s" msgstr "" #: apps/nmjedit/album.c:325 #, c-format msgid "Removing poster %s" msgstr "" #: apps/nmjedit/gmerlin-nmjedit.c:169 msgid "Editor for NMJ2 databases\n" msgstr "" #: apps/recorder/recorder_window.c:502 msgid "Error, check messages and settings" msgstr "" #: apps/recorder/recorder_window.c:620 msgid "Reopen inputs" msgstr "" #: apps/recorder/recorder_window.c:624 msgid "Make snapshot" msgstr "" #: apps/recorder/recorder_window.c:631 msgid "Hide controls" msgstr "" #: apps/recorder/recorder_window.c:717 msgid "Recorder configuration" msgstr "" #: apps/recorder/recorder_window.c:767 msgid "Snapshots" msgstr "" #: apps/thumbnailer/gmerlin-video-thumbnailer.c:46 msgid "Option -s requires an argument" msgstr "" #: apps/thumbnailer/gmerlin-video-thumbnailer.c:58 msgid "Option -t requires an argument" msgstr "" #: apps/thumbnailer/gmerlin-video-thumbnailer.c:92 msgid "[options] video_file thumbnail_file...\n" msgstr "" #: apps/thumbnailer/gmerlin-video-thumbnailer.c:93 msgid "Video thumbnailer\n" msgstr "" #: apps/thumbnailer/gmerlin-video-thumbnailer.c:158 msgid "No input files given" msgstr "" #: apps/thumbnailer/gmerlin-video-thumbnailer.c:169 #, c-format msgid "Cannot stat %s" msgstr "" #: apps/thumbnailer/gmerlin-video-thumbnailer.c:200 #, c-format msgid "%s has no tracks" msgstr "" #: apps/thumbnailer/gmerlin-video-thumbnailer.c:214 #, c-format msgid "File %s has no video" msgstr "" #: apps/thumbnailer/gmerlin-video-thumbnailer.c:317 msgid "Cannot reset stream after failed seek" msgstr "" #: apps/thumbnailer/gmerlin-video-thumbnailer.c:344 msgid "Couldn't read frame" msgstr "" #: apps/thumbnailer/gmerlin-video-thumbnailer.c:416 #, c-format msgid "Successfully saved %s" msgstr "" #: tests/imgconvert.c:95 msgid "[-co options] input_image output_image\n" msgstr "" #: tests/imgconvert.c:96 msgid "Image converter\n" msgstr "" #: tests/fvtest.c:173 msgid "[options] infile outimage\n" msgstr "" #: tests/fvtest.c:174 msgid "Test tool for video filters\n" msgstr "" #: tests/cfgtest.c:622 msgid "[Options]" msgstr "" #: tests/cfgtest.c:623 msgid "Configure test\n" msgstr "" #: tests/visualization.c:76 msgid "[]\n" msgstr "" #: tests/visualization.c:77 msgid "Visualize test\n" msgstr "" #: tests/visualization.c:127 msgid "No input plugin defined" msgstr "" #: tests/visualization.c:134 msgid "Input plugin could not be loaded" msgstr "" #: tests/visualization.c:144 msgid "No output plugin defined" msgstr "" #: tests/visualization.c:151 msgid "Output plugin could not be loaded" msgstr "" #: tests/visualization.c:168 msgid "Opening input plugin failed" msgstr "" #: tests/gmerlin_visualize.c:154 msgid "No encoder plugin present" msgstr "" #: tests/gmerlin_visualize.c:160 #, c-format msgid "Cannot load plugin %s" msgstr "" #: tests/gmerlin_visualize.c:169 #, c-format msgid "Opening %s failed" msgstr "" #: tests/gmerlin_visualize.c:208 #, c-format msgid "Starting %s failed" msgstr "" #: tests/gmerlin_visualize.c:342 msgid "[-w width -h height -fps num:den] infile out_base\n" msgstr "" #: tests/gmerlin_visualize.c:343 msgid "Visualize audio files and save as A/V files\n" msgstr "" #: tests/gmerlin_visualize.c:481 #, c-format msgid "Opened %s" msgstr "" #: tests/gmerlin_visualize.c:517 msgid "Cannot open encoder" msgstr "" #: lib/recorder_video.c:51 #, c-format msgid "Won't save snapshot %s (file exists)" msgstr "" #: lib/recorder_video.c:55 #, c-format msgid "Saving snapshot %s" msgstr "" #: lib/recorder_video.c:154 msgid "Record video" msgstr "" #: lib/recorder_video.c:166 msgid "Limit fps" msgstr "" #: lib/recorder_video.c:170 msgid "" "Limit frames per second. By default, the maximum possible framerate will be " "used." msgstr "" #: lib/recorder_video.c:175 msgid "fps limit" msgstr "" #: lib/recorder_video.c:181 msgid "" "Specify the maximum framerate for input plugins, which can capture images " "really fast" msgstr "" #: lib/recorder_video.c:278 msgid "Enable monitor" msgstr "" #: lib/recorder_video.c:369 msgid "Automatic" msgstr "" #: lib/recorder_video.c:374 msgid "Snapshot interval" msgstr "" #: lib/recorder_video.c:383 msgid "Overwrite existing files" msgstr "" #: lib/recorder_video.c:710 lib/recorder_audio.c:236 msgid "Read failed (device unplugged?)" msgstr "" #: lib/bggavl.c:393 lib/bggavl.c:411 #, c-format msgid "Unknown scale mode %s\n" msgstr "" #: lib/player_subtitle.c:122 lib/transcoder_track.c:324 msgid "Time offset" msgstr "" #: lib/transcoder_pp.c:209 #, c-format msgid "Not adding %s: Unsupported filename" msgstr "" #: lib/transcoder_pp.c:218 #, c-format msgid "Scheduling %s for postprocessing" msgstr "" #: lib/transcoder_pp.c:236 msgid "Skipping postprocessing (no suitable files found)" msgstr "" #: lib/player_video.c:143 msgid "Still image framerate" msgstr "" #: lib/player_video.c:149 msgid "Set framerate with which still images will be redisplayed periodically" msgstr "" #: lib/player_video.c:199 msgid "Restarting playback due to changed video options" msgstr "" #: lib/player_video.c:278 lib/player_loop.c:1123 lib/player_audio.c:320 msgid "Detected EOF" msgstr "" #: lib/preset.c:290 msgid "Cannot make new preset: No home directory" msgstr "" #: lib/preset.c:307 #, c-format msgid "Could not create directory: %s" msgstr "" #: lib/bgladspa.c:196 msgid "Add effect to input data" msgstr "" #: lib/bgladspa.c:206 msgid "Add gain (dB)" msgstr "" #: lib/bgladspa.c:214 msgid "" "Overall gain for this filter. This is only valid if you add the effect to " "the input data" msgstr "" #: lib/bgladspa.c:264 #, c-format msgid "" "ladspa plugin\n" "Author:\t%s\n" "Copyright:\t%s" msgstr "" #: lib/bgladspa.c:295 lib/bgladspa.c:673 #, c-format msgid "No symbol \"ladspa_descriptor\" found: %s" msgstr "" #: lib/bgladspa.c:390 #, c-format msgid "Remixing to stereo for filter \"%s\"" msgstr "" #: lib/searchpath.c:154 #, c-format msgid "Creating directory %s failed: %s" msgstr "" #: lib/searchpath.c:160 lib/transcoder.c:1882 #, c-format msgid "Created directory %s" msgstr "" #: lib/pluginregistry.c:626 lib/pluginregistry.c:1571 #, c-format msgid "Plugin %s has no or wrong version" msgstr "" #: lib/pluginregistry.c:632 #, c-format msgid "No symbol the_plugin in %s" msgstr "" #: lib/pluginregistry.c:636 #, c-format msgid "Plugin %s has zero priority" msgstr "" #: lib/pluginregistry.c:647 #, c-format msgid "Not loading %s (blacklisted)" msgstr "" #: lib/pluginregistry.c:749 lib/pluginregistry.c:1560 #, c-format msgid "dlopen failed for %s: %s" msgstr "" #: lib/pluginregistry.c:1343 #, c-format msgid "bg_plugin_ref %s: %d" msgstr "" #: lib/pluginregistry.c:1407 #, c-format msgid "bg_plugin_unref_nolock %s: %d" msgstr "" #: lib/pluginregistry.c:1418 #, c-format msgid "bg_plugin_unref %s: %d" msgstr "" #: lib/pluginregistry.c:1443 lib/pluginregistry.c:1497 #, c-format msgid "No plugin found for image %s" msgstr "" #: lib/pluginregistry.c:1578 #, c-format msgid "dlsym failed for %s: %s" msgstr "" #: lib/pluginregistry.c:1666 msgid "Invalid plugin type for video output" msgstr "" #: lib/pluginregistry.c:1673 #, c-format msgid "Plugin %s doesn't support embedded windows" msgstr "" #: lib/pluginregistry.c:1921 #, c-format msgid "Loading plugin \"%s\" failed" msgstr "" #: lib/pluginregistry.c:1933 lib/pluginregistry.c:1970 #, c-format msgid "Opening %s with \"%s\" failed" msgstr "" #: lib/pluginregistry.c:2147 lib/pluginregistry.c:2630 msgid "Overlay subtitles" msgstr "" #: lib/pluginregistry.c:2302 msgid "Registry settings" msgstr "" #: lib/pluginregistry.c:2309 msgid "Plugin settings" msgstr "" #: lib/pluginregistry.c:2316 lib/gtk/plugin_multi.c:402 msgid "Extensions" msgstr "" #: lib/pluginregistry.c:2323 lib/gtk/plugin_multi.c:394 msgid "Protocols" msgstr "" #: lib/pluginregistry.c:2330 lib/gtk/plugin_multi.c:384 msgid "Priority" msgstr "" #: lib/pluginregistry.c:2588 msgid "Write audio stream to video file if possible" msgstr "" #: lib/pluginregistry.c:2595 msgid "Write text subtitles to video file if possible" msgstr "" #: lib/pluginregistry.c:2602 msgid "Write overlay subtitles to video file if possible" msgstr "" #: lib/visualize_slave.c:298 #, c-format msgid "Cannot dlopen plugin module %s: %s" msgstr "" #: lib/visualize_slave.c:307 #, c-format msgid "cannot get API version: %s" msgstr "" #: lib/visualize_slave.c:313 #, c-format msgid "Wrong API version: Got %d expected %d" msgstr "" #: lib/visualize_slave.c:321 #, c-format msgid "No symbol the_plugin: %s" msgstr "" #: lib/visualize_slave.c:431 msgid "No window ID given" msgstr "" #: lib/visualize_slave.c:436 msgid "No plugin given" msgstr "" #: lib/visualize_slave.c:674 msgid "Joined thread" msgstr "" #: lib/visualize_slave.c:693 msgid "Started thread" msgstr "" #: lib/visualize_slave.c:929 msgid "Starting visualization failed" msgstr "" #: lib/visualize.c:110 lib/visualize.c:130 lib/visualize.c:597 msgid "Visualization process crashed, restart to try again" msgstr "" #: lib/visualize.c:336 msgid "Width" msgstr "" #: lib/visualize.c:342 msgid "" "Desired image with, the visualization plugin might override this for no " "apparent reason" msgstr "" #: lib/visualize.c:346 msgid "Height" msgstr "" #: lib/visualize.c:352 msgid "" "Desired image height, the visualization plugin might override this for no " "apparent reason" msgstr "" #: lib/visualize.c:366 msgid "Gain" msgstr "" #: lib/visualize.c:373 msgid "" "Gain (in dB) to apply to the audio samples before it is sent to the " "visualization plugin" msgstr "" #: lib/visualize.c:392 #, c-format msgid "Got visualization plugin %s" msgstr "" #: lib/thumbnail.c:134 lib/bgxml.c:77 #, c-format msgid "Cannot stat %s: %s" msgstr "" #: lib/thumbnail.c:143 msgid "Cannot get home directory" msgstr "" #: lib/formats.c:33 msgid "Zero" msgstr "" #: lib/formats.c:63 #, c-format msgid "" "Channels: %d\n" "Channel order: %s\n" "Samplerate: %d\n" "Samples per frame: %d\n" "Interleave Mode: %s\n" "Sample format: %s" msgstr "" #: lib/formats.c:65 #, c-format msgid "" "Channels:\t %d\n" "Channel order\t %s\n" "Samplerate:\t %d\n" "Samples per frame:\t %d\n" "Interleave Mode:\t %s\n" "Sample format:\t %s" msgstr "" #: lib/formats.c:85 #, c-format msgid "" "Frame size: %d x %d\n" "Image size: %d x %d\n" "Pixel size: %d x %d\n" "Pixel format: %s\n" msgstr "" #: lib/formats.c:87 #, c-format msgid "" "Frame size:\t %d x %d\n" "Image size:\t %d x %d\n" "Pixel size:\t %d x %d\n" "Pixel format:\t %s\n" msgstr "" #: lib/formats.c:98 msgid "Still image\n" msgstr "" #: lib/formats.c:104 #, c-format msgid "Framerate: Variable (timescale: %d)\n" msgstr "" #: lib/formats.c:106 #, c-format msgid "Framerate:\tVariable (timescale: %d)\n" msgstr "" #: lib/formats.c:115 #, c-format msgid "Framerate: %f fps [%d / %d]%s\n" msgstr "" #: lib/formats.c:117 #, c-format msgid "Framerate:\t%f fps [%d / %d]%s\n" msgstr "" #: lib/formats.c:123 msgid " (constant)" msgstr "" #: lib/formats.c:124 msgid " (variable)" msgstr "" #: lib/formats.c:130 #, c-format msgid "Interlace mode: %s" msgstr "" #: lib/formats.c:132 #, c-format msgid "Interlace mode:\t%s" msgstr "" #: lib/formats.c:143 #, c-format msgid "" "\n" "Chroma placement: %s" msgstr "" #: lib/formats.c:145 #, c-format msgid "" "\n" "Chroma placement:\t%s" msgstr "" #: lib/formats.c:154 #, c-format msgid "" "\n" "Timecode rate: %d" msgstr "" #: lib/formats.c:156 #, c-format msgid "" "\n" "Timecode rate:\t%d" msgstr "" #: lib/formats.c:164 msgid "" "\n" "Timecode flags: " msgstr "" #: lib/formats.c:166 msgid "" "\n" "Timecode flags:\t" msgstr "" #: lib/formats.c:171 msgid "Drop " msgstr "" #: lib/formats.c:184 msgid "Unknown channel" msgstr "" #: lib/formats.c:185 msgid "Front C" msgstr "" #: lib/formats.c:186 msgid "Front L" msgstr "" #: lib/formats.c:187 msgid "Front R" msgstr "" #: lib/formats.c:188 msgid "Front CL" msgstr "" #: lib/formats.c:189 msgid "Front CR" msgstr "" #: lib/formats.c:190 msgid "Rear C" msgstr "" #: lib/formats.c:191 msgid "Rear L" msgstr "" #: lib/formats.c:192 msgid "Rear R" msgstr "" #: lib/formats.c:193 msgid "Side L" msgstr "" #: lib/formats.c:194 msgid "Side R" msgstr "" #: lib/formats.c:196 msgid "AUX" msgstr "" #: lib/formats.c:200 msgid "Not specified" msgstr "" #: lib/formats.c:201 msgid "Unsigned 8 bit" msgstr "" #: lib/formats.c:202 msgid "Signed 8 bit" msgstr "" #: lib/formats.c:203 msgid "Unsigned 16 bit" msgstr "" #: lib/formats.c:204 msgid "Signed 16 bit" msgstr "" #: lib/formats.c:205 msgid "Signed 32 bit" msgstr "" #: lib/formats.c:206 msgid "Floating point" msgstr "" #: lib/formats.c:207 msgid "Double precision" msgstr "" #: lib/formats.c:210 msgid "Not interleaved" msgstr "" #: lib/formats.c:211 msgid "Interleaved channel pairs" msgstr "" #: lib/formats.c:212 msgid "All channels interleaved" msgstr "" #: lib/formats.c:216 msgid "None (Progressive)" msgstr "" #: lib/formats.c:217 msgid "Top field first" msgstr "" #: lib/formats.c:218 msgid "Bottom field first" msgstr "" #: lib/formats.c:219 msgid "Mixed" msgstr "" #: lib/formats.c:222 msgid "MPEG-1/JPEG" msgstr "" #: lib/formats.c:223 msgid "MPEG-2" msgstr "" #: lib/formats.c:224 msgid "DV PAL" msgstr "" #: lib/formats.c:228 msgid "15 bpp RGB" msgstr "" #: lib/formats.c:229 msgid "15 bpp BGR" msgstr "" #: lib/formats.c:230 msgid "16 bpp RGB" msgstr "" #: lib/formats.c:231 msgid "16 bpp BGR" msgstr "" #: lib/formats.c:232 msgid "24 bpp RGB" msgstr "" #: lib/formats.c:233 msgid "24 bpp BGR" msgstr "" #: lib/formats.c:234 msgid "32 bpp RGB" msgstr "" #: lib/formats.c:235 msgid "32 bpp BGR" msgstr "" #: lib/formats.c:236 msgid "32 bpp RGBA" msgstr "" #: lib/formats.c:237 msgid "48 bpp RGB" msgstr "" #: lib/formats.c:238 msgid "64 bpp RGBA" msgstr "" #: lib/formats.c:239 msgid "Float RGB" msgstr "" #: lib/formats.c:240 msgid "Float RGBA" msgstr "" #: lib/formats.c:241 msgid "YUV 422 (YUY2)" msgstr "" #: lib/formats.c:242 msgid "YUV 422 (UYVY)" msgstr "" #: lib/formats.c:243 msgid "YUVA 4444" msgstr "" #: lib/formats.c:244 msgid "YUV 420 Planar" msgstr "" #: lib/formats.c:245 msgid "YUV 410 Planar" msgstr "" #: lib/formats.c:246 msgid "YUV 411 Planar" msgstr "" #: lib/formats.c:247 msgid "YUV 422 Planar" msgstr "" #: lib/formats.c:248 msgid "YUV 422 Planar (16 bit)" msgstr "" #: lib/formats.c:249 msgid "YUV 444 Planar" msgstr "" #: lib/formats.c:250 msgid "YUV 444 Planar (16 bit)" msgstr "" #: lib/formats.c:251 msgid "YUVJ 420 Planar" msgstr "" #: lib/formats.c:252 msgid "YUVJ 422 Planar" msgstr "" #: lib/formats.c:253 msgid "YUVJ 444 Planar" msgstr "" #: lib/formats.c:254 msgid "Undefined" msgstr "" #: lib/cmdline.c:221 msgid "Copyright (C) 2001-2007 Members of the gmerlin project\n" msgstr "" #: lib/cmdline.c:222 msgid "" "This is free software. You may redistribute copies of it under the terms " "of\n" "the GNU General Public License .\n" "There is NO WARRANTY.\n" msgstr "" #: lib/cmdline.c:290 msgid "Print this help message and exit" msgstr "" #: lib/cmdline.c:295 msgid "Print this help message as a manual page and exit" msgstr "" #: lib/cmdline.c:300 msgid "Print this help message in texinfo format and exit" msgstr "" #: lib/cmdline.c:305 msgid "Print version info and exit" msgstr "" #: lib/cmdline.c:338 msgid "" "Environment variables\n" "\n" msgstr "" #: lib/cmdline.c:352 msgid "" "Files\n" "\n" msgstr "" #: lib/cmdline.c:416 msgid ".SH ENVIRONMENT VARIABLES\n" msgstr "" #: lib/cmdline.c:431 msgid ".SH FILES\n" msgstr "" #: lib/cmdline.c:470 msgid "@item Environment variables\n" msgstr "" #: lib/cmdline.c:484 msgid "@item Files\n" msgstr "" #: lib/cmdline.c:697 msgid "" "Supported options:\n" "\n" msgstr "" #: lib/cmdline.c:777 #, c-format msgid "[1|0] (default: %d)" msgstr "" #: lib/cmdline.c:786 lib/cmdline.c:800 msgid " (" msgstr "" #: lib/cmdline.c:792 #, c-format msgid "default: %d)" msgstr "" #: lib/cmdline.c:811 #, c-format msgid "default: %%.%df)" msgstr "" #: lib/cmdline.c:827 lib/cmdline.c:840 lib/cmdline.c:847 msgid "" msgstr "" #: lib/cmdline.c:830 #, c-format msgid " (Default: %s)" msgstr "" #: lib/cmdline.c:857 msgid "Supported strings: " msgstr "" #: lib/cmdline.c:879 lib/cmdline.c:960 #, c-format msgid "Default: %s" msgstr "" #: lib/cmdline.c:886 #, c-format msgid ",, (default: %.3f,%.3f,%.3f)" msgstr "" #: lib/cmdline.c:897 lib/cmdline.c:1029 msgid ", and are in the range 0.0..1.0" msgstr "" #: lib/cmdline.c:904 #, c-format msgid ",,, (default: %.3f,%.3f,%.3f,%.3f)" msgstr "" #: lib/cmdline.c:916 msgid ", , and are in the range 0.0..1.0" msgstr "" #: lib/cmdline.c:923 msgid "option[{suboptions}]" msgstr "" #: lib/cmdline.c:932 lib/cmdline.c:978 msgid "Supported options: " msgstr "" #: lib/cmdline.c:954 msgid "" msgstr "" #: lib/cmdline.c:966 msgid "{option[{suboptions}][:option[{suboptions}]...]}" msgstr "" #: lib/cmdline.c:998 msgid "{[[HH:]MM:]SS} (" msgstr "" #: lib/cmdline.c:1008 #, c-format msgid "default: %s)" msgstr "" #: lib/cmdline.c:1016 msgid "Seconds can be fractional (i.e. with decimal point)\n" msgstr "" #: lib/cmdline.c:1019 #, c-format msgid ", (default: %.3f,%.3f)" msgstr "" #: lib/cmdline.c:1068 lib/cmdline.c:1071 #, c-format msgid "Suboptions for %s=%s" msgstr "" #: lib/cmdline.c:1076 #, c-format msgid "Suboptions for %s" msgstr "" #: lib/ov.c:181 #, c-format msgid "Using hardeware overlay for stream %d" msgstr "" #: lib/ov.c:190 #, c-format msgid "Using software overlay for stream %d" msgstr "" #: lib/converters.c:331 lib/converters.c:338 msgid "variable" msgstr "" #: lib/converters.c:344 #, c-format msgid "Doing framerate conversion %s -> %s" msgstr "" #: lib/converters.c:373 #, c-format msgid "Initialized video converter, %d steps" msgstr "" #: lib/mediafiledevice.c:116 lib/metadata.c:59 msgid "Album" msgstr "" #: lib/mediafiledevice.c:121 msgid "Shuffle" msgstr "" #: lib/mediafiledevice.c:222 msgid "No album file given" msgstr "" #: lib/mediafiledevice.c:259 #, c-format msgid "Album file %s contains no usable entries" msgstr "" #: lib/mediafiledevice.c:295 msgid "Reloading album (file changed)" msgstr "" #: lib/mediafiledevice.c:488 msgid "Audiofile recorder" msgstr "" #: lib/mediafiledevice.c:489 msgid "" "Take a bunch of audio file and make them available as a recording device" msgstr "" #: lib/lcdproc.c:106 msgid "Enable LCDproc" msgstr "" #: lib/lcdproc.c:112 msgid "Hostname" msgstr "" #: lib/lcdproc.c:126 msgid "Display track name and time" msgstr "" #: lib/lcdproc.c:132 msgid "Display audio/video formats" msgstr "" #: lib/lcdproc.c:138 msgid "Display audio/video descriptions" msgstr "" #: lib/lcdproc.c:165 lib/lcdproc.c:170 msgid "Sending command failed" msgstr "" #: lib/lcdproc.c:193 #, c-format msgid "Command \"%s\" not unserstood by server" msgstr "" #: lib/lcdproc.c:214 #, c-format msgid "Could not resolve adress for: %s" msgstr "" #: lib/lcdproc.c:221 #, c-format msgid "Could not connect to server at %s:%d" msgstr "" #: lib/lcdproc.c:231 msgid "Could not send hello message" msgstr "" #: lib/lcdproc.c:237 msgid "Could not get server welcome line" msgstr "" #: lib/lcdproc.c:246 #, c-format msgid "Invalid answer: %s" msgstr "" #: lib/lcdproc.c:278 #, c-format msgid "Connection to server established, display size: %dx%d" msgstr "" #: lib/lcdproc.c:290 lib/lcdproc.c:837 msgid "Connection to server closed due to error" msgstr "" #: lib/lcdproc.c:931 msgid "Server connection closed" msgstr "" #: lib/player_loop.c:291 msgid "Cannot pause live stream" msgstr "" #: lib/player_loop.c:1200 msgid "Ignoring command while playback is interrupted" msgstr "" #: lib/charset.c:97 msgid "Invalid Multibyte sequence" msgstr "" #: lib/charset.c:101 msgid "Incomplete Multibyte sequence" msgstr "" #: lib/transcoder.c:507 #, c-format msgid "Transcoding took %s (%.2f %% of realtime duration)" msgstr "" #: lib/transcoder.c:517 msgid "Output Directory" msgstr "" #: lib/transcoder.c:523 msgid "Delete incomplete output files" msgstr "" #: lib/transcoder.c:526 msgid "" "Delete the encoded files if you hit the stop button. This option will " "automatically be disabled, when the track is an URL" msgstr "" #: lib/transcoder.c:531 msgid "Clean up after postprocessing" msgstr "" #: lib/transcoder.c:533 msgid "Clean up all encoded files, which were postprocessed" msgstr "" #: lib/transcoder.c:537 msgid "Send finished files to player" msgstr "" #: lib/transcoder.c:1212 #, c-format msgid "Using statistics file: %s" msgstr "" #: lib/transcoder.c:1347 msgid "Encoding audio failed" msgstr "" #: lib/transcoder.c:1666 msgid "Encoding video failed" msgstr "" #: lib/transcoder.c:1756 lib/transcoder.c:1809 msgid "Encoding subtitles failed" msgstr "" #: lib/transcoder.c:1876 #, c-format msgid "Cannot create directory %s: %s, using default" msgstr "" #: lib/transcoder.c:1933 #, c-format msgid "Postprocessing %s" msgstr "" #: lib/transcoder.c:1937 lib/transcoder.c:3184 #, c-format msgid "Transcoding %s [Track %d, Pass %d/%d]" msgstr "" #: lib/transcoder.c:1942 #, c-format msgid "Transcoding %s [Track %d]" msgstr "" #: lib/transcoder.c:1953 #, c-format msgid "" "Metadata:\n" "%s" msgstr "" #: lib/transcoder.c:1970 #, c-format msgid "" "Audio stream %d input format:\n" "%s" msgstr "" #: lib/transcoder.c:1976 #, c-format msgid "" "Audio stream %d output format:\n" "%s" msgstr "" #: lib/transcoder.c:1984 #, c-format msgid "" "Audio stream %d format:\n" "%s" msgstr "" #: lib/transcoder.c:1999 #, c-format msgid "" "Video stream %d input format:\n" "%s" msgstr "" #: lib/transcoder.c:2004 #, c-format msgid "" "Video stream %d output format:\n" "%s" msgstr "" #: lib/transcoder.c:2011 #, c-format msgid "" "Video stream %d format:\n" "%s" msgstr "" #: lib/transcoder.c:2023 #, c-format msgid "Text subtitle stream %d: Blending onto video stream %d" msgstr "" #: lib/transcoder.c:2028 #, c-format msgid "Text subtitle stream %d: Exporting to file" msgstr "" #: lib/transcoder.c:2042 #, c-format msgid "Overlay subtitle stream %d: Blending onto video stream %d" msgstr "" #: lib/transcoder.c:2047 #, c-format msgid "Overlay subtitle stream %d: Exporting to file" msgstr "" #: lib/transcoder.c:2093 #, c-format msgid "Cannot find plugin %s" msgstr "" #: lib/transcoder.c:2124 #, c-format msgid "Invalid track number %d" msgstr "" #: lib/transcoder.c:2154 #, c-format msgid "Audio stream %d cannot be read compressed" msgstr "" #: lib/transcoder.c:2164 #, c-format msgid "Audio stream %d cannot be written compressed" msgstr "" #: lib/transcoder.c:2169 #, c-format msgid "Copying compressed audio stream %d" msgstr "" #: lib/transcoder.c:2183 #, c-format msgid "Video stream %d cannot be read compressed" msgstr "" #: lib/transcoder.c:2195 lib/transcoder.c:2210 #, c-format msgid "Not copying video stream %d: Will blend subtitles" msgstr "" #: lib/transcoder.c:2223 #, c-format msgid "Video stream %d cannot be written compressed" msgstr "" #: lib/transcoder.c:2228 #, c-format msgid "Copying compressed video stream %d" msgstr "" #: lib/transcoder.c:2351 lib/player_input.c:219 msgid "Starting input plugin failed" msgstr "" #: lib/transcoder.c:2361 lib/transcoder.c:2370 msgid "Cannot seek to start point" msgstr "" #: lib/transcoder.c:2381 msgid "End time if before start time" msgstr "" #: lib/transcoder.c:2543 lib/transcoder.c:2591 msgid "Subtitle stream cannot be handled" msgstr "" #: lib/transcoder.c:2612 msgid "Input and output are the same file" msgstr "" #: lib/transcoder.c:2924 msgid "Zero peaks detected (silent file?). Disabling normalization." msgstr "" #: lib/transcoder.c:2930 #, c-format msgid "Correcting volume by %.2f dB" msgstr "" #: lib/transcoder.c:2989 msgid "No stream to encode" msgstr "" #: lib/transcoder.c:3393 #, c-format msgid "Video stream %d: Transcoded %s frames" msgstr "" #: lib/transcoder.c:3404 #, c-format msgid "Audio stream %d: Transcoded %s samples" msgstr "" #: lib/x11/xvideo.c:120 #, c-format msgid "Visual and depth not supported by adaptor %d" msgstr "" #: lib/x11/xvideo.c:253 msgid "Image width out of range" msgstr "" #: lib/x11/xvideo.c:258 msgid "Image height out of range" msgstr "" #: lib/x11/xvideo.c:268 #, c-format msgid "Using XV format: %c%c%c%c" msgstr "" #: lib/x11/xvideo.c:280 msgid "No suitable pixelformat" msgstr "" #: lib/x11/xvideo.c:295 #, c-format msgid "Port %li already grabbed, trying next one" msgstr "" #: lib/x11/xvideo.c:300 #, c-format msgid "Grabbing Port %li failed (invalid time), trying next one" msgstr "" #: lib/x11/xvideo.c:305 #, c-format msgid "Grabbing Port %li failed (unknown error)" msgstr "" #: lib/x11/xvideo.c:316 msgid "Could not find free port" msgstr "" #: lib/x11/x11_video.c:233 #, c-format msgid "Trying %s driver" msgstr "" #: lib/x11/x11_video.c:237 #, c-format msgid "Opening %s driver failed" msgstr "" #: lib/x11/x11_video.c:245 #, c-format msgid "Opening %s driver succeeded" msgstr "" #: lib/x11/x11_window.c:1116 msgid "Auto resize window" msgstr "" #: lib/x11/x11_window.c:1150 msgid "Disable Screensaver for normal playback" msgstr "" #: lib/x11/x11_window.c:1156 msgid "Disable Screensaver for fullscreen playback" msgstr "" #: lib/x11/x11_window.c:1162 msgid "Force hardware scaling" msgstr "" #: lib/x11/x11_window.c:1164 msgid "" "Use hardware scaling even if it involves more CPU intensive pixelformat " "conversions" msgstr "" #: lib/x11/x11_window.c:1173 msgid "" "Specify the background color for videos with alpha channel. This is only " "used by the OpenGL driver." msgstr "" #: lib/x11/x11_window.c:1179 msgid "Software scaler" msgstr "" #: lib/x11/x11_window.c:1218 lib/x11/x11_window.c:1223 msgid "Scale quality" msgstr "" #: lib/x11/x11_window.c:1389 msgid "Could not get GL Visual" msgstr "" #: lib/x11/x11_window.c:1404 #, c-format msgid "Got Visual 0x%lx depth %d" msgstr "" #: lib/x11/x11_gl.c:75 msgid "GLX extension missing" msgstr "" #: lib/x11/x11_gl.c:82 #, c-format msgid "GLX version too old: requested >= 1.3 but got %d.%d" msgstr "" #: lib/x11/x11_gl.c:88 #, c-format msgid "Got GLX version %d.%d" msgstr "" #: lib/x11/x11_gl.c:127 msgid "No framebuffer configs found (insufficient driver or hardware)" msgstr "" #: lib/x11/grab.c:57 msgid "Grab from root window" msgstr "" #: lib/x11/grab.c:62 msgid "Draw cursor" msgstr "" #: lib/x11/grab.c:68 msgid "Keep grab window on top" msgstr "" #: lib/x11/grab.c:74 msgid "Make grab window sticky" msgstr "" #: lib/x11/grab.c:80 msgid "Disable screensaver" msgstr "" #: lib/x11/grab.c:83 msgid "Disable screensaver and energy saving mode" msgstr "" #: lib/x11/grab.c:602 #, c-format msgid "Window geometry: %dx%d+%d+%d" msgstr "" #: lib/x11/grab.c:673 msgid "Couldn't get shared memory segment" msgstr "" #: lib/x11/grab.c:681 msgid "Couldn't attach shared memory segment" msgstr "" #: lib/x11/grab.c:687 msgid "Using shared memory for grabbing" msgstr "" #: lib/x11/grab.c:776 #, c-format msgid "Cursor too wide, increase MAX_CURSOR_SIZE in grab.c to %d" msgstr "" #: lib/x11/grab.c:783 #, c-format msgid "Cursor too high, increase MAX_CURSOR_SIZE in grab.c to %d" msgstr "" #: lib/x11/grab.c:903 msgid "XShmGetImage failed" msgstr "" #: lib/x11/shm.c:87 msgid "Cannot create shared memory" msgstr "" #: lib/textrenderer.c:163 msgid "Default format" msgstr "" #: lib/textrenderer.c:168 msgid "Default width" msgstr "" #: lib/textrenderer.c:176 msgid "Default height" msgstr "" #: lib/textrenderer.c:184 msgid "Default Colorspace" msgstr "" #: lib/textrenderer.c:188 msgid "YCrCb" msgstr "" #: lib/textrenderer.c:188 msgid "RGB" msgstr "" #: lib/textrenderer.c:192 msgid "Default Framerate" msgstr "" #: lib/tree.c:252 lib/tree.c:435 msgid "Incoming" msgstr "" #: lib/tree.c:257 lib/tree.c:443 msgid "Favourites" msgstr "" #: lib/tree.c:1086 msgid "Doubleclick on a track first" msgstr "" #: lib/tree.c:1107 #, c-format msgid "Cannot open %s: no plugin found" msgstr "" #: lib/tree.c:1111 #, c-format msgid "Loading %s (plugin: %s)" msgstr "" #: lib/tree.c:1130 #, c-format msgid "Selecting track %d for %s failed" msgstr "" #: lib/tree.c:1169 msgid "Use metadata for track names" msgstr "" #: lib/tree.c:1172 msgid "If disabled, track name will be taken from filename" msgstr "" #: lib/tree.c:1192 msgid "Purge directory on exit" msgstr "" #: lib/tree.c:1195 msgid "" "Purge directory (i.e. delete\n" "unused album files) at program exit" msgstr "" #: lib/tree.c:1200 msgid "Blacklisted extensions" msgstr "" #: lib/tree.c:1203 msgid "File extensions, which are never loaded automatically" msgstr "" #: lib/tree.c:1207 msgid "Blacklisted filenames" msgstr "" #: lib/tree.c:1209 msgid "Filenames, which are never loaded automatically" msgstr "" #: lib/tree.c:1463 #, c-format msgid "Purging %s" msgstr "" #: lib/tree.c:1580 msgid "No current track for copying to favourites" msgstr "" #: lib/singlepic.c:97 msgid "Display time" msgstr "" #: lib/singlepic.c:102 msgid "Time to pass until the next track will be selected. 0 means infinite." msgstr "" #: lib/singlepic.c:327 #, c-format msgid "Plugin %s could not be loaded" msgstr "" #: lib/singlepic.c:594 msgid "Image video input plugin" msgstr "" #: lib/singlepic.c:595 msgid "" "This plugin reads series of images as a video. It uses the installed image " "readers." msgstr "" #: lib/singlepic.c:641 msgid "" "This plugin reads images as stills. It uses the installed image readers." msgstr "" #: lib/singlepic.c:760 msgid "Framenumber digits" msgstr "" #: lib/singlepic.c:768 msgid "Framenumber offset" msgstr "" #: lib/singlepic.c:1037 #, c-format msgid "Couldn't write data to %s: %s" msgstr "" #: lib/singlepic.c:1098 msgid "" "This plugin encodes a video as a series of images. It uses the installed " "image writers." msgstr "" #: lib/metadata.c:38 msgid "Artist" msgstr "" #: lib/metadata.c:45 msgid "Album artist" msgstr "" #: lib/metadata.c:52 msgid "Title" msgstr "" #: lib/metadata.c:66 lib/transcoder_track.c:194 lib/gtk/infowindow.c:782 msgid "Track" msgstr "" #: lib/metadata.c:73 msgid "Genre" msgstr "" #: lib/metadata.c:80 msgid "Author" msgstr "" #: lib/metadata.c:87 msgid "Copyright" msgstr "" #: lib/metadata.c:94 msgid "Year" msgstr "" #: lib/metadata.c:448 #, c-format msgid "%s%s%s\n" msgstr "" #: lib/player_audio.c:246 msgid "Restarting playback due to changed audio options" msgstr "" #: lib/player_audio.c:288 msgid "Restarting playback due to changed audio filters" msgstr "" #: lib/transcoder_track.c:170 lib/gtk/infowindow.c:767 #: lib/gtk/treewidget.c:1123 lib/gtk/chapterdialog.c:185 #: lib/gtk/presetmenu.c:181 msgid "Name" msgstr "" #: lib/transcoder_track.c:176 lib/gtk/infowindow.c:777 msgid "Location" msgstr "" #: lib/transcoder_track.c:188 lib/gtk/fileselect.c:269 msgid "Prefer EDL" msgstr "" #: lib/transcoder_track.c:200 msgid "Subdirectory" msgstr "" #: lib/transcoder_track.c:202 msgid "Subdirectory, where this track will be written to" msgstr "" #: lib/transcoder_track.c:242 msgid "Postprocess only" msgstr "" #: lib/transcoder_track.c:244 msgid "" "Skip transcoding of this track and send the file directly to the " "postprocessor." msgstr "" #: lib/transcoder_track.c:248 msgid "Set start time" msgstr "" #: lib/transcoder_track.c:252 msgid "" "Specify a start time below. This time will be slightly wrong if the input " "format doesn't support sample accurate seeking." msgstr "" #: lib/transcoder_track.c:257 msgid "Start time" msgstr "" #: lib/transcoder_track.c:264 msgid "Set end time" msgstr "" #: lib/transcoder_track.c:268 msgid "Specify an end time below." msgstr "" #: lib/transcoder_track.c:272 msgid "End time" msgstr "" #: lib/transcoder_track.c:286 lib/transcoder_track.c:351 #: lib/transcoder_track.c:1331 lib/transcoder_track.c:1360 msgid "Action" msgstr "" #: lib/transcoder_track.c:294 lib/transcoder_track.c:357 #: lib/transcoder_track.c:1336 lib/transcoder_track.c:1366 msgid "Forget" msgstr "" #: lib/transcoder_track.c:295 msgid "Transcode as text" msgstr "" #: lib/transcoder_track.c:296 msgid "Transcode as overlay" msgstr "" #: lib/transcoder_track.c:297 lib/transcoder_track.c:359 msgid "Blend onto video" msgstr "" #: lib/transcoder_track.c:299 msgid "Select action for this subtitle stream." msgstr "" #: lib/transcoder_track.c:303 lib/transcoder_track.c:365 #: lib/transcoder_track.c:1372 msgid "Input Language" msgstr "" #: lib/transcoder_track.c:309 lib/transcoder_track.c:371 #: lib/transcoder_track.c:1378 lib/recorder_audio.c:99 msgid "Language" msgstr "" #: lib/transcoder_track.c:317 lib/transcoder_track.c:379 #: lib/transcoder_track.c:1386 msgid "Force language" msgstr "" #: lib/transcoder_track.c:320 lib/transcoder_track.c:382 #: lib/transcoder_track.c:1389 msgid "" "Force the given language even if the input has the language set differently." msgstr "" #: lib/transcoder_track.c:333 msgid "Video stream" msgstr "" #: lib/transcoder_track.c:338 msgid "" "Attach subtitle stream to this video stream. For blending, this video stream " "will get the subtitles. For encoding, take frame dimensions and framerate " "from this video stream as they are sometimes needed by subtitle encoders." msgstr "" #: lib/transcoder_track.c:358 lib/transcoder_track.c:1334 #: lib/transcoder_track.c:1364 lib/gtk/albumwidget.c:1543 msgid "Transcode" msgstr "" #: lib/transcoder_track.c:386 msgid "Video stream to blend onto" msgstr "" #: lib/transcoder_track.c:1335 lib/transcoder_track.c:1365 msgid "Copy (if possible)" msgstr "" #: lib/transcoder_track.c:1338 lib/transcoder_track.c:1368 msgid "" "Choose the desired action for the stream. If copying is not possible, the " "stream will be transcoded" msgstr "" #: lib/transcoder_track.c:1343 msgid "Enable 2-pass encoding" msgstr "" #: lib/transcoder_track.c:1345 msgid "" "Encode this stream in 2 passes, i.e. analyze it first and do the final " "transcoding in the second pass. This enables higher quality within the given " "bitrate constraints but roughly doubles the video encoding time." msgstr "" #: lib/transcoder_track.c:1393 msgid "Normalize audio" msgstr "" #: lib/transcoder_track.c:1395 msgid "" "This will enable 2 pass transcoding. In the first pass, the peak volume is " "detected. In the second pass, the stream is transcoded with normalized " "volume." msgstr "" #: lib/osd.c:76 msgid "Enable OSD" msgstr "" #: lib/osd.c:83 msgid "Size" msgstr "" #: lib/osd.c:89 msgid "" "Specify fontsize for OSD. The value you enter, is for an image width of 640. " "For other widths, the value will be scaled" msgstr "" #: lib/osd.c:94 msgid "Foreground color" msgstr "" #: lib/osd.c:160 msgid "Bottom border" msgstr "" #: lib/osd.c:169 msgid "Duration (milliseconds)" msgstr "" #: lib/remote.c:102 msgid "Setting up socket failed, this instance won't be reachable via remote" msgstr "" #: lib/remote.c:107 #, c-format msgid "Remote socket listening at port %d" msgstr "" #: lib/remote.c:127 msgid "Reading hello line failed" msgstr "" #: lib/remote.c:136 lib/remote.c:457 msgid "Protocol mismatch" msgstr "" #: lib/remote.c:187 msgid "Client connection closed" msgstr "" #: lib/remote.c:211 msgid "New client connection" msgstr "" #: lib/remote.c:321 msgid "Allow connections from other machines" msgstr "" #: lib/remote.c:327 msgid "Maximum number of connections" msgstr "" #: lib/remote.c:427 msgid "Connecting failed" msgstr "" #: lib/remote.c:439 msgid "Sending initialization string failed" msgstr "" #: lib/remote.c:448 msgid "Reading welcome line failed" msgstr "" #: lib/player_input.c:267 msgid "Cannot select track, skipping" msgstr "" #: lib/player_input.c:310 msgid "Track has neither audio nor video, skipping" msgstr "" #: lib/player_input.c:351 #, c-format msgid "Audio sample counter: %s" msgstr "" #: lib/player_input.c:356 #, c-format msgid "Video frame counter: %s" msgstr "" #: lib/player_input.c:581 msgid "" "When showing still images, gmerlin repeats them periodically to make " "realtime filter tweaking work." msgstr "" #: lib/player_input.c:591 msgid "" "Use this for playing buggy files, which have a constant offset between audio " "and video. Use positive values if the video is ahead of audio" msgstr "" #: lib/chapterlist.c:134 #, c-format msgid "Chapter %d" msgstr "" #: lib/stringutils.c:181 #, c-format msgid "Cannot open file \"%s\" for writing" msgstr "" #: lib/stringutils.c:595 #, c-format msgid "Stream %d [%s]" msgstr "" #: lib/stringutils.c:597 #, c-format msgid "Stream %d" msgstr "" #: lib/ocr.c:88 #, c-format msgid "Writing image file %s" msgstr "" #: lib/ocr.c:129 msgid "No engine found" msgstr "" #: lib/ocr.c:155 msgid "" "Background color to use, when converting formats with transparency to " "grayscale" msgstr "" #: lib/ocr.c:159 msgid "Temporary directory" msgstr "" #: lib/ocr.c:162 msgid "Temporary directory for image files" msgstr "" #: lib/ocr.c:257 #, c-format msgid "OCR failed, keeping %s" msgstr "" #: lib/socket.c:149 #, c-format msgid "Cannot resolve address of %s: %s" msgstr "" #: lib/socket.c:191 msgid "Cannot create socket" msgstr "" #: lib/socket.c:198 lib/socket.c:380 lib/socket.c:416 msgid "Cannot set nonblocking mode" msgstr "" #: lib/socket.c:216 msgid "Connection timed out" msgstr "" #: lib/socket.c:221 msgid "select() failed on connect" msgstr "" #: lib/socket.c:227 lib/socket.c:239 #, c-format msgid "Connecting failed: %s" msgstr "" #: lib/socket.c:248 msgid "Cannot set blocking mode" msgstr "" #: lib/socket.c:262 msgid "Cannot create unix socket" msgstr "" #: lib/socket.c:273 msgid "Connecting unix socket failed" msgstr "" #: lib/socket.c:305 #, c-format msgid "Cannot resolve address of localhost: %s" msgstr "" #: lib/socket.c:345 msgid "Cannot create inet server socket" msgstr "" #: lib/socket.c:375 #, c-format msgid "Cannot bind inet socket: %s" msgstr "" #: lib/socket.c:385 lib/socket.c:421 msgid "Cannot put socket into listening mode" msgstr "" #: lib/socket.c:401 msgid "Cannot create unix server socket" msgstr "" #: lib/socket.c:411 msgid "Could not bind socket" msgstr "" #: lib/socket.c:478 #, c-format msgid "Sending data failed: %s" msgstr "" #: lib/player_oa.c:122 #, c-format msgid "Got initial audio timestamp: %s" msgstr "" #: lib/album_xml.c:226 #, c-format msgid "Couldn't open album file %s" msgstr "" #: lib/encoder.c:183 #, c-format msgid "Created output file %s" msgstr "" #: lib/encoder.c:199 #, c-format msgid "Created temp file %s\n" msgstr "" #: lib/encoder.c:651 msgid "Multipass encoding not supported by encoder plugin" msgstr "" #: lib/gtk/infowindow.c:516 #, c-format msgid "Name:\t%s" msgstr "" #: lib/gtk/infowindow.c:526 #, c-format msgid "Input plugin:\t%s" msgstr "" #: lib/gtk/infowindow.c:535 #, c-format msgid "Location:\t%s" msgstr "" #: lib/gtk/infowindow.c:543 #, c-format msgid "Track:\t%d" msgstr "" #: lib/gtk/infowindow.c:590 #, c-format msgid "Audio stream %d/%d" msgstr "" #: lib/gtk/infowindow.c:605 #, c-format msgid "Subtitle stream %d/%d [%s]" msgstr "" #: lib/gtk/infowindow.c:620 #, c-format msgid "Video stream %d/%d" msgstr "" #: lib/gtk/infowindow.c:706 lib/gtk/infowindow.c:725 lib/gtk/infowindow.c:744 msgid "Input format" msgstr "" #: lib/gtk/infowindow.c:772 msgid "Input plugin" msgstr "" #: lib/gtk/infowindow.c:1040 msgid "Copy selected" msgstr "" #: lib/gtk/infowindow.c:1042 msgid "Copy all" msgstr "" #: lib/gtk/infowindow.c:1090 msgid "Gmerlin Track Info" msgstr "" #: lib/gtk/treewidget.c:958 msgid "Album name" msgstr "" #: lib/gtk/treewidget.c:966 lib/gtk/treewidget.c:2043 msgid "Rename album" msgstr "" #: lib/gtk/treewidget.c:1130 msgid "Add device" msgstr "" #: lib/gtk/treewidget.c:1344 msgid "Expand all" msgstr "" #: lib/gtk/treewidget.c:1348 msgid "Collapse all" msgstr "" #: lib/gtk/treewidget.c:1352 msgid "Tabbed mode" msgstr "" #: lib/gtk/treewidget.c:1356 msgid "Windowed mode" msgstr "" #: lib/gtk/treewidget.c:1366 msgid "Open" msgstr "" #: lib/gtk/treewidget.c:1370 msgid "Close" msgstr "" #: lib/gtk/treewidget.c:1374 msgid "New..." msgstr "" #: lib/gtk/treewidget.c:1378 msgid "New from directory..." msgstr "" #: lib/gtk/treewidget.c:1382 lib/gtk/albumwidget.c:1533 msgid "Rename..." msgstr "" #: lib/gtk/treewidget.c:1395 msgid "Scan for devices" msgstr "" #: lib/gtk/treewidget.c:1399 msgid "Add device..." msgstr "" #: lib/gtk/treewidget.c:1406 lib/gtk/albumwidget.c:1601 msgid "Album..." msgstr "" #: lib/gtk/treewidget.c:1419 msgid "Tree..." msgstr "" #: lib/gtk/treewidget.c:2041 msgid "Delete album" msgstr "" #: lib/gtk/treewidget.c:2050 msgid "New album" msgstr "" #: lib/gtk/logwindow.c:238 #, c-format msgid "%s messages" msgstr "" #: lib/gtk/logwindow.c:333 msgid "Number of messages" msgstr "" #: lib/gtk/logwindow.c:336 msgid "Maximum number of messages hold in the window" msgstr "" #: lib/gtk/logwindow.c:340 msgid "Show info messages" msgstr "" #: lib/gtk/logwindow.c:346 msgid "Show warning messages" msgstr "" #: lib/gtk/logwindow.c:352 msgid "Show error messages" msgstr "" #: lib/gtk/logwindow.c:358 msgid "Show debug messages" msgstr "" #: lib/gtk/logwindow.c:364 msgid "Info foreground" msgstr "" #: lib/gtk/logwindow.c:367 msgid "Color for info messages" msgstr "" #: lib/gtk/logwindow.c:371 msgid "Warning foreground" msgstr "" #: lib/gtk/logwindow.c:374 msgid "Color for warning messages" msgstr "" #: lib/gtk/logwindow.c:381 msgid "Color for error messages" msgstr "" #: lib/gtk/logwindow.c:385 msgid "Debug foreground" msgstr "" #: lib/gtk/logwindow.c:388 msgid "Color for debug messages" msgstr "" #: lib/gtk/question.c:93 msgid "Question" msgstr "" #: lib/gtk/plugin_multi.c:270 lib/gtk/plugin_single.c:372 msgid "Plugin info" msgstr "" #: lib/gtk/plugin_multi.c:273 lib/gtk/plugin_single.c:367 msgid "Plugin options" msgstr "" #: lib/gtk/fileselect.c:232 msgid "Recursive" msgstr "" #: lib/gtk/fileselect.c:240 msgid "Add subdirectories as subalbums" msgstr "" #: lib/gtk/fileselect.c:245 msgid "Watch directories" msgstr "" #: lib/gtk/chapterdialog.c:194 msgid "Time" msgstr "" #: lib/gtk/chapterdialog.c:222 lib/gtk/chapterdialog.c:362 msgid "Edit chapter" msgstr "" #: lib/gtk/chapterdialog.c:360 msgid "Add new chapter" msgstr "" #: lib/gtk/chapterdialog.c:364 msgid "Delete chapter" msgstr "" #: lib/gtk/cfg_time.c:216 #, c-format msgid "%s (Hours)" msgstr "" #: lib/gtk/cfg_time.c:220 #, c-format msgid "%s (Minutes)" msgstr "" #: lib/gtk/cfg_time.c:224 #, c-format msgid "%s (Seconds)" msgstr "" #: lib/gtk/cfg_time.c:228 #, c-format msgid "%s (Milliseconds)" msgstr "" #: lib/gtk/cfg_time.c:252 msgid "h:" msgstr "" #: lib/gtk/cfg_time.c:257 msgid "m:" msgstr "" #: lib/gtk/cfg_time.c:261 msgid "s:" msgstr "" #: lib/gtk/cfg_time.c:265 msgid "ms:" msgstr "" #: lib/gtk/fileentry.c:85 msgid "Select a directory" msgstr "" #: lib/gtk/fileentry.c:97 msgid "Select a file" msgstr "" #: lib/gtk/fileentry.c:161 lib/gtk/cfg_font.c:196 msgid "Browse..." msgstr "" #: lib/gtk/pluginmenu.c:36 msgid "Auto Select" msgstr "" #: lib/gtk/pluginmenu.c:107 msgid "Plugin: " msgstr "" #: lib/gtk/presetmenu.c:183 msgid "New preset" msgstr "" #: lib/gtk/presetmenu.c:190 msgid "Save preset" msgstr "" #: lib/gtk/presetmenu.c:323 msgid "Save new..." msgstr "" #: lib/gtk/presetmenu.c:326 msgid "Load..." msgstr "" #: lib/gtk/presetmenu.c:332 msgid "Save to..." msgstr "" #: lib/gtk/presetmenu.c:338 msgid "Delete..." msgstr "" #: lib/gtk/presetmenu.c:349 msgid "Preset" msgstr "" #: lib/gtk/urlselect.c:179 msgid "URL:" msgstr "" #: lib/gtk/albumwidget.c:1130 msgid "Track name" msgstr "" #: lib/gtk/albumwidget.c:1141 msgid "Rename entry" msgstr "" #: lib/gtk/albumwidget.c:1153 #, c-format msgid "Add files to album %s" msgstr "" #: lib/gtk/albumwidget.c:1179 #, c-format msgid "Add URLS to album %s" msgstr "" #: lib/gtk/albumwidget.c:1263 #, c-format msgid "Add albums to %s" msgstr "" #: lib/gtk/albumwidget.c:1455 msgid "URLs..." msgstr "" #: lib/gtk/albumwidget.c:1457 msgid "Albums..." msgstr "" #: lib/gtk/albumwidget.c:1469 msgid "Copy to favourites" msgstr "" #: lib/gtk/albumwidget.c:1478 msgid "Move to top" msgstr "" #: lib/gtk/albumwidget.c:1486 msgid "Move to bottom" msgstr "" #: lib/gtk/albumwidget.c:1522 msgid "Find..." msgstr "" #: lib/gtk/albumwidget.c:1536 msgid "Info..." msgstr "" #: lib/gtk/albumwidget.c:1550 msgid "Refresh" msgstr "" #: lib/gtk/albumwidget.c:1553 msgid "Export as EDL" msgstr "" #: lib/gtk/albumwidget.c:1566 msgid "Save as..." msgstr "" #: lib/gtk/albumwidget.c:1570 msgid "Sort" msgstr "" #: lib/gtk/albumwidget.c:1607 msgid "Select error tracks" msgstr "" #: lib/gtk/albumwidget.c:1610 msgid "Show toolbar" msgstr "" #: lib/gtk/albumwidget.c:2901 msgid "Add URLs" msgstr "" #: lib/gtk/albumwidget.c:2914 msgid "Close album and eject disc" msgstr "" #: lib/gtk/albumwidget.c:2920 msgid "Copy selected tracks to favourites" msgstr "" #: lib/gtk/albumwidget.c:2923 msgid "Rename selected track" msgstr "" #: lib/gtk/albumwidget.c:2926 msgid "Show track info" msgstr "" #: lib/gtk/albumwidget.c:2929 msgid "Find tracks" msgstr "" #: lib/gtk/albumwidget.c:3130 msgid "Backward search hit top, continuing at bottom" msgstr "" #: lib/gtk/albumwidget.c:3139 msgid "Backward search: No tracks found" msgstr "" #: lib/gtk/albumwidget.c:3158 msgid "Forward search hit bottom, continuing at top" msgstr "" #: lib/gtk/albumwidget.c:3167 msgid "Forward search: No tracks found" msgstr "" #: lib/gtk/albumwidget.c:3291 msgid "Exact match" msgstr "" #: lib/gtk/albumwidget.c:3292 msgid "String is an exact substring" msgstr "" #: lib/gtk/albumwidget.c:3296 msgid "Match case" msgstr "" #: lib/gtk/albumwidget.c:3297 msgid "Match upper and lower case" msgstr "" #: lib/gtk/aboutwindow.c:119 msgid "" "Get the latest source version from http://gmerlin.sourceforge.net * * * If " "you installed gmerlin from a binary package, you might have limited features" msgstr "" #: lib/gtk/aboutwindow.c:136 msgid "Visit homepage" msgstr "" #: lib/gtk/aboutwindow.c:170 msgid "Copyright © 2001-2009 Members of the gmerlin project" msgstr "" #: lib/gtk/aboutwindow.c:174 msgid "" "This is free software. You may redistribute copies of it under the terms " "of\n" "the GNU General Public License .\n" "There is NO WARRANTY." msgstr "" #: lib/gtk/treewindow.c:177 msgid "Gmerlin Media Tree" msgstr "" #: lib/gtk/cfg_multi_list.c:863 #, c-format msgid "Add %s" msgstr "" #: lib/gtk/multiinfo.c:142 #, c-format msgid "" "Name:\t %s\n" "Label:\t %s" msgstr "" #: lib/gtk/multiinfo.c:149 msgid "Not available" msgstr "" #: lib/gtk/driveselect.c:225 msgid "Drive:" msgstr "" #: lib/gtk/cfg_dialog.c:502 msgid "No options here, choose subcategory" msgstr "" #: lib/gtk/cfg_dialog.c:682 msgid "No options available" msgstr "" #: lib/gtk/albumentry.c:51 #, c-format msgid "" "Name:\t %s\n" "Location:\t %s\n" "Track:\t %d/%d%s\n" "Plugin:\t %s\n" "Duration:\t %s\n" "Audio Streams:\t %d\n" "Video Streams:\t %d\n" "Subtitle Streams:\t %d" msgstr "" #: lib/gtk/albumentry.c:56 msgid "Auto detect" msgstr "" #: lib/gtk/cfg_position.c:150 msgid "X" msgstr "" #: lib/gtk/cfg_position.c:155 msgid "Y" msgstr "" #: lib/gtk/plugininfo.c:155 msgid "Audio output" msgstr "" #: lib/gtk/plugininfo.c:158 msgid "Video recorder" msgstr "" #: lib/gtk/plugininfo.c:159 msgid "Audio encoder" msgstr "" #: lib/gtk/plugininfo.c:160 msgid "Video encoder" msgstr "" #: lib/gtk/plugininfo.c:162 msgid "Overlay subtitle exporter" msgstr "" #: lib/gtk/plugininfo.c:163 msgid "Audio/Video encoder" msgstr "" #: lib/gtk/plugininfo.c:164 msgid "Image reader" msgstr "" #: lib/gtk/plugininfo.c:165 msgid "Image writer" msgstr "" #: lib/gtk/plugininfo.c:166 msgid "Encoding postprocessor" msgstr "" #: lib/gtk/plugininfo.c:167 msgid "Audio filter" msgstr "" #: lib/gtk/plugininfo.c:168 msgid "Video filter" msgstr "" #: lib/gtk/plugininfo.c:180 msgid "Removable Device" msgstr "" #: lib/gtk/plugininfo.c:183 msgid "URL" msgstr "" #: lib/gtk/plugininfo.c:184 msgid "Playback" msgstr "" #: lib/gtk/plugininfo.c:185 msgid "Tuner" msgstr "" #: lib/gtk/plugininfo.c:186 msgid "Filter with 1 input" msgstr "" #: lib/gtk/plugininfo.c:187 msgid "Renders via gmerlin" msgstr "" #: lib/gtk/plugininfo.c:188 msgid "Renders via OpenGL" msgstr "" #: lib/gtk/plugininfo.c:258 #, c-format msgid "" "Name:\t %s\n" "Long name:\t %s\n" "Type:\t %s\n" "Flags:\t %s\n" "Priority:\t %d\n" "DLL Filename:\t %s" msgstr "" #: lib/gtk/auth.c:73 msgid "Authentication" msgstr "" #: lib/gtk/auth.c:103 msgid "Save user/password (can be dangerous!)" msgstr "" #: lib/gtk/auth.c:114 msgid "Enter username and password for" msgstr "" #: lib/gtk/auth.c:129 msgid "Username" msgstr "" #: lib/gtk/auth.c:134 msgid "Password" msgstr "" #: lib/gtk/cfg_device.c:340 msgid "Delete" msgstr "" #: lib/gtk/message.c:87 msgid "Message" msgstr "" #: lib/recorder.c:52 #, c-format msgid "New track: %s" msgstr "" #: lib/recorder.c:502 msgid "Output filename mask" msgstr "" #: lib/recorder.c:505 msgid "" "Extension is appended by the plugin\n" "For the date and time formatting, consult the documentation\n" "of the strftime(3) function" msgstr "" #: lib/recorder.c:511 msgid "Snapshot directory" msgstr "" #: lib/recorder.c:517 msgid "Snapshot filename mask" msgstr "" #: lib/recorder.c:562 msgid "Metadata mode" msgstr "" #: lib/recorder.c:568 msgid "Static" msgstr "" #: lib/recorder.c:569 msgid "From input" msgstr "" #: lib/recorder.c:570 msgid "From player" msgstr "" #: lib/recorder.c:731 #, c-format msgid "New track %s" msgstr "" #: lib/subprocess.c:168 #, c-format msgid "Created process: %s [%d]" msgstr "" #: lib/subprocess.c:173 #, c-format msgid "Creating process failed: %s" msgstr "" #: lib/subprocess.c:206 #, c-format msgid "Finished process [%d] return value: %d" msgstr "" #: lib/player.c:65 msgid "Aspect ratio changed" msgstr "" #: lib/player.c:309 msgid "Control loop interval" msgstr "" #: lib/player.c:315 msgid "Time update interval" msgstr "" #: lib/player.c:318 msgid "Seconds" msgstr "" #: lib/player.c:318 msgid "frames" msgstr "" #: lib/player.c:323 msgid "Report peak values for audio" msgstr "" #: lib/player.c:328 msgid "Finish mode" msgstr "" #: lib/player.c:331 msgid "Change" msgstr "" #: lib/recorder_audio.c:87 msgid "Record audio" msgstr "" #: lib/bgfrei0r.c:68 lib/bgfrei0r.c:76 lib/bgfrei0r.c:83 lib/bgfrei0r.c:90 #: lib/bgfrei0r.c:183 lib/bgfrei0r.c:475 lib/bgfrei0r.c:490 lib/bgfrei0r.c:496 #: lib/bgfrei0r.c:502 lib/bgfrei0r.c:508 #, c-format msgid "Cannot load frei0r plugin: %s" msgstr "" #: lib/bgfrei0r.c:207 #, c-format msgid "" "Author: %s\n" "%s" msgstr "" #: lib/album.c:499 lib/album.c:545 msgid "Not exporting empty album" msgstr "" #: lib/album.c:506 lib/album.c:552 #, c-format msgid "Could not open %s: %s" msgstr "" #: lib/album.c:610 msgid "Unnamed disc" msgstr "" #: lib/album.c:713 #, c-format msgid "%s disappeared, updating album" msgstr "" #: lib/album.c:723 #, c-format msgid "%s appeared, updating album" msgstr "" #: lib/album.c:825 #, c-format msgid "Album %s already open" msgstr "" #: lib/album.c:830 #, c-format msgid "Opening album %s" msgstr "" #: lib/album.c:975 #, c-format msgid "Not closing album %s (open_count > 0)" msgstr "" #: lib/album.c:978 #, c-format msgid "Closing album %s" msgstr "" #: lib/album.c:2210 #, c-format msgid "Not loading %s (blacklisted extension)" msgstr "" #: lib/album.c:2221 #, c-format msgid "Not loading %s (blacklisted filename)" msgstr "" #: lib/album.c:2251 #, c-format msgid "Loading %s" msgstr "" #: lib/album.c:2295 #, c-format msgid "Loaded %s (track %d of %d)" msgstr "" #: lib/album.c:2497 msgid "Ejecting disc failed" msgstr "" #: lib/album.c:2615 msgid "Invalid selection range given" msgstr "" #: lib/ovl2text.c:159 msgid "Plugin for writing the text subtitles" msgstr "" #: lib/ovl2text.c:233 msgid "Overlay to text converter" msgstr "" #: lib/ovl2text.c:234 msgid "Exports overlay subtitles to a text format by performing an OCR." msgstr "" #: lib/edldec.c:642 msgid "EDL only works with seekable sources" msgstr "" #: lib/edldec.c:1018 msgid "Unexpected EOF, clearing frame" msgstr "" #: lib/edldec.c:1185 msgid "Seeked audio out of range" msgstr "" #: lib/edldec.c:1205 msgid "Seeked video out of range" msgstr "" #: lib/edldec.c:1227 lib/edldec.c:1248 msgid "Seeked text subtitles out of range" msgstr "" #: lib/edldec.c:1372 msgid "EDL decoder" msgstr "" #: lib/edldec.c:1373 msgid "This metaplugin decodes an EDL as if it was a single file." msgstr "" #: lib/filters.c:193 msgid "Audio Filters" msgstr "" #: lib/filters.c:353 #, c-format msgid "Initialized audio filter %s" msgstr "" #: lib/filters.c:623 msgid "Video Filters" msgstr "" #: lib/filters.c:778 #, c-format msgid "Initialized video filter %s" msgstr "" #: lib/bglv.c:429 msgid "libvisual plugin" msgstr "" #: lib/bglv.c:434 #, c-format msgid "" "\n" "Author: %s" msgstr "" #: lib/bglv.c:441 #, c-format msgid "" "\n" "Version: %s" msgstr "" #: lib/bglv.c:448 #, c-format msgid "" "\n" "About: %s" msgstr "" #: lib/bglv.c:455 #, c-format msgid "" "\n" "Help: %s" msgstr "" #: lib/bglv.c:462 #, c-format msgid "" "\n" "License: %s" msgstr "" gmerlin-1.2.0~dfsg/po/insert-header.sin0000644000175000017500000000124011764363410017756 0ustar alessioalessio# Sed script that inserts the file called HEADER before the header entry. # # At each occurrence of a line starting with "msgid ", we execute the following # commands. At the first occurrence, insert the file. At the following # occurrences, do nothing. The distinction between the first and the following # occurrences is achieved by looking at the hold space. /^msgid /{ x # Test if the hold space is empty. s/m/m/ ta # Yes it was empty. First occurrence. Read the file. r HEADER # Output the file's contents by reading the next line. But don't lose the # current line while doing this. g N bb :a # The hold space was nonempty. Following occurrences. Do nothing. x :b } gmerlin-1.2.0~dfsg/COPYING0000644000175000017500000010451311331674343015135 0ustar alessioalessio GNU GENERAL PUBLIC LICENSE Version 3, 29 June 2007 Copyright (C) 2007 Free Software Foundation, Inc. Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble The GNU General Public License is a free, copyleft license for software and other kinds of works. The licenses for most software and other practical works are designed to take away your freedom to share and change the works. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change all versions of a program--to make sure it remains free software for all its users. We, the Free Software Foundation, use the GNU General Public License for most of our software; it applies also to any other work released this way by its authors. You can apply it to your programs, too. When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for them if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs, and that you know you can do these things. To protect your rights, we need to prevent others from denying you these rights or asking you to surrender the rights. Therefore, you have certain responsibilities if you distribute copies of the software, or if you modify it: responsibilities to respect the freedom of others. For example, if you distribute copies of such a program, whether gratis or for a fee, you must pass on to the recipients the same freedoms that you received. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. Developers that use the GNU GPL protect your rights with two steps: (1) assert copyright on the software, and (2) offer you this License giving you legal permission to copy, distribute and/or modify it. For the developers' and authors' protection, the GPL clearly explains that there is no warranty for this free software. For both users' and authors' sake, the GPL requires that modified versions be marked as changed, so that their problems will not be attributed erroneously to authors of previous versions. Some devices are designed to deny users access to install or run modified versions of the software inside them, although the manufacturer can do so. This is fundamentally incompatible with the aim of protecting users' freedom to change the software. The systematic pattern of such abuse occurs in the area of products for individuals to use, which is precisely where it is most unacceptable. Therefore, we have designed this version of the GPL to prohibit the practice for those products. If such problems arise substantially in other domains, we stand ready to extend this provision to those domains in future versions of the GPL, as needed to protect the freedom of users. Finally, every program is threatened constantly by software patents. States should not allow patents to restrict development and use of software on general-purpose computers, but in those that do, we wish to avoid the special danger that patents applied to a free program could make it effectively proprietary. To prevent this, the GPL assures that patents cannot be used to render the program non-free. The precise terms and conditions for copying, distribution and modification follow. TERMS AND CONDITIONS 0. Definitions. "This License" refers to version 3 of the GNU General Public License. "Copyright" also means copyright-like laws that apply to other kinds of works, such as semiconductor masks. "The Program" refers to any copyrightable work licensed under this License. Each licensee is addressed as "you". "Licensees" and "recipients" may be individuals or organizations. To "modify" a work means to copy from or adapt all or part of the work in a fashion requiring copyright permission, other than the making of an exact copy. The resulting work is called a "modified version" of the earlier work or a work "based on" the earlier work. A "covered work" means either the unmodified Program or a work based on the Program. To "propagate" a work means to do anything with it that, without permission, would make you directly or secondarily liable for infringement under applicable copyright law, except executing it on a computer or modifying a private copy. Propagation includes copying, distribution (with or without modification), making available to the public, and in some countries other activities as well. To "convey" a work means any kind of propagation that enables other parties to make or receive copies. Mere interaction with a user through a computer network, with no transfer of a copy, is not conveying. An interactive user interface displays "Appropriate Legal Notices" to the extent that it includes a convenient and prominently visible feature that (1) displays an appropriate copyright notice, and (2) tells the user that there is no warranty for the work (except to the extent that warranties are provided), that licensees may convey the work under this License, and how to view a copy of this License. If the interface presents a list of user commands or options, such as a menu, a prominent item in the list meets this criterion. 1. Source Code. The "source code" for a work means the preferred form of the work for making modifications to it. "Object code" means any non-source form of a work. A "Standard Interface" means an interface that either is an official standard defined by a recognized standards body, or, in the case of interfaces specified for a particular programming language, one that is widely used among developers working in that language. The "System Libraries" of an executable work include anything, other than the work as a whole, that (a) is included in the normal form of packaging a Major Component, but which is not part of that Major Component, and (b) serves only to enable use of the work with that Major Component, or to implement a Standard Interface for which an implementation is available to the public in source code form. A "Major Component", in this context, means a major essential component (kernel, window system, and so on) of the specific operating system (if any) on which the executable work runs, or a compiler used to produce the work, or an object code interpreter used to run it. The "Corresponding Source" for a work in object code form means all the source code needed to generate, install, and (for an executable work) run the object code and to modify the work, including scripts to control those activities. However, it does not include the work's System Libraries, or general-purpose tools or generally available free programs which are used unmodified in performing those activities but which are not part of the work. For example, Corresponding Source includes interface definition files associated with source files for the work, and the source code for shared libraries and dynamically linked subprograms that the work is specifically designed to require, such as by intimate data communication or control flow between those subprograms and other parts of the work. The Corresponding Source need not include anything that users can regenerate automatically from other parts of the Corresponding Source. The Corresponding Source for a work in source code form is that same work. 2. Basic Permissions. All rights granted under this License are granted for the term of copyright on the Program, and are irrevocable provided the stated conditions are met. This License explicitly affirms your unlimited permission to run the unmodified Program. The output from running a covered work is covered by this License only if the output, given its content, constitutes a covered work. This License acknowledges your rights of fair use or other equivalent, as provided by copyright law. You may make, run and propagate covered works that you do not convey, without conditions so long as your license otherwise remains in force. You may convey covered works to others for the sole purpose of having them make modifications exclusively for you, or provide you with facilities for running those works, provided that you comply with the terms of this License in conveying all material for which you do not control copyright. Those thus making or running the covered works for you must do so exclusively on your behalf, under your direction and control, on terms that prohibit them from making any copies of your copyrighted material outside their relationship with you. Conveying under any other circumstances is permitted solely under the conditions stated below. Sublicensing is not allowed; section 10 makes it unnecessary. 3. Protecting Users' Legal Rights From Anti-Circumvention Law. No covered work shall be deemed part of an effective technological measure under any applicable law fulfilling obligations under article 11 of the WIPO copyright treaty adopted on 20 December 1996, or similar laws prohibiting or restricting circumvention of such measures. When you convey a covered work, you waive any legal power to forbid circumvention of technological measures to the extent such circumvention is effected by exercising rights under this License with respect to the covered work, and you disclaim any intention to limit operation or modification of the work as a means of enforcing, against the work's users, your or third parties' legal rights to forbid circumvention of technological measures. 4. Conveying Verbatim Copies. You may convey verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice; keep intact all notices stating that this License and any non-permissive terms added in accord with section 7 apply to the code; keep intact all notices of the absence of any warranty; and give all recipients a copy of this License along with the Program. You may charge any price or no price for each copy that you convey, and you may offer support or warranty protection for a fee. 5. Conveying Modified Source Versions. You may convey a work based on the Program, or the modifications to produce it from the Program, in the form of source code under the terms of section 4, provided that you also meet all of these conditions: a) The work must carry prominent notices stating that you modified it, and giving a relevant date. b) The work must carry prominent notices stating that it is released under this License and any conditions added under section 7. This requirement modifies the requirement in section 4 to "keep intact all notices". c) You must license the entire work, as a whole, under this License to anyone who comes into possession of a copy. This License will therefore apply, along with any applicable section 7 additional terms, to the whole of the work, and all its parts, regardless of how they are packaged. This License gives no permission to license the work in any other way, but it does not invalidate such permission if you have separately received it. d) If the work has interactive user interfaces, each must display Appropriate Legal Notices; however, if the Program has interactive interfaces that do not display Appropriate Legal Notices, your work need not make them do so. A compilation of a covered work with other separate and independent works, which are not by their nature extensions of the covered work, and which are not combined with it such as to form a larger program, in or on a volume of a storage or distribution medium, is called an "aggregate" if the compilation and its resulting copyright are not used to limit the access or legal rights of the compilation's users beyond what the individual works permit. Inclusion of a covered work in an aggregate does not cause this License to apply to the other parts of the aggregate. 6. Conveying Non-Source Forms. You may convey a covered work in object code form under the terms of sections 4 and 5, provided that you also convey the machine-readable Corresponding Source under the terms of this License, in one of these ways: a) Convey the object code in, or embodied in, a physical product (including a physical distribution medium), accompanied by the Corresponding Source fixed on a durable physical medium customarily used for software interchange. b) Convey the object code in, or embodied in, a physical product (including a physical distribution medium), accompanied by a written offer, valid for at least three years and valid for as long as you offer spare parts or customer support for that product model, to give anyone who possesses the object code either (1) a copy of the Corresponding Source for all the software in the product that is covered by this License, on a durable physical medium customarily used for software interchange, for a price no more than your reasonable cost of physically performing this conveying of source, or (2) access to copy the Corresponding Source from a network server at no charge. c) Convey individual copies of the object code with a copy of the written offer to provide the Corresponding Source. This alternative is allowed only occasionally and noncommercially, and only if you received the object code with such an offer, in accord with subsection 6b. d) Convey the object code by offering access from a designated place (gratis or for a charge), and offer equivalent access to the Corresponding Source in the same way through the same place at no further charge. You need not require recipients to copy the Corresponding Source along with the object code. If the place to copy the object code is a network server, the Corresponding Source may be on a different server (operated by you or a third party) that supports equivalent copying facilities, provided you maintain clear directions next to the object code saying where to find the Corresponding Source. Regardless of what server hosts the Corresponding Source, you remain obligated to ensure that it is available for as long as needed to satisfy these requirements. e) Convey the object code using peer-to-peer transmission, provided you inform other peers where the object code and Corresponding Source of the work are being offered to the general public at no charge under subsection 6d. A separable portion of the object code, whose source code is excluded from the Corresponding Source as a System Library, need not be included in conveying the object code work. A "User Product" is either (1) a "consumer product", which means any tangible personal property which is normally used for personal, family, or household purposes, or (2) anything designed or sold for incorporation into a dwelling. In determining whether a product is a consumer product, doubtful cases shall be resolved in favor of coverage. For a particular product received by a particular user, "normally used" refers to a typical or common use of that class of product, regardless of the status of the particular user or of the way in which the particular user actually uses, or expects or is expected to use, the product. A product is a consumer product regardless of whether the product has substantial commercial, industrial or non-consumer uses, unless such uses represent the only significant mode of use of the product. "Installation Information" for a User Product means any methods, procedures, authorization keys, or other information required to install and execute modified versions of a covered work in that User Product from a modified version of its Corresponding Source. The information must suffice to ensure that the continued functioning of the modified object code is in no case prevented or interfered with solely because modification has been made. If you convey an object code work under this section in, or with, or specifically for use in, a User Product, and the conveying occurs as part of a transaction in which the right of possession and use of the User Product is transferred to the recipient in perpetuity or for a fixed term (regardless of how the transaction is characterized), the Corresponding Source conveyed under this section must be accompanied by the Installation Information. But this requirement does not apply if neither you nor any third party retains the ability to install modified object code on the User Product (for example, the work has been installed in ROM). The requirement to provide Installation Information does not include a requirement to continue to provide support service, warranty, or updates for a work that has been modified or installed by the recipient, or for the User Product in which it has been modified or installed. Access to a network may be denied when the modification itself materially and adversely affects the operation of the network or violates the rules and protocols for communication across the network. Corresponding Source conveyed, and Installation Information provided, in accord with this section must be in a format that is publicly documented (and with an implementation available to the public in source code form), and must require no special password or key for unpacking, reading or copying. 7. Additional Terms. "Additional permissions" are terms that supplement the terms of this License by making exceptions from one or more of its conditions. Additional permissions that are applicable to the entire Program shall be treated as though they were included in this License, to the extent that they are valid under applicable law. If additional permissions apply only to part of the Program, that part may be used separately under those permissions, but the entire Program remains governed by this License without regard to the additional permissions. When you convey a copy of a covered work, you may at your option remove any additional permissions from that copy, or from any part of it. (Additional permissions may be written to require their own removal in certain cases when you modify the work.) You may place additional permissions on material, added by you to a covered work, for which you have or can give appropriate copyright permission. Notwithstanding any other provision of this License, for material you add to a covered work, you may (if authorized by the copyright holders of that material) supplement the terms of this License with terms: a) Disclaiming warranty or limiting liability differently from the terms of sections 15 and 16 of this License; or b) Requiring preservation of specified reasonable legal notices or author attributions in that material or in the Appropriate Legal Notices displayed by works containing it; or c) Prohibiting misrepresentation of the origin of that material, or requiring that modified versions of such material be marked in reasonable ways as different from the original version; or d) Limiting the use for publicity purposes of names of licensors or authors of the material; or e) Declining to grant rights under trademark law for use of some trade names, trademarks, or service marks; or f) Requiring indemnification of licensors and authors of that material by anyone who conveys the material (or modified versions of it) with contractual assumptions of liability to the recipient, for any liability that these contractual assumptions directly impose on those licensors and authors. All other non-permissive additional terms are considered "further restrictions" within the meaning of section 10. If the Program as you received it, or any part of it, contains a notice stating that it is governed by this License along with a term that is a further restriction, you may remove that term. If a license document contains a further restriction but permits relicensing or conveying under this License, you may add to a covered work material governed by the terms of that license document, provided that the further restriction does not survive such relicensing or conveying. If you add terms to a covered work in accord with this section, you must place, in the relevant source files, a statement of the additional terms that apply to those files, or a notice indicating where to find the applicable terms. Additional terms, permissive or non-permissive, may be stated in the form of a separately written license, or stated as exceptions; the above requirements apply either way. 8. Termination. You may not propagate or modify a covered work except as expressly provided under this License. Any attempt otherwise to propagate or modify it is void, and will automatically terminate your rights under this License (including any patent licenses granted under the third paragraph of section 11). However, if you cease all violation of this License, then your license from a particular copyright holder is reinstated (a) provisionally, unless and until the copyright holder explicitly and finally terminates your license, and (b) permanently, if the copyright holder fails to notify you of the violation by some reasonable means prior to 60 days after the cessation. Moreover, your license from a particular copyright holder is reinstated permanently if the copyright holder notifies you of the violation by some reasonable means, this is the first time you have received notice of violation of this License (for any work) from that copyright holder, and you cure the violation prior to 30 days after your receipt of the notice. Termination of your rights under this section does not terminate the licenses of parties who have received copies or rights from you under this License. If your rights have been terminated and not permanently reinstated, you do not qualify to receive new licenses for the same material under section 10. 9. Acceptance Not Required for Having Copies. You are not required to accept this License in order to receive or run a copy of the Program. Ancillary propagation of a covered work occurring solely as a consequence of using peer-to-peer transmission to receive a copy likewise does not require acceptance. However, nothing other than this License grants you permission to propagate or modify any covered work. These actions infringe copyright if you do not accept this License. Therefore, by modifying or propagating a covered work, you indicate your acceptance of this License to do so. 10. Automatic Licensing of Downstream Recipients. Each time you convey a covered work, the recipient automatically receives a license from the original licensors, to run, modify and propagate that work, subject to this License. You are not responsible for enforcing compliance by third parties with this License. An "entity transaction" is a transaction transferring control of an organization, or substantially all assets of one, or subdividing an organization, or merging organizations. If propagation of a covered work results from an entity transaction, each party to that transaction who receives a copy of the work also receives whatever licenses to the work the party's predecessor in interest had or could give under the previous paragraph, plus a right to possession of the Corresponding Source of the work from the predecessor in interest, if the predecessor has it or can get it with reasonable efforts. You may not impose any further restrictions on the exercise of the rights granted or affirmed under this License. For example, you may not impose a license fee, royalty, or other charge for exercise of rights granted under this License, and you may not initiate litigation (including a cross-claim or counterclaim in a lawsuit) alleging that any patent claim is infringed by making, using, selling, offering for sale, or importing the Program or any portion of it. 11. Patents. A "contributor" is a copyright holder who authorizes use under this License of the Program or a work on which the Program is based. The work thus licensed is called the contributor's "contributor version". A contributor's "essential patent claims" are all patent claims owned or controlled by the contributor, whether already acquired or hereafter acquired, that would be infringed by some manner, permitted by this License, of making, using, or selling its contributor version, but do not include claims that would be infringed only as a consequence of further modification of the contributor version. For purposes of this definition, "control" includes the right to grant patent sublicenses in a manner consistent with the requirements of this License. Each contributor grants you a non-exclusive, worldwide, royalty-free patent license under the contributor's essential patent claims, to make, use, sell, offer for sale, import and otherwise run, modify and propagate the contents of its contributor version. In the following three paragraphs, a "patent license" is any express agreement or commitment, however denominated, not to enforce a patent (such as an express permission to practice a patent or covenant not to sue for patent infringement). To "grant" such a patent license to a party means to make such an agreement or commitment not to enforce a patent against the party. If you convey a covered work, knowingly relying on a patent license, and the Corresponding Source of the work is not available for anyone to copy, free of charge and under the terms of this License, through a publicly available network server or other readily accessible means, then you must either (1) cause the Corresponding Source to be so available, or (2) arrange to deprive yourself of the benefit of the patent license for this particular work, or (3) arrange, in a manner consistent with the requirements of this License, to extend the patent license to downstream recipients. "Knowingly relying" means you have actual knowledge that, but for the patent license, your conveying the covered work in a country, or your recipient's use of the covered work in a country, would infringe one or more identifiable patents in that country that you have reason to believe are valid. If, pursuant to or in connection with a single transaction or arrangement, you convey, or propagate by procuring conveyance of, a covered work, and grant a patent license to some of the parties receiving the covered work authorizing them to use, propagate, modify or convey a specific copy of the covered work, then the patent license you grant is automatically extended to all recipients of the covered work and works based on it. A patent license is "discriminatory" if it does not include within the scope of its coverage, prohibits the exercise of, or is conditioned on the non-exercise of one or more of the rights that are specifically granted under this License. You may not convey a covered work if you are a party to an arrangement with a third party that is in the business of distributing software, under which you make payment to the third party based on the extent of your activity of conveying the work, and under which the third party grants, to any of the parties who would receive the covered work from you, a discriminatory patent license (a) in connection with copies of the covered work conveyed by you (or copies made from those copies), or (b) primarily for and in connection with specific products or compilations that contain the covered work, unless you entered into that arrangement, or that patent license was granted, prior to 28 March 2007. Nothing in this License shall be construed as excluding or limiting any implied license or other defenses to infringement that may otherwise be available to you under applicable patent law. 12. No Surrender of Others' Freedom. If conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot convey a covered work so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not convey it at all. For example, if you agree to terms that obligate you to collect a royalty for further conveying from those to whom you convey the Program, the only way you could satisfy both those terms and this License would be to refrain entirely from conveying the Program. 13. Use with the GNU Affero General Public License. Notwithstanding any other provision of this License, you have permission to link or combine any covered work with a work licensed under version 3 of the GNU Affero General Public License into a single combined work, and to convey the resulting work. The terms of this License will continue to apply to the part which is the covered work, but the special requirements of the GNU Affero General Public License, section 13, concerning interaction through a network will apply to the combination as such. 14. Revised Versions of this License. The Free Software Foundation may publish revised and/or new versions of the GNU General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Program specifies that a certain numbered version of the GNU General Public License "or any later version" applies to it, you have the option of following the terms and conditions either of that numbered version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of the GNU General Public License, you may choose any version ever published by the Free Software Foundation. If the Program specifies that a proxy can decide which future versions of the GNU General Public License can be used, that proxy's public statement of acceptance of a version permanently authorizes you to choose that version for the Program. Later license versions may give you additional or different permissions. However, no additional obligations are imposed on any author or copyright holder as a result of your choosing to follow a later version. 15. Disclaimer of Warranty. THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 16. Limitation of Liability. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. 17. Interpretation of Sections 15 and 16. If the disclaimer of warranty and limitation of liability provided above cannot be given local legal effect according to their terms, reviewing courts shall apply local law that most closely approximates an absolute waiver of all civil liability in connection with the Program, unless a warranty or assumption of liability accompanies a copy of the Program in return for a fee. END OF TERMS AND CONDITIONS How to Apply These Terms to Your New Programs If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms. To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively state the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) 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 3 of the License, 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 this program. If not, see . Also add information on how to contact you by electronic and paper mail. If the program does terminal interaction, make it output a short notice like this when it starts in an interactive mode: Copyright (C) This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. This is free software, and you are welcome to redistribute it under certain conditions; type `show c' for details. The hypothetical commands `show w' and `show c' should show the appropriate parts of the General Public License. Of course, your program's commands might be different; for a GUI interface, you would use an "about box". You should also get your employer (if you work as a programmer) or school, if any, to sign a "copyright disclaimer" for the program, if necessary. For more information on this, and how to apply and follow the GNU GPL, see . The GNU General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Lesser General Public License instead of this License. But first, please read . gmerlin-1.2.0~dfsg/INSTALL0000644000175000017500000000366611764363414015146 0ustar alessioalessio1. Requirements First of all: The only required libraries are gavl (which can be downloaded from the gmerlin website) and libxml2, which is part of most (if not all) linux distributions. All other libraries are OPTIONAL, i.e. the configure script will search for them and use them, if they are found. The more libraries you have, the more features you can use, e.g. if you really don't want to encode movie files, you can skip the installation of libquicktime and everything will be fine for you. Gtk-2 is required for building all the applications. Without it, you'll just get some libraries, but they won't be of much use for now. The website (http://gmerlin.sf.net/download.html) lists all packages, which can be used by gmerlin. At the very end, the configure script prints out a summary of the packages it found. If you installed a library but it wasn't found by the configure script, the error is in 99% of the cases one of the following: - A binary package (e.g. rpm) was installed but not the development package (e.g. for libfoo-1.2.3-4.i386.rpm you also need libfoo-devel-1.2.3-4.i386.rpm) - The path where the libraries got installed (usually /usr/local/bin for source packages) is missing in the file /etc/ld.so.conf. This is the case e.g. on Fedora Core 3. Add the path there, run /sbin/ldconfig as root and everything should work. - After installation of the library, /sbin/ldconfig wasn't called - The package wasn't found, because the environment variable PKG_CONFIG_PATH is not properly set. Typing export PKG_CONFIG_PATH=/usr/local/lib/pkgconfig before calling configure helps in most cases. If all these tips don't help, attach the file config.log to an email and send it to gmerlin-general@lists.sourceforge.net. 2. Compilation Nothing special here. It's the usual procedure: ./configure make su make install The configure script supports some command line options, type ./configure --help to see them. gmerlin-1.2.0~dfsg/configure.ac0000644000175000017500000007322711764363414016403 0ustar alessioalessio AC_INIT AC_CONFIG_SRCDIR([include/gmerlin/player.h]) AM_CONFIG_HEADER(include/config.h) AM_INIT_AUTOMAKE(gmerlin, 1.2.0) BG_VERSION=$VERSION BG_VERSION_MAJOR=`echo $VERSION | cut -d . -f 1` BG_VERSION_MINOR=`echo $VERSION | cut -d . -f 2` BG_VERSION_MICRO=`echo $VERSION | cut -d . -f 3 | cut -d p -f 1` LTVERSION_CURRENT="0" LTVERSION_REVISION="0" LTVERSION_AGE="0" AC_SUBST(BG_VERSION) AC_SUBST(BG_VERSION_MAJOR) AC_SUBST(BG_VERSION_MINOR) AC_SUBST(BG_VERSION_MICRO) AC_SUBST(LTVERSION_CURRENT) AC_SUBST(LTVERSION_REVISION) AC_SUBST(LTVERSION_AGE) SAVE_CFLAGS=$CFLAGS AC_DISABLE_STATIC dnl AM_DISABLE_STATIC AC_PROG_LIBTOOL CFLAGS=$SAVE_CFLAGS dnl dnl General features dnl AC_CHECK_SIZEOF(long) AC_CHECK_SIZEOF(float) AC_CHECK_SIZEOF(double) AC_CHECK_FUNCS(vasprintf) AC_CHECK_FUNCS(canonicalize_file_name) AC_C99_FUNC_LRINT AC_C99_FUNC_LRINTF AC_C_BIGENDIAN(,,AC_MSG_ERROR("Cannot detect endianess")) AC_CHECK_HEADERS([sys/select.h]) AC_CHECK_DECLS([MSG_NOSIGNAL, SO_NOSIGPIPE],,, [#include #include ]) dnl dnl POSIX Semaphores dnl GMERLIN_CHECK_SEMAPHORES dnl dnl Gettext dnl AM_GNU_GETTEXT([external]) dnl dnl Check for Dependencies package dnl GMERLIN_DEP_DIR=/opt/gmerlin if test -d $GMERLIN_DEP_DIR; then have_opt_gmerlin="true" export PKG_CONFIG_PATH=$GMERLIN_DEP_DIR/lib/pkgconfig:$PKG_CONFIG_PATH GMERLIN_DEP_CFLAGS="-I$GMERLIN_DEP_DIR/include" GMERLIN_DEP_LDPATH="$GMERLIN_DEP_DIR/lib" GMERLIN_DEP_LIBS="-L$GMERLIN_DEP_DIR/lib" AC_MSG_CHECKING(for --rpath option) OLD_LDFLAGS=$LDFLAGS LDFLAGS="$LDFLAGS -Wl,--rpath -Wl,$GMERLIN_DEP_DIR/lib" AC_TRY_LINK([],[], [GMERLIN_DEP_RPATH="-Wl,--rpath -Wl,$GMERLIN_DEP_DIR/lib"; AC_MSG_RESULT(Supported)], [GMERLIN_DEP_RPATH="";AC_MSG_RESULT(Unsupported)]) LDFLAGS=$OLD_LDFLAGS else have_opt_gmerlin="false" GMERLIN_DEP_CFLAGS="" GMERLIN_DEP_LDPATH="" GMERLIN_DEP_LIBS="" GMERLIN_DEP_RPATH="" fi LDFLAGS="$GMERLIN_DEP_RPATH" AC_SUBST(GMERLIN_DEP_LIBS) dnl dnl Doxygen dnl test_doxygen="true" have_doxygen="false" AC_ARG_WITH(doxygen, AC_HELP_STRING([--without-doxygen], [disable doxygen documentation generation]), test_doxygen="false") if test "x$test_doxygen" = "xtrue"; then AC_CHECK_PROG(DOXYGEN, doxygen, "doxygen") if test -z "$DOXYGEN"; then AC_MSG_ERROR([Doxygen not found, use --without-doxygen to disable documentation generation]) else have_doxygen="true" fi fi AM_CONDITIONAL(HAVE_DOXYGEN, test "x$have_doxygen" = "xtrue") dnl dnl texinfo (now a build requirement) dnl have_texinfo="false" AC_CHECK_PROG(TEXINFO, makeinfo, "makeinfo") if test -z "$TEXINFO"; then AC_MSG_ERROR([Texinfo not found]) fi dnl dnl Check for Libraries dnl dnl Required LT_LIB_M XML2_REQUIRED="2.4.0" PKG_CHECK_MODULES(XML2, libxml-2.0 >= $XML2_REQUIRED, , AC_MSG_ERROR("libxml2 not found")) AC_SUBST(XML2_REQUIRED) GAVL_REQUIRED="1.4.0" PKG_CHECK_MODULES(GAVL, gavl >= $GAVL_REQUIRED, , AC_MSG_ERROR("gavl not found")) AC_SUBST(GAVL_REQUIRED) FONTCONFIG_REQUIRED="2.2.3" PKG_CHECK_MODULES(FONTCONFIG, fontconfig >= $FONTCONFIG_REQUIRED, , AC_MSG_ERROR("fontconfig not found")) FREETYPE_REQUIRED="9.7.3" PKG_CHECK_MODULES(FREETYPE, freetype2 >= $FREETYPE_REQUIRED, , AC_MSG_ERROR("freetype2 not found")) ICONV_LIBS="" AC_CHECK_LIB(iconv, libiconv_close, ICONV_LIBS="-liconv") AC_SUBST(ICONV_LIBS) SQLITE3_LIBS="" AC_CHECK_LIB(sqlite3, sqlite3_exec, [SQLITE3_LIBS="-lsqlite3"; have_sqlite3="true"], have_sqlite3="false") AC_SUBST(SQLITE3_LIBS) dnl dnl Gtk dnl GTK_REQUIRED="2.8.0" AM_PATH_GTK_2_0($GTK_REQUIRED, have_gtk=true, have_gtk=false) AM_CONDITIONAL(HAVE_GTK, test x$have_gtk = xtrue) AC_SUBST(GTK_REQUIRED) dnl Always be in sync with the newest gtk GTK_CFLAGS="$GTK_CFLAGS -DGTK_DISABLE_DEPRECATED" dnl dnl X11 dnl have_x="false" X_CFLAGS="" X_LIBS="" AC_PATH_X if test x$no_x != xyes; then if test "x$x_includes" != "x"; then X_CFLAGS="-I$x_includes" elif test -d /usr/X11R6/include; then X_CFLAGS="-I/usr/X11R6/include" else X_CFLAGS="" fi if test "x$x_libraries" != "x"; then X_LIBS="-L$x_libraries -lX11" else X_LIBS="-lX11" fi have_x="true" else PKG_CHECK_MODULES(X, x11 >= 1.0.0, have_x=true, have_x=false) fi if test x$have_x = xtrue; then X_LIBS="$X_LIBS -lXext" else AC_MSG_ERROR([Gmerlin needs X11 headers]) fi AC_SUBST(X_CFLAGS) AC_SUBST(X_LIBS) AM_CONDITIONAL(HAVE_X11, test x$have_x = xtrue) dnl dnl OpenGL dnl GMERLIN_CHECK_OPENGL dnl dnl Pulseaudio dnl GMERLIN_CHECK_PULSEAUDIO dnl dnl Xinerama dnl AH_TEMPLATE([HAVE_LIBXINERAMA], [Do we have xinerama installed?]) have_xinerama="false" XINERAMA_LIBS="" if test x$have_x = xtrue; then OLD_CFLAGS=$CFLAGS OLD_LIBS=$LIBS CFLAGS=$X_FLAGS LIBS="$X_LIBS -lXinerama" AC_MSG_CHECKING(for xinerama) AC_TRY_LINK([#include #include ], [int i = 0; /* We ensure the function is here but never call it */ if(i) XineramaQueryExtension(NULL, NULL, NULL); return 0;], [XINERAMA_LIBS="-lXinerama";have_xinerama=true;AC_MSG_RESULT(Yes)], AC_MSG_RESULT(No)) if test x$have_xinerama = "xtrue"; then AC_DEFINE(HAVE_LIBXINERAMA) fi AC_SUBST(XINERAMA_LIBS) CFLAGS=$OLD_CFLAGS LIBS=$OLD_LIBS fi dnl dnl XTest dnl AH_TEMPLATE([HAVE_XTEST], [Do we have xtest installed?]) have_xtest="false" XTEST_LIBS="" if test x$have_x = xtrue; then OLD_CFLAGS=$CFLAGS OLD_LIBS=$LIBS CFLAGS=$X_FLAGS LIBS="$X_LIBS -lXtst" AC_MSG_CHECKING(for xtest) AC_TRY_LINK([#include #include ], [int i = 0; /* We ensure the function is here but never call it */ if(i) XTestQueryExtension(NULL, NULL, NULL, NULL, NULL); return 0;], [XTEST_LIBS="-lXtst";have_xtest=true;AC_MSG_RESULT(Yes)], AC_MSG_RESULT(No)) if test x$have_xtest = "xtrue"; then AC_DEFINE(HAVE_XTEST) fi AC_SUBST(XTEST_LIBS) CFLAGS=$OLD_CFLAGS LIBS=$OLD_LIBS fi AM_CONDITIONAL(HAVE_XTEST, test x$have_xtest = xtrue) dnl dnl Xv dnl AH_TEMPLATE([HAVE_LIBXV], [Do we have xv installed?]) have_xv="false" XV_LIBS="" if test x$have_x = xtrue; then OLD_CFLAGS=$CFLAGS OLD_LIBS=$LIBS CFLAGS=$X_FLAGS LIBS="$X_LIBS -lXv" AC_MSG_CHECKING(for xv) AC_TRY_LINK([#include #include ], [int i = 0; /* We ensure the function is here but never call it */ if(i) XvQueryExtension(NULL, NULL, NULL, NULL, NULL, NULL); return 0;], [XV_LIBS="-lXv";have_xv=true;AC_MSG_RESULT(Yes)], AC_MSG_RESULT("No")) if test x$have_xv = "xtrue"; then AC_DEFINE(HAVE_LIBXV) fi AC_SUBST(XV_LIBS) CFLAGS=$OLD_CFLAGS LIBS=$OLD_LIBS fi AM_CONDITIONAL(HAVE_XV, test x$have_xv = xtrue) dnl dnl X11 DPMS extension dnl AH_TEMPLATE([HAVE_XDPMS], [Do we have X11 dpms extension installed?]) have_xdpms="false" XDPMS_LIBS="" if test x$have_x = xtrue; then OLD_CFLAGS=$CFLAGS OLD_LIBS=$LIBS CFLAGS=$X_FLAGS LIBS="$X_LIBS -lXext" AC_MSG_CHECKING(for x11 dpms) AC_TRY_LINK([#include #include ], [int i = 0; /* We ensure the function is here but never call it */ if(i) DPMSQueryExtension(NULL, NULL, NULL); return 0;], [XDPMS_LIBS="-lXext";have_xdpms=true;AC_MSG_RESULT(Yes)], AC_MSG_RESULT("No")) if test x$have_xdpms = "xtrue"; then AC_DEFINE(HAVE_XDPMS) fi AC_SUBST(XDPMS_LIBS) CFLAGS=$OLD_CFLAGS LIBS=$OLD_LIBS fi dnl dnl XFixes dnl AH_TEMPLATE([HAVE_XFIXES], [Do we have XFixes extension installed?]) have_xfixes="false" XFIXES_LIBS="" if test x$have_x = xtrue; then OLD_CFLAGS=$CFLAGS OLD_LIBS=$LIBS CFLAGS=$X_FLAGS LIBS="$X_LIBS -lXfixes" AC_MSG_CHECKING(for x11 dpms) AC_TRY_LINK([#include #include ], [int i = 0; /* We ensure the function is here but never call it */ if(i) XFixesQueryExtension(NULL, NULL, NULL); return 0;], [XFIXES_LIBS="-lXfixes";have_xfixes=true;AC_MSG_RESULT(Yes)], AC_MSG_RESULT("No")) if test x$have_xfixes = "xtrue"; then AC_DEFINE(HAVE_XFIXES) fi AC_SUBST(XFIXES_LIBS) CFLAGS=$OLD_CFLAGS LIBS=$OLD_LIBS fi dnl dnl Libquicktime dnl LQT_REQUIRED="1.2.4" have_lqt=false AC_ARG_ENABLE(lqt, AC_HELP_STRING(--disable-lqt, [Disable Libquicktime support (default: autodetect)]), [case "${enableval}" in yes) test_lqt=true ;; no) test_lqt=false ;; esac], test_lqt=true) if test x$test_lqt = "xtrue"; then PKG_CHECK_MODULES(LQT, libquicktime >= $LQT_REQUIRED, have_lqt=true, have_lqt=false) fi dnl AC_PATH_LQT($LQT_REQUIRED, have_lqt=true, have_lqt=false) AM_CONDITIONAL(HAVE_LQT, test x$have_lqt = xtrue) AC_SUBST(LQT_REQUIRED) dnl dnl libexif dnl AH_TEMPLATE([HAVE_LIBEXIF], [Do we have libexif installed?]) PKG_CHECK_MODULES(LIBEXIF, libexif, have_libexif=true, have_libexif=false) if test x$have_libexif = "xtrue"; then AC_DEFINE(HAVE_LIBEXIF) fi AM_CONDITIONAL(HAVE_LIBEXIF, test x$have_libexif = xtrue) dnl dnl libv4lconvert dnl AH_TEMPLATE([HAVE_V4LCONVERT], [Do we have libv4lconvert installed?]) V4LCONVERT_REQUIRED="0.5.7" have_v4lconvert=false AC_ARG_ENABLE(lqt, AC_HELP_STRING(--disable-v4lconvert, [Disable libv4lconvert support (default: autodetect)]), [case "${enableval}" in yes) test_v4lconvert=true ;; no) test_v4lconvert=false ;; esac], test_v4lconvert=true) if test x$test_v4lconvert = "xtrue"; then PKG_CHECK_MODULES(V4LCONVERT, libv4lconvert >= $V4LCONVERT_REQUIRED, have_v4lconvert=true, have_v4lconvert=false) fi AM_CONDITIONAL(HAVE_V4LVCONVERT, test x$have_v4lconvert = xtrue) AC_SUBST(V4LCONVERT_REQUIRED) if test x$have_v4lconvert = xtrue; then AC_DEFINE(HAVE_V4LCONVERT) fi dnl dnl Libvisual dnl AH_TEMPLATE([HAVE_LV], [Do we have libvisual installed?]) AH_TEMPLATE([LV_PLUGIN_DIR], [libvisual plugin directory]) LV_REQUIRED="0.4.0" have_LV=false AC_ARG_ENABLE(libvisual, AC_HELP_STRING(--disable-libvisual, [Disable Libvisual support (default: autodetect)]), [case "${enableval}" in yes) test_lv=true ;; no) test_lv=false ;; esac], test_lv=true) if test x$test_lv = "xtrue"; then PKG_CHECK_MODULES(LV, libvisual-0.4 >= $LV_REQUIRED, have_lv=true, have_lv=false) fi if test x$have_lv = "xtrue"; then AC_DEFINE(HAVE_LV) lv_plugin_dir=`pkg-config --variable=pluginsbasedir libvisual-0.4` lv_plugin_dir="$lv_plugin_dir/actor" AC_DEFINE_UNQUOTED(LV_PLUGIN_DIR, ["$lv_plugin_dir"], [libvisual plugin directory]) fi AM_CONDITIONAL(HAVE_LV, test x$have_lv = xtrue) AC_SUBST(LV_REQUIRED) dnl dnl CDrom support dnl have_cdio="false" CDIO_REQUIRED="0.76" AC_ARG_ENABLE(libcdio, [AC_HELP_STRING([--disable-libcdio],[Disable libcdio (default: autodetect)])], [case "${enableval}" in yes) test_cdio=true ;; no) test_cdio=false ;; esac],[test_cdio=true]) if test x$test_cdio = xtrue; then PKG_CHECK_MODULES(CDIO, libcdio >= $CDIO_REQUIRED, have_cdio="true", have_cdio="false") if test x$have_cdio = xtrue; then PKG_CHECK_MODULES(CDIO_CDDA, libcdio_cdda >= $CDIO_REQUIRED, have_cdio="true", have_cdio="false") fi if test x$have_cdio = xtrue; then PKG_CHECK_MODULES(CDIO_PARANOIA, libcdio_paranoia >= $CDIO_REQUIRED, have_cdio="true", have_cdio="false") fi fi AM_CONDITIONAL(HAVE_CDIO, test x$have_cdio = xtrue) AC_SUBST(CDIO_REQUIRED) dnl dnl Musicbrainz dnl AH_TEMPLATE([HAVE_MUSICBRAINZ], [Do we have libmusicbrainz installed?]) MUSICBRAINZ_REQUIRED="2.0.2" have_musicbrainz=false AC_ARG_ENABLE(musicbrainz, AC_HELP_STRING(--disable-musicbrainz, [Disable musicbrainz support (default: autodetect)]), [case "${enableval}" in yes) test_musicbrainz=true ;; no) test_musicbrainz=false ;; esac], test_musicbrainz=true) dnl We check for musicbrainz only if we already detected CDROM support if test x$have_cdio = "xfalse"; then test_musicbrainz=false fi if test x$test_musicbrainz = "xtrue"; then PKG_CHECK_MODULES(MUSICBRAINZ, libmusicbrainz >= $MUSICBRAINZ_REQUIRED, have_musicbrainz=true, have_musicbrainz=false) fi if test x$have_musicbrainz = "xtrue"; then AC_DEFINE(HAVE_MUSICBRAINZ) fi AM_CONDITIONAL(HAVE_MUSICBRAINZ, test x$have_musicbrainz = xtrue) AC_SUBST(MUSICBRAINZ_REQUIRED) dnl dnl Libcddb dnl AH_TEMPLATE([HAVE_LIBCDDB], [Do we have libcddb installed?]) dnl LIBCDDB_REQUIRED="1.2.1" LIBCDDB_REQUIRED="1.0.2" have_cddb=false AC_ARG_ENABLE(cddb, AC_HELP_STRING(--disable-cddb, [Disable cddb support (default: autodetect)]), [case "${enableval}" in yes) test_cddb=true ;; no) test_cddb=false ;; esac], test_cddb=true) dnl We check for cddb only of we already detected CDROM support if test x$have_cdio = "xfalse"; then test_cddb=false fi if test x$test_cddb = "xtrue"; then PKG_CHECK_MODULES(CDDB, libcddb >= $LIBCDDB_REQUIRED, have_cddb=true, have_cddb=false) fi if test x$have_cddb = "xtrue"; then AC_DEFINE(HAVE_LIBCDDB) fi AM_CONDITIONAL(HAVE_LIBCDDB, test x$have_cddb = xtrue) AC_SUBST(LIBCDDB_REQUIRED) dnl dnl ESounD dnl ESD_REQUIRED="0.2.19" have_esd=false AC_ARG_ENABLE(esd, AC_HELP_STRING(--disable-esd, [Disable EsounD (default: autodetect)]), [case "${enableval}" in yes) test_esd=true ;; no) test_esd=false ;; esac], test_esd=true) if test x$test_esd = xtrue; then AM_PATH_ESD($ESD_REQUIRED, have_esd=true, have_esd=false) fi AM_CONDITIONAL(HAVE_ESD, test x$have_esd = xtrue) AC_SUBST(ESD_REQUIRED) dnl dnl ALSA dnl ALSA_REQUIRED="1.0.0" have_alsa="false" OLD_CFLAGS=$CFLAGS OLD_LIBS=$LIBS AC_ARG_ENABLE(alsa, AC_HELP_STRING(--disable-alsa, [Disable Alsa (default: autodetect)]), [case "${enableval}" in yes) test_alsa=true ;; no) test_alsa=false ;; esac], test_alsa=true) if test x$test_alsa = xtrue; then AM_PATH_ALSA(1.0.0, have_alsa="true", have_alsa="false") fi dnl CFLAGS and LIBS must be cleared after AM_PATH_ALSA CFLAGS=$OLD_CFLAGS LIBS=$OLD_LIBS AM_CONDITIONAL(HAVE_ALSA, test x$have_alsa = xtrue) AC_SUBST(ALSA_REQUIRED) dnl dnl Jack dnl have_jack="false" AC_ARG_ENABLE(jack, AC_HELP_STRING(--disable-jack, [Disable Jack (default: autodetect)]), [case "${enableval}" in yes) test_jack=true ;; no) test_jack=false ;; esac], test_jack=true) JACK_REQUIRED="0.109.2" if test x$test_jack = xtrue; then PKG_CHECK_MODULES(JACK, jack >= $JACK_REQUIRED, have_jack="true", have_jack="false") fi AC_SUBST(JACK_REQUIRED) AM_CONDITIONAL(HAVE_JACK, test x$have_jack = xtrue) dnl dnl OSS dnl have_oss=false AC_ARG_ENABLE(oss, AC_HELP_STRING(--disable-oss, [Disable OSS (default: autodetect)]), [case "${enableval}" in yes) test_oss=true ;; no) test_oss=false ;; esac], test_oss=true) if test x$test_oss = xtrue; then AC_CHECK_HEADERS(sys/soundcard.h soundcard.h, have_oss=true) fi AM_CONDITIONAL(HAVE_OSS, test x$have_oss = xtrue) dnl dnl Video4linux dnl AH_TEMPLATE([HAVE_V4L], [Do we have v4l support?]) have_v4l=false AC_ARG_ENABLE(v4l, AC_HELP_STRING(--disable-v4l, [Disable Video4Linux (default: autodetect)]), [case "${enableval}" in yes) test_v4l=true ;; no) test_v4l=false ;; esac], test_v4l=true) if test x$test_v4l = xtrue; then AC_CHECK_HEADERS(linux/videodev.h, have_v4l=true) fi if test x$have_v4l = xtrue; then AC_DEFINE(HAVE_V4L) fi AM_CONDITIONAL(HAVE_V4L, test x$have_v4l = xtrue) dnl dnl Video4linux2 dnl have_v4l2=false AC_ARG_ENABLE(v4l2, AC_HELP_STRING(--disable-v4l2, [Disable Video4Linux (default: autodetect)]), [case "${enableval}" in yes) test_v4l2=true ;; no) test_v4l2=false ;; esac], test_v4l2=true) if test x$test_v4l2 = xtrue; then AC_CHECK_HEADERS(linux/videodev2.h, have_v4l2=true) fi AM_CONDITIONAL(HAVE_V4L2, test x$have_v4l2 = xtrue) dnl dnl libjpeg dnl GMERLIN_CHECK_LIBJPEG dnl dnl png dnl GMERLIN_CHECK_LIBPNG dnl dnl libtiff dnl GMERLIN_CHECK_LIBTIFF dnl dnl inotify dnl GMERLIN_CHECK_INOTIFY dnl dnl Applications dnl dnl Plugin configurator AC_ARG_ENABLE(plugincfg, AC_HELP_STRING(--disable-plugincfg, [Disable plugin configurator (default: enabled)]), [case "${enableval}" in yes) have_plugincfg=true ;; no) have_plugincfg=false ;; esac], have_plugincfg=true) if test "x$have_gtk" != "xtrue"; then have_plugincfg=false fi AM_CONDITIONAL(HAVE_PLUGINCFG, test x$have_plugincfg = xtrue) dnl Alsamixer AC_ARG_ENABLE(alsamixer, AC_HELP_STRING(--disable-alsamixer, [Disable alsamixer (default: enabled)]), [case "${enableval}" in yes) have_alsamixer=true ;; no) have_alsamixer=false ;; esac], have_alsamixer=true) if test "x$have_gtk" != "xtrue" -o "x$have_alsa" = "xfalse"; then have_alsamixer=false fi AM_CONDITIONAL(HAVE_ALSAMIXER, test x$have_alsamixer = xtrue) dnl Player AC_ARG_ENABLE(player, AC_HELP_STRING(--disable-player, [Disable player (default: enabled)]), [case "${enableval}" in yes) have_player=true ;; no) have_player=false ;; esac], have_player=true) if test "x$have_gtk" != "xtrue"; then have_player=false fi AM_CONDITIONAL(HAVE_PLAYER, test x$have_player = xtrue) dnl kbd AC_ARG_ENABLE(kbd, AC_HELP_STRING(--disable-kbd, [Disable keyboard daemon (default: enabled)]), [case "${enableval}" in yes) have_kbd=true ;; no) have_kbd=false ;; esac], have_kbd=true) if test "x$have_gtk" != "xtrue"; then have_kbd=false fi if test "x$have_x" != "xtrue"; then have_kbd=false fi AM_CONDITIONAL(HAVE_KBD, test x$have_kbd = xtrue) dnl Transcoder AC_ARG_ENABLE(transcoder, AC_HELP_STRING(--disable-transcoder, [Disable transcoder (default: enabled)]), [case "${enableval}" in yes) have_transcoder=true ;; no) have_transcoder=false ;; esac], have_transcoder=true) if test "x$have_gtk" = "xfalse"; then have_transcoder=false fi AM_CONDITIONAL(HAVE_TRANSCODER, test x$have_transcoder = xtrue) dnl Recorder AC_ARG_ENABLE(recorder, AC_HELP_STRING(--disable-recorder, [Disable recorder (default: enabled)]), [case "${enableval}" in yes) have_recorder=true ;; no) have_recorder=false ;; esac], have_recorder=true) if test "x$have_gtk" = "xfalse"; then have_recorder=false fi AM_CONDITIONAL(HAVE_RECORDER, test x$have_recorder = xtrue) dnl Visualizer AC_ARG_ENABLE(visualizer, AC_HELP_STRING(--disable-visualizer, [Disable visualizer (default: enabled)]), [case "${enableval}" in yes) have_visualizer=true ;; no) have_visualizer=false ;; esac], have_visualizer=true) if test "x$have_gtk" = "xfalse"; then have_visualizer=false fi AM_CONDITIONAL(HAVE_VISUALIZER, test x$have_visualizer = xtrue) dnl Thumbnailer AC_ARG_ENABLE(thumbnailer, AC_HELP_STRING(--disable-thumbnailer, [Disable thumbnailer (default: enabled)]), [case "${enableval}" in yes) have_thumbnailer=true ;; no) have_thumbnailer=false ;; esac], have_thumbnailer=true) AM_CONDITIONAL(HAVE_THUMBNAILER, test x$have_thumbnailer = xtrue) dnl nmjedit AC_ARG_ENABLE(nmjedit, AC_HELP_STRING(--enable-nmjedit, [Enable nmjedit (default: disabled)]), [case "${enableval}" in yes) have_nmjedit=true ;; no) have_nmjedit=false ;; esac], have_nmjedit=false) if test "x$have_sqlite3" = "xfalse"; then have_nmjedit="false" fi AM_CONDITIONAL(HAVE_NMJEDIT, test "x$have_nmjedit" = "xtrue") dnl dnl CFLAGS dnl LQT_OPT_CFLAGS($host_cpu, ["-O3 -funroll-all-loops -fomit-frame-pointer -ffast-math"]) CFLAGS="$CFLAGS -D_REENTRANT -D_FILE_OFFSET_BITS=64 $GAVL_CFLAGS $OPT_CFLAGS" LQT_TRY_CFLAGS(-Wall, CFLAGS="$CFLAGS -Wall", ) LQT_TRY_CFLAGS(-Wmissing-declarations, CFLAGS="$CFLAGS -Wmissing-declarations", ) LQT_TRY_CFLAGS(-Wdeclaration-after-statement, CFLAGS="$CFLAGS -Wdeclaration-after-statement") dnl dnl Check for SIMD dnl GAVL_CHECK_SIMD($host_cpu, "$OPT_CFLAGS") dnl dnl libxml is necessary for all sources dnl CFLAGS="$CFLAGS $XML2_CFLAGS" LIBS="$GAVL_LIBS" dnl Output variables if test "x$prefix" = xNONE; then prefix="${ac_default_prefix}" fi if test "x$exec_prefix" = xNONE; then exec_prefix="${prefix}" fi AC_DEFINE_UNQUOTED(PREFIX, "$prefix", Installation prefix) INCLUDES='-I$(top_builddir)/include' AC_SUBST(INCLUDES) dnl Link all modules to libgmerlin so we can use them from within plugins MODULE_LIBADD='$(top_builddir)/lib/libgmerlin.la' AC_SUBST(MODULE_LIBADD) dnl Absolute src path for doxygen TOP_SRCDIR=`cd ${srcdir} && pwd` AC_SUBST(TOP_SRCDIR) dnl LDFLAGS for plugins GMERLIN_PLUGIN_LDFLAGS='-export-symbols $(top_srcdir)/plugin.sym' AC_SUBST(GMERLIN_PLUGIN_LDFLAGS) dnl Configuration Subdirectiories AC_CONFIG_FILES([Makefile po/Makefile.in \ gmerlin.spec \ gmerlin.pc \ gmerlin-gtk.pc \ apps/Makefile \ apps/plugincfg/Makefile \ apps/player/Makefile \ apps/alsamixer/Makefile \ apps/cmdlineplayer/Makefile \ apps/cmdlinerecorder/Makefile \ apps/recorder/Makefile \ apps/transcoder/Makefile \ apps/visualizer/Makefile \ apps/kbd/Makefile \ apps/thumbnailer/Makefile \ apps/nmjedit/Makefile \ doc/Makefile \ doc/Doxyfile \ icons/Makefile \ m4/Makefile \ utils/Makefile \ tests/Makefile \ include/Makefile \ include/gmerlin/Makefile \ include/gmerlin/bg_version.h \ include/gui_gtk/Makefile \ include/x11/Makefile \ lib/Makefile \ lib/gtk/Makefile \ lib/x11/Makefile \ osd/Makefile \ plugins/Makefile \ plugins/alsa/Makefile \ plugins/audiofilters/Makefile \ plugins/x11/Makefile \ plugins/cdaudio/Makefile \ plugins/edl/Makefile \ plugins/esd/Makefile \ plugins/gavl/Makefile \ plugins/jack/Makefile \ plugins/lqt/Makefile \ plugins/oss/Makefile \ plugins/jpeg/Makefile \ plugins/mikmod/Makefile \ plugins/png/Makefile \ plugins/postprocessors/Makefile \ plugins/pulseaudio/Makefile \ plugins/subwriters/Makefile \ plugins/image/Makefile \ plugins/tiff/Makefile \ plugins/v4l/Makefile \ plugins/v4l2/Makefile \ plugins/videofilters/Makefile \ plugins/visualization/Makefile \ plugins/wavwrite/Makefile \ skins/Makefile \ skins/Default/Makefile]) AC_OUTPUT echo "=== Libraries: ====================================" echo -n "Gtk-2.0: " if test "x$have_gtk" = "xtrue"; then echo "Yes" else echo "Missing (GUI applications won't be compiled! Go to http://www.gtk.org/)" fi echo echo "=== Plugins: ======================================" echo -n "EsounD: " if test "x$have_esd" = "xtrue"; then echo "Yes (CFLAGS=$ESD_CFLAGS LIBS=$ESD_LIBS)" else if test "x$test_esd" = "xtrue"; then echo "Missing (Go to http://www.tux.org/~ricdude/EsounD.html)" else echo "Disabled" fi fi echo -n "Alsa: " if test "x$have_alsa" = "xtrue"; then echo "Yes (CFLAGS=$ALSA_CFLAGS LIBS=$ALSA_LIBS)" else if test "x$test_alsa" = "xtrue"; then echo "Missing (Go to http://www.alsa-project.org/)" else echo "Disabled" fi fi echo -n "Jack: " if test "x$have_jack" = "xtrue"; then echo "Yes (CFLAGS=$JACK_CFLAGS LIBS=$JACK_LIBS)" else if test "x$test_jack" = "xtrue"; then echo "Missing (Go to http://jackit.sourceforge.net/)" else echo "Disabled" fi fi echo -n "Libquicktime: " if test "x$have_lqt" = "xtrue"; then echo "Yes (CFLAGS=$LQT_CFLAGS LIBS=$LQT_LIBS)" else if test "x$test_lqt" = "xtrue"; then echo "Missing (Go to http://libquicktime.sourceforge.net/)" else echo "Disabled" fi fi echo -n "Libvisual: " if test "x$have_lv" = "xtrue"; then echo "Yes (CFLAGS=$LV_CFLAGS LIBS=$LV_LIBS)" else if test "x$test_lv" = "xtrue"; then echo "Missing (Go to http://libvisual.sourceforge.net/)" else echo "Disabled" fi fi echo -n "Libjpeg: " if test "x$have_libjpeg" = "xtrue"; then echo "Yes (CFLAGS=$JPEG_CFLAGS LIBS=$JPEG_LIBS)" else if test "x$test_libjpeg" = "xtrue"; then echo "Missing (Go to http://www.ijg.org/)" else echo "Disabled" fi fi echo -n "Libpng: " if test "x$have_libpng" = "xtrue"; then echo "Yes (CFLAGS=$PNG_CFLAGS LIBS=$PNG_LIBS)" else if test "x$test_libpng" = "xtrue"; then echo "Missing (Go to http://www.libpng.org/pub/png/libpng.html)" else echo "Disabled" fi fi echo -n "Libtiff: " if test "x$have_libtiff" = "xtrue"; then echo "Yes (CFLAGS=$TIFF_CFLAGS LIBS=$TIFF_LIBS)" else if test "x$test_libtiff" = "xtrue"; then echo "Missing (Go to http://www.remotesensing.org/libtiff/)" else echo "Disabled" fi fi echo -n "pulseaudio: " if test "x$have_pulseaudio" = "xtrue"; then echo "Yes (CFLAGS=$PULSEAUDIO_CFLAGS LIBS=$PULSEAUDIO_LIBS)" else if test "x$test_pulseaudio" = "xtrue"; then echo "Missing (Go to http://www.pulseaudio.org)" else echo "Disabled" fi fi echo -n "OSS: " if test "x$have_oss" = "xtrue"; then echo "Yes" else if test "x$test_oss" = "xtrue"; then echo "Missing (Probably unsupported architecture)" else echo "Disabled" fi fi echo -n "Video4Linux: " if test "x$have_v4l" = "xtrue"; then echo "Yes" else if test "x$test_v4l" = "xtrue"; then echo "Missing (Probably unsupported architecture)" else echo "Disabled" fi fi echo -n "Video4Linux2: " if test "x$have_v4l2" = "xtrue"; then echo "Yes" else if test "x$test_v4l2" = "xtrue"; then echo "Missing (Probably unsupported architecture)" else echo "Disabled" fi fi echo -n "X11: " if test "x$have_x" = "xtrue"; then echo "Yes" else echo "Missing" fi echo -n "OpenGL: " if test "x$have_GL" = "xtrue"; then echo "Yes (CFLAGS=$GL_CFLAGS, LIBS=$GL_LIBS)" else echo "Missing" fi echo -n "GLX: " if test "x$have_GLX" = "xtrue"; then echo "Yes (CFLAGS=$GLX_CFLAGS, LIBS=$GLX_LIBS)" else echo "Missing" fi echo -n "Xinerama: " if test "x$have_xinerama" = "xtrue"; then echo "Yes" else echo "Missing" fi echo -n "Xtest: " if test "x$have_xtest" = "xtrue"; then echo "Yes" else echo "Missing" fi echo -n "Xvideo extension: " if test "x$have_xv" = "xtrue"; then echo "Yes" else echo "Missing" fi echo -n "X11 dpms extension: " if test "x$have_xdpms" = "xtrue"; then echo "Yes" else echo "Missing" fi echo -n "XFixes extension: " if test "x$have_xfixes" = "xtrue"; then echo "Yes" else echo "Missing" fi echo -n "libcdio: " if test "x$have_cdio" = "xtrue"; then echo "Yes (CFLAGS=$CDIO_CFLAGS $CDIO_CDDA_CFLAGS $CDIO_PARANOIA_CFLAGS LIBS=$CDIO_LIBS $CDIO_CDDA_LIBS $CDIO_PARANOIA_LIBS)" else if test "x$test_cdio" = "xtrue"; then echo "Missing (Go to http://www.gnu.org/software/libcdio/)" else echo "Disabled" fi fi echo -n "Musicbrainz: " if test "x$have_musicbrainz" = "xtrue"; then echo "Yes (CFLAGS=$MUSICBRAINZ_CFLAGS LIBS=$MUSICBRAINZ_LIBS)" else if test "x$test_musicbrainz" = "xtrue"; then echo "Missing (Go to http://musicbrainz.org/products/client/index.html)" else echo "Disabled" fi fi echo -n "libcddb: " if test "x$have_cddb" = "xtrue"; then echo "Yes (CFLAGS=$CDDB_CFLAGS LIBS=$CDDB_LIBS)" else if test "x$test_cddb" = "xtrue"; then echo "Missing (Go to http://libcddb.sourceforge.net)" else echo "Disabled" fi fi echo -n "libv4lconvert: " if test "x$have_v4lconvert" = "xtrue"; then echo "Yes (CFLAGS=$V4LCONVERT_CFLAGS LIBS=$V4LCONVERT_LIBS)" else if test "x$test_v4lconvert" = "xtrue"; then echo "Missing (Go to http://people.atrpms.net/~hdegoede/)" else echo "Disabled" fi fi echo -n "libexif: " if test "x$have_libexif" = "xtrue"; then echo "Yes (CFLAGS=$LIBEXIF_CFLAGS LIBS=$LIBEXIF_LIBS)" else echo "Missing (Go to http://libexif.sourceforge.net/)" fi echo echo "=== Applications: =================================" echo -n "Plugin Configurator: " if test "x$have_plugincfg" = "xtrue"; then echo "Enabled" else echo "Disabled" fi echo -n "Alsamixer: " if test "x$have_alsamixer" = "xtrue"; then echo "Enabled" else echo "Disabled" fi echo -n "Player: " if test "x$have_player" = "xtrue"; then echo "Enabled" else echo "Disabled" fi echo -n "Transcoder: " if test "x$have_transcoder" = "xtrue"; then echo "Enabled" else echo "Disabled" fi echo -n "Recorder: " if test "x$have_recorder" = "xtrue"; then echo "Enabled" else echo "Disabled" fi echo -n "Visualizer: " if test "x$have_visualizer" = "xtrue"; then echo "Enabled" else echo "Disabled" fi echo -n "Keyboard daemon: " if test "x$have_kbd" = "xtrue"; then echo "Enabled" else echo "Disabled" fi echo -n "Thumbnailer: " if test "x$have_thumbnailer" = "xtrue"; then echo "Enabled" else echo "Disabled" fi echo -n "nmjedit: " if test "x$have_nmjedit" = "xtrue"; then echo "Enabled" else echo "Disabled" fi echo echo "If you installed a library but it was not detected, check the file INSTALL" echo "for troubleshooting tips. Also note that if the configure script reaches" echo "this point, all missing packages are optional so compilation should succeed" echo "anyway." gmerlin-1.2.0~dfsg/cvs_clean.sh0000755000175000017500000000172711764363414016405 0ustar alessioalessio#!/bin/sh SUBDIRS="m4 doc plugins/cdaudio plugins/subwriters plugins/v4l plugins/alsa plugins/esd plugins/lqt plugins/oss plugins/wavwrite plugins/x11 plugins/tiff plugins/postprocessors plugins/png plugins/mikmod plugins/image plugins/jpeg plugins plugins/tga plugins/vorbis tests include include/gui_gtk icons lib lib/gtk apps apps/player apps/plugincfg apps/alsamixer apps/camelot apps/transcoder skins/Default skins apps/ossmixer osd " make distclean CLEANFILES="Makefile Makefile.in *.o *.lo *.la .libs .deps" TOPCLEANFILES="aclocal.m4 config.guess config.status config.sub configure gmerlin.spec gmerlin.pc libtool ltmain.sh autom4te*.cache depcomp install-sh missing mkinstalldirs Makefile.in" echo "Cleaning up..." for i in $TOPCLEANFILES; do echo "Removing $i" rm -rf $i done for i in $CLEANFILES; do echo "Removing $i" rm -rf $i done for i in $SUBDIRS; do for j in $CLEANFILES; do echo rm -rf $i/$j rm -rf $i/$j done done echo "You can now rerun autogen.sh" gmerlin-1.2.0~dfsg/ABOUT-NLS0000644000175000017500000023523511764363414015343 0ustar alessioalessio1 Notes on the Free Translation Project *************************************** Free software is going international! The Free Translation Project is a way to get maintainers of free software, translators, and users all together, so that free software will gradually become able to speak many languages. A few packages already provide translations for their messages. If you found this `ABOUT-NLS' file inside a distribution, you may assume that the distributed package does use GNU `gettext' internally, itself available at your nearest GNU archive site. But you do _not_ need to install GNU `gettext' prior to configuring, installing or using this package with messages translated. Installers will find here some useful hints. These notes also explain how users should proceed for getting the programs to use the available translations. They tell how people wanting to contribute and work on translations can contact the appropriate team. When reporting bugs in the `intl/' directory or bugs which may be related to internationalization, you should tell about the version of `gettext' which is used. The information can be found in the `intl/VERSION' file, in internationalized packages. 1.1 Quick configuration advice ============================== If you want to exploit the full power of internationalization, you should configure it using ./configure --with-included-gettext to force usage of internationalizing routines provided within this package, despite the existence of internationalizing capabilities in the operating system where this package is being installed. So far, only the `gettext' implementation in the GNU C library version 2 provides as many features (such as locale alias, message inheritance, automatic charset conversion or plural form handling) as the implementation here. It is also not possible to offer this additional functionality on top of a `catgets' implementation. Future versions of GNU `gettext' will very likely convey even more functionality. So it might be a good idea to change to GNU `gettext' as soon as possible. So you need _not_ provide this option if you are using GNU libc 2 or you have installed a recent copy of the GNU gettext package with the included `libintl'. 1.2 INSTALL Matters =================== Some packages are "localizable" when properly installed; the programs they contain can be made to speak your own native language. Most such packages use GNU `gettext'. Other packages have their own ways to internationalization, predating GNU `gettext'. By default, this package will be installed to allow translation of messages. It will automatically detect whether the system already provides the GNU `gettext' functions. If not, the included GNU `gettext' library will be used. This library is wholly contained within this package, usually in the `intl/' subdirectory, so prior installation of the GNU `gettext' package is _not_ required. Installers may use special options at configuration time for changing the default behaviour. The commands: ./configure --with-included-gettext ./configure --disable-nls will, respectively, bypass any pre-existing `gettext' to use the internationalizing routines provided within this package, or else, _totally_ disable translation of messages. When you already have GNU `gettext' installed on your system and run configure without an option for your new package, `configure' will probably detect the previously built and installed `libintl.a' file and will decide to use this. This might not be desirable. You should use the more recent version of the GNU `gettext' library. I.e. if the file `intl/VERSION' shows that the library which comes with this package is more recent, you should use ./configure --with-included-gettext to prevent auto-detection. The configuration process will not test for the `catgets' function and therefore it will not be used. The reason is that even an emulation of `gettext' on top of `catgets' could not provide all the extensions of the GNU `gettext' library. Internationalized packages usually have many `po/LL.po' files, where LL gives an ISO 639 two-letter code identifying the language. Unless translations have been forbidden at `configure' time by using the `--disable-nls' switch, all available translations are installed together with the package. However, the environment variable `LINGUAS' may be set, prior to configuration, to limit the installed set. `LINGUAS' should then contain a space separated list of two-letter codes, stating which languages are allowed. 1.3 Using This Package ====================== As a user, if your language has been installed for this package, you only have to set the `LANG' environment variable to the appropriate `LL_CC' combination. Here `LL' is an ISO 639 two-letter language code, and `CC' is an ISO 3166 two-letter country code. For example, let's suppose that you speak German and live in Germany. At the shell prompt, merely execute `setenv LANG de_DE' (in `csh'), `export LANG; LANG=de_DE' (in `sh') or `export LANG=de_DE' (in `bash'). This can be done from your `.login' or `.profile' file, once and for all. You might think that the country code specification is redundant. But in fact, some languages have dialects in different countries. For example, `de_AT' is used for Austria, and `pt_BR' for Brazil. The country code serves to distinguish the dialects. The locale naming convention of `LL_CC', with `LL' denoting the language and `CC' denoting the country, is the one use on systems based on GNU libc. On other systems, some variations of this scheme are used, such as `LL' or `LL_CC.ENCODING'. You can get the list of locales supported by your system for your language by running the command `locale -a | grep '^LL''. Not all programs have translations for all languages. By default, an English message is shown in place of a nonexistent translation. If you understand other languages, you can set up a priority list of languages. This is done through a different environment variable, called `LANGUAGE'. GNU `gettext' gives preference to `LANGUAGE' over `LANG' for the purpose of message handling, but you still need to have `LANG' set to the primary language; this is required by other parts of the system libraries. For example, some Swedish users who would rather read translations in German than English for when Swedish is not available, set `LANGUAGE' to `sv:de' while leaving `LANG' to `sv_SE'. Special advice for Norwegian users: The language code for Norwegian bokma*l changed from `no' to `nb' recently (in 2003). During the transition period, while some message catalogs for this language are installed under `nb' and some older ones under `no', it's recommended for Norwegian users to set `LANGUAGE' to `nb:no' so that both newer and older translations are used. In the `LANGUAGE' environment variable, but not in the `LANG' environment variable, `LL_CC' combinations can be abbreviated as `LL' to denote the language's main dialect. For example, `de' is equivalent to `de_DE' (German as spoken in Germany), and `pt' to `pt_PT' (Portuguese as spoken in Portugal) in this context. 1.4 Translating Teams ===================== For the Free Translation Project to be a success, we need interested people who like their own language and write it well, and who are also able to synergize with other translators speaking the same language. Each translation team has its own mailing list. The up-to-date list of teams can be found at the Free Translation Project's homepage, `http://www.iro.umontreal.ca/contrib/po/HTML/', in the "National teams" area. If you'd like to volunteer to _work_ at translating messages, you should become a member of the translating team for your own language. The subscribing address is _not_ the same as the list itself, it has `-request' appended. For example, speakers of Swedish can send a message to `sv-request@li.org', having this message body: subscribe Keep in mind that team members are expected to participate _actively_ in translations, or at solving translational difficulties, rather than merely lurking around. If your team does not exist yet and you want to start one, or if you are unsure about what to do or how to get started, please write to `translation@iro.umontreal.ca' to reach the coordinator for all translator teams. The English team is special. It works at improving and uniformizing the terminology in use. Proven linguistic skill are praised more than programming skill, here. 1.5 Available Packages ====================== Languages are not equally supported in all packages. The following matrix shows the current state of internationalization, as of July 2006. The matrix shows, in regard of each package, for which languages PO files have been submitted to translation coordination, with a translation percentage of at least 50%. Ready PO files af am ar az be bg bs ca cs cy da de el en en_GB eo +----------------------------------------------------+ GNUnet | [] | a2ps | [] [] [] [] [] | aegis | () | ant-phone | () | anubis | [] | ap-utils | | aspell | [] [] [] [] | bash | [] [] [] | batchelor | [] | bfd | | bibshelf | [] | binutils | [] | bison | [] [] | bison-runtime | [] | bluez-pin | [] [] [] [] [] | cflow | [] | clisp | [] [] | console-tools | [] [] | coreutils | [] [] [] [] | cpio | | cpplib | [] [] [] | cryptonit | [] | darkstat | [] () [] | dialog | [] [] [] [] [] [] | diffutils | [] [] [] [] [] [] | doodle | [] | e2fsprogs | [] [] | enscript | [] [] [] [] | error | [] [] [] [] | fetchmail | [] [] () [] | fileutils | [] [] | findutils | [] [] [] | flex | [] [] [] | fslint | [] | gas | | gawk | [] [] [] | gbiff | [] | gcal | [] | gcc | [] | gettext-examples | [] [] [] [] [] | gettext-runtime | [] [] [] [] [] | gettext-tools | [] [] | gimp-print | [] [] [] [] | gip | [] | gliv | [] | glunarclock | [] | gmult | [] [] | gnubiff | () | gnucash | () () [] | gnucash-glossary | [] () | gnuedu | | gnulib | [] [] [] [] [] [] | gnunet-gtk | | gnutls | | gpe-aerial | [] [] | gpe-beam | [] [] | gpe-calendar | [] [] | gpe-clock | [] [] | gpe-conf | [] [] | gpe-contacts | | gpe-edit | [] | gpe-filemanager | | gpe-go | [] | gpe-login | [] [] | gpe-ownerinfo | [] [] | gpe-package | | gpe-sketchbook | [] [] | gpe-su | [] [] | gpe-taskmanager | [] [] | gpe-timesheet | [] | gpe-today | [] [] | gpe-todo | | gphoto2 | [] [] [] [] | gprof | [] [] | gpsdrive | () () | gramadoir | [] [] | grep | [] [] [] [] [] [] | gretl | | gsasl | | gss | | gst-plugins | [] [] [] [] | gst-plugins-base | [] [] [] | gst-plugins-good | [] [] [] [] [] [] [] | gstreamer | [] [] [] [] [] [] [] | gtick | [] () | gtkam | [] [] [] | gtkorphan | [] [] | gtkspell | [] [] [] [] | gutenprint | [] | hello | [] [] [] [] [] | id-utils | [] [] | impost | | indent | [] [] [] | iso_3166 | [] [] | iso_3166_1 | [] [] [] [] [] | iso_3166_2 | | iso_3166_3 | [] | iso_4217 | [] | iso_639 | [] [] | jpilot | [] | jtag | | jwhois | | kbd | [] [] [] [] | keytouch | | keytouch-editor | | keytouch-keyboa... | | latrine | () | ld | [] | leafpad | [] [] [] [] [] | libc | [] [] [] [] [] | libexif | [] | libextractor | [] | libgpewidget | [] [] [] | libgpg-error | [] | libgphoto2 | [] [] | libgphoto2_port | [] [] | libgsasl | | libiconv | [] [] | libidn | [] [] | lifelines | [] () | lilypond | [] | lingoteach | | lynx | [] [] [] [] | m4 | [] [] [] [] | mailutils | [] | make | [] [] | man-db | [] () [] [] | minicom | [] [] [] | mysecretdiary | [] [] | nano | [] [] () [] | nano_1_0 | [] () [] [] | opcodes | [] | parted | | pilot-qof | [] | psmisc | [] | pwdutils | | python | | qof | | radius | [] | recode | [] [] [] [] [] [] | rpm | [] [] | screem | | scrollkeeper | [] [] [] [] [] [] [] [] | sed | [] [] [] | sh-utils | [] [] | shared-mime-info | [] [] [] | sharutils | [] [] [] [] [] [] | shishi | | silky | | skencil | [] () | sketch | [] () | solfege | | soundtracker | [] [] | sp | [] | stardict | [] | system-tools-ba... | [] [] [] [] [] [] [] [] [] | tar | [] | texinfo | [] [] [] | textutils | [] [] [] | tin | () () | tp-robot | [] | tuxpaint | [] [] [] [] [] | unicode-han-tra... | | unicode-transla... | | util-linux | [] [] [] [] | vorbis-tools | [] [] [] [] | wastesedge | () | wdiff | [] [] [] [] | wget | [] [] | xchat | [] [] [] [] [] | xkeyboard-config | | xpad | [] [] | +----------------------------------------------------+ af am ar az be bg bs ca cs cy da de el en en_GB eo 11 0 1 2 8 21 1 42 43 2 62 99 18 1 16 16 es et eu fa fi fr ga gl gu he hi hr hu id is it +--------------------------------------------------+ GNUnet | | a2ps | [] [] [] () | aegis | | ant-phone | [] | anubis | [] | ap-utils | [] [] | aspell | [] [] [] | bash | [] [] [] | batchelor | [] [] | bfd | [] | bibshelf | [] [] [] | binutils | [] [] [] | bison | [] [] [] [] [] [] | bison-runtime | [] [] [] [] [] | bluez-pin | [] [] [] [] [] | cflow | | clisp | [] [] | console-tools | | coreutils | [] [] [] [] [] [] | cpio | [] [] [] | cpplib | [] [] | cryptonit | [] | darkstat | [] () [] [] [] | dialog | [] [] [] [] [] [] [] [] | diffutils | [] [] [] [] [] [] [] [] [] | doodle | [] [] | e2fsprogs | [] [] [] | enscript | [] [] [] | error | [] [] [] [] [] | fetchmail | [] | fileutils | [] [] [] [] [] [] | findutils | [] [] [] [] | flex | [] [] [] | fslint | [] | gas | [] [] | gawk | [] [] [] [] | gbiff | [] | gcal | [] [] | gcc | [] | gettext-examples | [] [] [] [] [] | gettext-runtime | [] [] [] [] [] [] | gettext-tools | [] [] [] | gimp-print | [] [] | gip | [] [] [] | gliv | () | glunarclock | [] [] [] | gmult | [] [] [] | gnubiff | () () | gnucash | () () () | gnucash-glossary | [] [] | gnuedu | [] | gnulib | [] [] [] [] [] [] [] [] | gnunet-gtk | | gnutls | | gpe-aerial | [] [] | gpe-beam | [] [] | gpe-calendar | [] [] [] [] | gpe-clock | [] [] [] [] | gpe-conf | [] | gpe-contacts | [] [] | gpe-edit | [] [] [] [] | gpe-filemanager | [] | gpe-go | [] [] [] | gpe-login | [] [] [] | gpe-ownerinfo | [] [] [] [] [] | gpe-package | [] | gpe-sketchbook | [] [] | gpe-su | [] [] [] [] | gpe-taskmanager | [] [] [] | gpe-timesheet | [] [] [] [] | gpe-today | [] [] [] [] | gpe-todo | [] | gphoto2 | [] [] [] [] [] | gprof | [] [] [] [] | gpsdrive | () () [] () | gramadoir | [] [] | grep | [] [] [] [] [] [] [] [] [] [] [] [] | gretl | [] [] [] | gsasl | [] | gss | [] | gst-plugins | [] [] [] | gst-plugins-base | [] [] | gst-plugins-good | [] [] [] | gstreamer | [] [] [] | gtick | [] [] [] [] [] | gtkam | [] [] [] [] | gtkorphan | [] [] | gtkspell | [] [] [] [] [] [] | gutenprint | [] | hello | [] [] [] [] [] [] [] [] [] [] [] [] [] | id-utils | [] [] [] [] [] | impost | [] [] | indent | [] [] [] [] [] [] [] [] [] [] | iso_3166 | [] [] [] | iso_3166_1 | [] [] [] [] [] [] [] | iso_3166_2 | [] | iso_3166_3 | [] | iso_4217 | [] [] [] [] | iso_639 | [] [] [] [] [] | jpilot | [] [] | jtag | [] | jwhois | [] [] [] [] [] | kbd | [] [] | keytouch | [] | keytouch-editor | [] | keytouch-keyboa... | [] | latrine | [] [] [] | ld | [] [] | leafpad | [] [] [] [] [] [] | libc | [] [] [] [] [] | libexif | [] | libextractor | [] | libgpewidget | [] [] [] [] [] | libgpg-error | | libgphoto2 | [] [] [] | libgphoto2_port | [] [] | libgsasl | [] [] | libiconv | [] | libidn | [] [] | lifelines | () | lilypond | [] | lingoteach | [] [] [] | lynx | [] [] [] | m4 | [] [] [] [] | mailutils | [] [] | make | [] [] [] [] [] [] [] [] | man-db | () | minicom | [] [] [] [] | mysecretdiary | [] [] [] | nano | [] () [] [] [] [] | nano_1_0 | [] [] [] [] [] | opcodes | [] [] [] [] | parted | [] [] [] [] | pilot-qof | | psmisc | [] [] [] | pwdutils | | python | | qof | | radius | [] [] | recode | [] [] [] [] [] [] [] [] | rpm | [] [] | screem | | scrollkeeper | [] [] [] | sed | [] [] [] [] [] | sh-utils | [] [] [] [] [] [] [] | shared-mime-info | [] [] [] [] [] [] | sharutils | [] [] [] [] [] [] [] [] | shishi | | silky | [] | skencil | [] [] | sketch | [] [] | solfege | [] | soundtracker | [] [] [] | sp | [] | stardict | [] | system-tools-ba... | [] [] [] [] [] [] [] [] | tar | [] [] [] [] [] [] | texinfo | [] [] | textutils | [] [] [] [] [] | tin | [] () | tp-robot | [] [] [] [] | tuxpaint | [] [] | unicode-han-tra... | | unicode-transla... | [] [] | util-linux | [] [] [] [] [] [] [] | vorbis-tools | [] [] | wastesedge | () | wdiff | [] [] [] [] [] [] [] [] | wget | [] [] [] [] [] [] [] [] | xchat | [] [] [] [] [] [] [] [] | xkeyboard-config | [] [] [] [] | xpad | [] [] [] | +--------------------------------------------------+ es et eu fa fi fr ga gl gu he hi hr hu id is it 89 21 16 2 41 119 61 14 1 8 1 6 61 30 0 53 ja ko ku ky lg lt lv mk mn ms mt nb ne nl nn no +--------------------------------------------------+ GNUnet | | a2ps | () [] [] () | aegis | () | ant-phone | [] | anubis | [] [] [] | ap-utils | [] | aspell | [] [] | bash | [] | batchelor | [] [] | bfd | | bibshelf | [] | binutils | | bison | [] [] [] | bison-runtime | [] [] [] | bluez-pin | [] [] [] | cflow | | clisp | [] | console-tools | | coreutils | [] | cpio | | cpplib | [] | cryptonit | [] | darkstat | [] [] | dialog | [] [] | diffutils | [] [] [] | doodle | | e2fsprogs | [] | enscript | [] | error | [] | fetchmail | [] [] | fileutils | [] [] | findutils | [] | flex | [] [] | fslint | [] [] | gas | | gawk | [] [] | gbiff | [] | gcal | | gcc | | gettext-examples | [] [] | gettext-runtime | [] [] [] | gettext-tools | [] [] | gimp-print | [] [] | gip | [] [] | gliv | [] | glunarclock | [] [] | gmult | [] [] | gnubiff | | gnucash | () () | gnucash-glossary | [] | gnuedu | | gnulib | [] [] [] [] | gnunet-gtk | | gnutls | | gpe-aerial | [] | gpe-beam | [] | gpe-calendar | [] | gpe-clock | [] [] | gpe-conf | [] [] | gpe-contacts | [] | gpe-edit | [] [] | gpe-filemanager | [] | gpe-go | [] [] | gpe-login | [] [] | gpe-ownerinfo | [] | gpe-package | [] | gpe-sketchbook | [] [] | gpe-su | [] [] | gpe-taskmanager | [] [] [] | gpe-timesheet | [] | gpe-today | [] | gpe-todo | | gphoto2 | [] [] | gprof | | gpsdrive | () () () | gramadoir | () | grep | [] [] [] | gretl | | gsasl | [] | gss | | gst-plugins | [] | gst-plugins-base | | gst-plugins-good | [] | gstreamer | [] | gtick | [] | gtkam | [] | gtkorphan | [] | gtkspell | [] [] | gutenprint | | hello | [] [] [] [] [] [] [] [] | id-utils | [] | impost | | indent | [] [] | iso_3166 | [] | iso_3166_1 | [] [] | iso_3166_2 | [] | iso_3166_3 | [] | iso_4217 | [] [] [] | iso_639 | [] [] | jpilot | () () () | jtag | | jwhois | [] | kbd | [] | keytouch | [] | keytouch-editor | | keytouch-keyboa... | | latrine | [] | ld | | leafpad | [] [] | libc | [] [] [] [] [] | libexif | | libextractor | | libgpewidget | [] | libgpg-error | | libgphoto2 | [] | libgphoto2_port | [] | libgsasl | [] | libiconv | | libidn | [] [] | lifelines | [] | lilypond | | lingoteach | [] | lynx | [] [] | m4 | [] [] | mailutils | | make | [] [] [] | man-db | () | minicom | [] | mysecretdiary | [] | nano | [] [] [] | nano_1_0 | [] [] [] | opcodes | [] | parted | [] [] | pilot-qof | | psmisc | [] [] [] | pwdutils | | python | | qof | | radius | | recode | [] | rpm | [] [] | screem | [] | scrollkeeper | [] [] [] [] | sed | [] [] | sh-utils | [] [] | shared-mime-info | [] [] [] [] [] | sharutils | [] [] | shishi | | silky | [] | skencil | | sketch | | solfege | | soundtracker | | sp | () | stardict | [] [] | system-tools-ba... | [] [] [] [] | tar | [] [] [] | texinfo | [] [] [] | textutils | [] [] [] | tin | | tp-robot | [] | tuxpaint | [] | unicode-han-tra... | | unicode-transla... | | util-linux | [] [] | vorbis-tools | [] | wastesedge | [] | wdiff | [] [] | wget | [] [] | xchat | [] [] [] [] | xkeyboard-config | [] | xpad | [] [] [] | +--------------------------------------------------+ ja ko ku ky lg lt lv mk mn ms mt nb ne nl nn no 40 24 2 1 1 3 1 2 3 21 0 15 1 101 5 3 nso or pa pl pt pt_BR rm ro ru rw sk sl sq sr sv ta +------------------------------------------------------+ GNUnet | | a2ps | () [] [] [] [] [] [] | aegis | () () | ant-phone | [] [] | anubis | [] [] [] | ap-utils | () | aspell | [] [] | bash | [] [] [] | batchelor | [] [] | bfd | | bibshelf | [] | binutils | [] [] | bison | [] [] [] [] [] | bison-runtime | [] [] [] [] | bluez-pin | [] [] [] [] [] [] [] [] [] | cflow | [] | clisp | [] | console-tools | [] | coreutils | [] [] [] [] | cpio | [] [] [] | cpplib | [] | cryptonit | [] [] | darkstat | [] [] [] [] [] [] | dialog | [] [] [] [] [] [] [] [] [] | diffutils | [] [] [] [] [] [] | doodle | [] [] | e2fsprogs | [] [] | enscript | [] [] [] [] [] | error | [] [] [] [] | fetchmail | [] [] [] | fileutils | [] [] [] [] [] | findutils | [] [] [] [] [] [] | flex | [] [] [] [] [] | fslint | [] [] [] [] | gas | | gawk | [] [] [] [] | gbiff | [] | gcal | [] | gcc | [] | gettext-examples | [] [] [] [] [] [] [] [] | gettext-runtime | [] [] [] [] [] [] [] [] | gettext-tools | [] [] [] [] [] [] [] | gimp-print | [] [] | gip | [] [] [] [] | gliv | [] [] [] [] | glunarclock | [] [] [] [] [] [] | gmult | [] [] [] [] | gnubiff | () | gnucash | () [] | gnucash-glossary | [] [] [] | gnuedu | | gnulib | [] [] [] [] [] | gnunet-gtk | [] | gnutls | [] [] | gpe-aerial | [] [] [] [] [] [] [] | gpe-beam | [] [] [] [] [] [] [] | gpe-calendar | [] [] [] [] [] [] [] [] | gpe-clock | [] [] [] [] [] [] [] [] | gpe-conf | [] [] [] [] [] [] [] | gpe-contacts | [] [] [] [] [] | gpe-edit | [] [] [] [] [] [] [] [] | gpe-filemanager | [] [] | gpe-go | [] [] [] [] [] [] | gpe-login | [] [] [] [] [] [] [] [] | gpe-ownerinfo | [] [] [] [] [] [] [] [] | gpe-package | [] [] | gpe-sketchbook | [] [] [] [] [] [] [] [] | gpe-su | [] [] [] [] [] [] [] [] | gpe-taskmanager | [] [] [] [] [] [] [] [] | gpe-timesheet | [] [] [] [] [] [] [] [] | gpe-today | [] [] [] [] [] [] [] [] | gpe-todo | [] [] [] [] | gphoto2 | [] [] [] [] [] | gprof | [] [] [] | gpsdrive | [] [] [] | gramadoir | [] [] | grep | [] [] [] [] [] [] [] [] | gretl | [] | gsasl | [] [] | gss | [] [] [] | gst-plugins | [] [] [] [] | gst-plugins-base | [] | gst-plugins-good | [] [] [] [] | gstreamer | [] [] [] | gtick | [] [] [] | gtkam | [] [] [] [] | gtkorphan | [] | gtkspell | [] [] [] [] [] [] [] [] | gutenprint | [] | hello | [] [] [] [] [] [] [] [] | id-utils | [] [] [] [] | impost | [] | indent | [] [] [] [] [] [] | iso_3166 | [] [] [] [] [] [] | iso_3166_1 | [] [] [] [] | iso_3166_2 | | iso_3166_3 | [] [] [] [] | iso_4217 | [] [] [] [] | iso_639 | [] [] [] [] | jpilot | | jtag | [] | jwhois | [] [] [] [] | kbd | [] [] [] | keytouch | [] | keytouch-editor | [] | keytouch-keyboa... | [] | latrine | [] [] | ld | [] | leafpad | [] [] [] [] [] [] | libc | [] [] [] [] [] | libexif | [] | libextractor | [] [] | libgpewidget | [] [] [] [] [] [] [] | libgpg-error | [] [] | libgphoto2 | [] | libgphoto2_port | [] [] [] | libgsasl | [] [] [] [] | libiconv | | libidn | [] [] () | lifelines | [] [] | lilypond | | lingoteach | [] | lynx | [] [] [] | m4 | [] [] [] [] [] | mailutils | [] [] [] [] | make | [] [] [] [] | man-db | [] [] | minicom | [] [] [] [] [] | mysecretdiary | [] [] [] [] | nano | [] [] | nano_1_0 | [] [] [] [] | opcodes | [] [] | parted | [] | pilot-qof | [] | psmisc | [] [] | pwdutils | [] [] | python | | qof | [] | radius | [] [] | recode | [] [] [] [] [] [] [] | rpm | [] [] [] [] | screem | | scrollkeeper | [] [] [] [] [] [] [] | sed | [] [] [] [] [] [] [] [] [] | sh-utils | [] [] [] | shared-mime-info | [] [] [] [] [] | sharutils | [] [] [] [] | shishi | [] | silky | [] | skencil | [] [] [] | sketch | [] [] [] | solfege | [] | soundtracker | [] [] | sp | | stardict | [] [] [] | system-tools-ba... | [] [] [] [] [] [] [] [] [] | tar | [] [] [] [] [] | texinfo | [] [] [] [] | textutils | [] [] [] | tin | () | tp-robot | [] | tuxpaint | [] [] [] [] [] | unicode-han-tra... | | unicode-transla... | | util-linux | [] [] [] [] | vorbis-tools | [] [] | wastesedge | | wdiff | [] [] [] [] [] [] | wget | [] [] [] [] | xchat | [] [] [] [] [] [] [] | xkeyboard-config | [] [] | xpad | [] [] [] | +------------------------------------------------------+ nso or pa pl pt pt_BR rm ro ru rw sk sl sq sr sv ta 0 2 3 58 31 53 5 76 72 5 42 48 12 51 130 2 tg th tk tr uk ven vi wa xh zh_CN zh_HK zh_TW zu +---------------------------------------------------+ GNUnet | [] | 2 a2ps | [] [] [] | 19 aegis | | 0 ant-phone | [] [] | 6 anubis | [] [] [] | 11 ap-utils | () [] | 4 aspell | [] [] [] | 14 bash | [] | 11 batchelor | [] [] | 9 bfd | | 1 bibshelf | [] | 7 binutils | [] [] [] | 9 bison | [] [] [] | 19 bison-runtime | [] [] [] | 16 bluez-pin | [] [] [] [] [] [] | 28 cflow | [] [] | 4 clisp | | 6 console-tools | [] [] | 5 coreutils | [] [] | 17 cpio | [] [] [] | 9 cpplib | [] [] [] [] | 11 cryptonit | | 5 darkstat | [] () () | 15 dialog | [] [] [] [] [] | 30 diffutils | [] [] [] [] | 28 doodle | [] | 6 e2fsprogs | [] [] | 10 enscript | [] [] [] | 16 error | [] [] [] [] | 18 fetchmail | [] [] | 12 fileutils | [] [] [] | 18 findutils | [] [] [] | 17 flex | [] [] | 15 fslint | [] | 9 gas | [] | 3 gawk | [] [] | 15 gbiff | [] | 5 gcal | [] | 5 gcc | [] [] [] | 6 gettext-examples | [] [] [] [] [] [] | 26 gettext-runtime | [] [] [] [] [] [] | 28 gettext-tools | [] [] [] [] [] | 19 gimp-print | [] [] | 12 gip | [] [] | 12 gliv | [] [] | 8 glunarclock | [] [] [] | 15 gmult | [] [] [] [] | 15 gnubiff | [] | 1 gnucash | () | 2 gnucash-glossary | [] [] | 9 gnuedu | [] | 2 gnulib | [] [] [] [] [] | 28 gnunet-gtk | | 1 gnutls | | 2 gpe-aerial | [] [] | 14 gpe-beam | [] [] | 14 gpe-calendar | [] [] [] [] | 19 gpe-clock | [] [] [] [] | 20 gpe-conf | [] [] | 14 gpe-contacts | [] [] | 10 gpe-edit | [] [] [] [] | 19 gpe-filemanager | [] | 5 gpe-go | [] [] | 14 gpe-login | [] [] [] [] [] | 20 gpe-ownerinfo | [] [] [] [] | 20 gpe-package | [] | 5 gpe-sketchbook | [] [] | 16 gpe-su | [] [] [] | 19 gpe-taskmanager | [] [] [] | 19 gpe-timesheet | [] [] [] [] | 18 gpe-today | [] [] [] [] [] | 20 gpe-todo | [] | 6 gphoto2 | [] [] [] [] | 20 gprof | [] [] | 11 gpsdrive | | 4 gramadoir | [] | 7 grep | [] [] [] [] | 33 gretl | | 4 gsasl | [] [] | 6 gss | [] | 5 gst-plugins | [] [] [] | 15 gst-plugins-base | [] [] [] | 9 gst-plugins-good | [] [] [] | 18 gstreamer | [] [] [] | 17 gtick | [] | 11 gtkam | [] | 13 gtkorphan | [] | 7 gtkspell | [] [] [] [] [] [] | 26 gutenprint | | 3 hello | [] [] [] [] [] | 39 id-utils | [] [] | 14 impost | [] | 4 indent | [] [] [] [] | 25 iso_3166 | [] [] [] | 15 iso_3166_1 | [] [] | 20 iso_3166_2 | | 2 iso_3166_3 | [] [] | 9 iso_4217 | [] [] | 14 iso_639 | [] | 14 jpilot | [] [] [] [] | 7 jtag | [] | 3 jwhois | [] [] [] | 13 kbd | [] [] | 12 keytouch | [] | 4 keytouch-editor | | 2 keytouch-keyboa... | | 2 latrine | [] [] | 8 ld | [] [] [] [] | 8 leafpad | [] [] [] [] | 23 libc | [] [] [] | 23 libexif | [] | 4 libextractor | [] | 5 libgpewidget | [] [] [] | 19 libgpg-error | [] | 4 libgphoto2 | [] | 8 libgphoto2_port | [] [] [] | 11 libgsasl | [] | 8 libiconv | [] | 4 libidn | [] [] | 10 lifelines | | 4 lilypond | | 2 lingoteach | [] | 6 lynx | [] [] [] | 15 m4 | [] [] [] | 18 mailutils | [] | 8 make | [] [] [] | 20 man-db | [] | 6 minicom | [] | 14 mysecretdiary | [] [] | 12 nano | [] [] | 15 nano_1_0 | [] [] [] | 18 opcodes | [] [] | 10 parted | [] [] [] | 10 pilot-qof | [] | 3 psmisc | [] | 10 pwdutils | [] | 3 python | | 0 qof | [] | 2 radius | [] | 6 recode | [] [] [] | 25 rpm | [] [] [] [] | 14 screem | [] | 2 scrollkeeper | [] [] [] [] | 26 sed | [] [] [] | 22 sh-utils | [] | 15 shared-mime-info | [] [] [] [] | 23 sharutils | [] [] [] | 23 shishi | | 1 silky | [] | 4 skencil | [] | 7 sketch | | 6 solfege | | 2 soundtracker | [] [] | 9 sp | [] | 3 stardict | [] [] [] [] | 11 system-tools-ba... | [] [] [] [] [] [] [] | 37 tar | [] [] [] [] | 19 texinfo | [] [] [] | 15 textutils | [] [] [] | 17 tin | | 1 tp-robot | [] [] [] | 10 tuxpaint | [] [] [] | 16 unicode-han-tra... | | 0 unicode-transla... | | 2 util-linux | [] [] [] | 20 vorbis-tools | [] [] | 11 wastesedge | | 1 wdiff | [] [] | 22 wget | [] [] [] | 19 xchat | [] [] [] [] | 28 xkeyboard-config | [] [] [] [] | 11 xpad | [] [] [] | 14 +---------------------------------------------------+ 77 teams tg th tk tr uk ven vi wa xh zh_CN zh_HK zh_TW zu 172 domains 0 1 1 78 39 0 135 13 1 50 3 54 0 2054 Some counters in the preceding matrix are higher than the number of visible blocks let us expect. This is because a few extra PO files are used for implementing regional variants of languages, or language dialects. For a PO file in the matrix above to be effective, the package to which it applies should also have been internationalized and distributed as such by its maintainer. There might be an observable lag between the mere existence a PO file and its wide availability in a distribution. If July 2006 seems to be old, you may fetch a more recent copy of this `ABOUT-NLS' file on most GNU archive sites. The most up-to-date matrix with full percentage details can be found at `http://www.iro.umontreal.ca/contrib/po/HTML/matrix.html'. 1.6 Using `gettext' in new packages =================================== If you are writing a freely available program and want to internationalize it you are welcome to use GNU `gettext' in your package. Of course you have to respect the GNU Library General Public License which covers the use of the GNU `gettext' library. This means in particular that even non-free programs can use `libintl' as a shared library, whereas only free software can use `libintl' as a static library or use modified versions of `libintl'. Once the sources are changed appropriately and the setup can handle the use of `gettext' the only thing missing are the translations. The Free Translation Project is also available for packages which are not developed inside the GNU project. Therefore the information given above applies also for every other Free Software Project. Contact `translation@iro.umontreal.ca' to make the `.pot' files available to the translation teams. gmerlin-1.2.0~dfsg/README0000644000175000017500000000434611764363414014771 0ustar alessioalessioThis is gmerlin, a set of multimedia libraries bundled with an application suite. For documentation, check the file doc/usersguide.html. This file won't get installed as the final format of gmerlin documentation isn't decided yet. This package contains the core libraries, some plugins and most applications. For installation instructions and troubleshooting tips, read the file INSTALL. For instructions how to install the whole suite of gmerlin packages including the depdencies, check the file doc/usersguide.html. The following applications are included in this package: - Player: Just type gmerlin to start this. It's a media player with a mediatree where you can store your media collection in virtual directories (albums). In the tree window and in the album windows, right-click and context sensitive menus will tell you your options. There are also tooltips helping you through the software. To toggle between fullscreen and windowed playback, press the TAB key while the mouse is in the video window. - Transcoder: Type gmerlin_transcoder to start this. It works very simple: First, add tracks to the tasklist. Then, edit options (Metadata, encoder settings...) for each track. The task list can then be saved for later use. After all tracks are configured, start transcoding. - Alsamixer: Type gmerlin_alsamixer to start this. It's a mixer application which handles 100s of mixer controls without needing too much desktop space. Right click onto the controls, and you can reorder them. You can also move important controls to separate windows and iconify the main window after. Supported are an arbitrary number of soundcards with an arbitrary number of controls each. - Camelot: A small and simple webcam application. It lets you save webcam images either manually or automatically. - Plugin configurator: If you want to write a command line application, which uses gmerlin plugins, you might want to avoid translating 100s of plugin options into command line options. This can be done by typing gmerlin_plugincfg. It lets you configure all plugin options and save them at a location, where other applications can find them. One application, which uses this, is gmerlin_visualizer, which also comes as a separate package. gmerlin-1.2.0~dfsg/depcomp0000755000175000017500000004426711331674343015470 0ustar alessioalessio#! /bin/sh # depcomp - compile a program generating dependencies as side-effects scriptversion=2009-04-28.21; # UTC # Copyright (C) 1999, 2000, 2003, 2004, 2005, 2006, 2007, 2009 Free # Software Foundation, Inc. # 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 this program. If not, see . # As a special exception to the GNU General Public License, if you # distribute this file as part of a program that contains a # configuration script generated by Autoconf, you may include it under # the same distribution terms that you use for the rest of that program. # Originally written by Alexandre Oliva . case $1 in '') echo "$0: No command. Try \`$0 --help' for more information." 1>&2 exit 1; ;; -h | --h*) cat <<\EOF Usage: depcomp [--help] [--version] PROGRAM [ARGS] Run PROGRAMS ARGS to compile a file, generating dependencies as side-effects. Environment variables: depmode Dependency tracking mode. source Source file read by `PROGRAMS ARGS'. object Object file output by `PROGRAMS ARGS'. DEPDIR directory where to store dependencies. depfile Dependency file to output. tmpdepfile Temporary file to use when outputing dependencies. libtool Whether libtool is used (yes/no). Report bugs to . EOF exit $? ;; -v | --v*) echo "depcomp $scriptversion" exit $? ;; esac if test -z "$depmode" || test -z "$source" || test -z "$object"; then echo "depcomp: Variables source, object and depmode must be set" 1>&2 exit 1 fi # Dependencies for sub/bar.o or sub/bar.obj go into sub/.deps/bar.Po. depfile=${depfile-`echo "$object" | sed 's|[^\\/]*$|'${DEPDIR-.deps}'/&|;s|\.\([^.]*\)$|.P\1|;s|Pobj$|Po|'`} tmpdepfile=${tmpdepfile-`echo "$depfile" | sed 's/\.\([^.]*\)$/.T\1/'`} rm -f "$tmpdepfile" # Some modes work just like other modes, but use different flags. We # parameterize here, but still list the modes in the big case below, # to make depend.m4 easier to write. Note that we *cannot* use a case # here, because this file can only contain one case statement. if test "$depmode" = hp; then # HP compiler uses -M and no extra arg. gccflag=-M depmode=gcc fi if test "$depmode" = dashXmstdout; then # This is just like dashmstdout with a different argument. dashmflag=-xM depmode=dashmstdout fi cygpath_u="cygpath -u -f -" if test "$depmode" = msvcmsys; then # This is just like msvisualcpp but w/o cygpath translation. # Just convert the backslash-escaped backslashes to single forward # slashes to satisfy depend.m4 cygpath_u="sed s,\\\\\\\\,/,g" depmode=msvisualcpp fi case "$depmode" in gcc3) ## gcc 3 implements dependency tracking that does exactly what ## we want. Yay! Note: for some reason libtool 1.4 doesn't like ## it if -MD -MP comes after the -MF stuff. Hmm. ## Unfortunately, FreeBSD c89 acceptance of flags depends upon ## the command line argument order; so add the flags where they ## appear in depend2.am. Note that the slowdown incurred here ## affects only configure: in makefiles, %FASTDEP% shortcuts this. for arg do case $arg in -c) set fnord "$@" -MT "$object" -MD -MP -MF "$tmpdepfile" "$arg" ;; *) set fnord "$@" "$arg" ;; esac shift # fnord shift # $arg done "$@" stat=$? if test $stat -eq 0; then : else rm -f "$tmpdepfile" exit $stat fi mv "$tmpdepfile" "$depfile" ;; gcc) ## There are various ways to get dependency output from gcc. Here's ## why we pick this rather obscure method: ## - Don't want to use -MD because we'd like the dependencies to end ## up in a subdir. Having to rename by hand is ugly. ## (We might end up doing this anyway to support other compilers.) ## - The DEPENDENCIES_OUTPUT environment variable makes gcc act like ## -MM, not -M (despite what the docs say). ## - Using -M directly means running the compiler twice (even worse ## than renaming). if test -z "$gccflag"; then gccflag=-MD, fi "$@" -Wp,"$gccflag$tmpdepfile" stat=$? if test $stat -eq 0; then : else rm -f "$tmpdepfile" exit $stat fi rm -f "$depfile" echo "$object : \\" > "$depfile" alpha=ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz ## The second -e expression handles DOS-style file names with drive letters. sed -e 's/^[^:]*: / /' \ -e 's/^['$alpha']:\/[^:]*: / /' < "$tmpdepfile" >> "$depfile" ## This next piece of magic avoids the `deleted header file' problem. ## The problem is that when a header file which appears in a .P file ## is deleted, the dependency causes make to die (because there is ## typically no way to rebuild the header). We avoid this by adding ## dummy dependencies for each header file. Too bad gcc doesn't do ## this for us directly. tr ' ' ' ' < "$tmpdepfile" | ## Some versions of gcc put a space before the `:'. On the theory ## that the space means something, we add a space to the output as ## well. ## Some versions of the HPUX 10.20 sed can't process this invocation ## correctly. Breaking it into two sed invocations is a workaround. sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' | sed -e 's/$/ :/' >> "$depfile" rm -f "$tmpdepfile" ;; hp) # This case exists only to let depend.m4 do its work. It works by # looking at the text of this script. This case will never be run, # since it is checked for above. exit 1 ;; sgi) if test "$libtool" = yes; then "$@" "-Wp,-MDupdate,$tmpdepfile" else "$@" -MDupdate "$tmpdepfile" fi stat=$? if test $stat -eq 0; then : else rm -f "$tmpdepfile" exit $stat fi rm -f "$depfile" if test -f "$tmpdepfile"; then # yes, the sourcefile depend on other files echo "$object : \\" > "$depfile" # Clip off the initial element (the dependent). Don't try to be # clever and replace this with sed code, as IRIX sed won't handle # lines with more than a fixed number of characters (4096 in # IRIX 6.2 sed, 8192 in IRIX 6.5). We also remove comment lines; # the IRIX cc adds comments like `#:fec' to the end of the # dependency line. tr ' ' ' ' < "$tmpdepfile" \ | sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' | \ tr ' ' ' ' >> "$depfile" echo >> "$depfile" # The second pass generates a dummy entry for each header file. tr ' ' ' ' < "$tmpdepfile" \ | sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' -e 's/$/:/' \ >> "$depfile" else # The sourcefile does not contain any dependencies, so just # store a dummy comment line, to avoid errors with the Makefile # "include basename.Plo" scheme. echo "#dummy" > "$depfile" fi rm -f "$tmpdepfile" ;; aix) # The C for AIX Compiler uses -M and outputs the dependencies # in a .u file. In older versions, this file always lives in the # current directory. Also, the AIX compiler puts `$object:' at the # start of each line; $object doesn't have directory information. # Version 6 uses the directory in both cases. dir=`echo "$object" | sed -e 's|/[^/]*$|/|'` test "x$dir" = "x$object" && dir= base=`echo "$object" | sed -e 's|^.*/||' -e 's/\.o$//' -e 's/\.lo$//'` if test "$libtool" = yes; then tmpdepfile1=$dir$base.u tmpdepfile2=$base.u tmpdepfile3=$dir.libs/$base.u "$@" -Wc,-M else tmpdepfile1=$dir$base.u tmpdepfile2=$dir$base.u tmpdepfile3=$dir$base.u "$@" -M fi stat=$? if test $stat -eq 0; then : else rm -f "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" exit $stat fi for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" do test -f "$tmpdepfile" && break done if test -f "$tmpdepfile"; then # Each line is of the form `foo.o: dependent.h'. # Do two passes, one to just change these to # `$object: dependent.h' and one to simply `dependent.h:'. sed -e "s,^.*\.[a-z]*:,$object:," < "$tmpdepfile" > "$depfile" # That's a tab and a space in the []. sed -e 's,^.*\.[a-z]*:[ ]*,,' -e 's,$,:,' < "$tmpdepfile" >> "$depfile" else # The sourcefile does not contain any dependencies, so just # store a dummy comment line, to avoid errors with the Makefile # "include basename.Plo" scheme. echo "#dummy" > "$depfile" fi rm -f "$tmpdepfile" ;; icc) # Intel's C compiler understands `-MD -MF file'. However on # icc -MD -MF foo.d -c -o sub/foo.o sub/foo.c # ICC 7.0 will fill foo.d with something like # foo.o: sub/foo.c # foo.o: sub/foo.h # which is wrong. We want: # sub/foo.o: sub/foo.c # sub/foo.o: sub/foo.h # sub/foo.c: # sub/foo.h: # ICC 7.1 will output # foo.o: sub/foo.c sub/foo.h # and will wrap long lines using \ : # foo.o: sub/foo.c ... \ # sub/foo.h ... \ # ... "$@" -MD -MF "$tmpdepfile" stat=$? if test $stat -eq 0; then : else rm -f "$tmpdepfile" exit $stat fi rm -f "$depfile" # Each line is of the form `foo.o: dependent.h', # or `foo.o: dep1.h dep2.h \', or ` dep3.h dep4.h \'. # Do two passes, one to just change these to # `$object: dependent.h' and one to simply `dependent.h:'. sed "s,^[^:]*:,$object :," < "$tmpdepfile" > "$depfile" # Some versions of the HPUX 10.20 sed can't process this invocation # correctly. Breaking it into two sed invocations is a workaround. sed 's,^[^:]*: \(.*\)$,\1,;s/^\\$//;/^$/d;/:$/d' < "$tmpdepfile" | sed -e 's/$/ :/' >> "$depfile" rm -f "$tmpdepfile" ;; hp2) # The "hp" stanza above does not work with aCC (C++) and HP's ia64 # compilers, which have integrated preprocessors. The correct option # to use with these is +Maked; it writes dependencies to a file named # 'foo.d', which lands next to the object file, wherever that # happens to be. # Much of this is similar to the tru64 case; see comments there. dir=`echo "$object" | sed -e 's|/[^/]*$|/|'` test "x$dir" = "x$object" && dir= base=`echo "$object" | sed -e 's|^.*/||' -e 's/\.o$//' -e 's/\.lo$//'` if test "$libtool" = yes; then tmpdepfile1=$dir$base.d tmpdepfile2=$dir.libs/$base.d "$@" -Wc,+Maked else tmpdepfile1=$dir$base.d tmpdepfile2=$dir$base.d "$@" +Maked fi stat=$? if test $stat -eq 0; then : else rm -f "$tmpdepfile1" "$tmpdepfile2" exit $stat fi for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2" do test -f "$tmpdepfile" && break done if test -f "$tmpdepfile"; then sed -e "s,^.*\.[a-z]*:,$object:," "$tmpdepfile" > "$depfile" # Add `dependent.h:' lines. sed -ne '2,${ s/^ *// s/ \\*$// s/$/:/ p }' "$tmpdepfile" >> "$depfile" else echo "#dummy" > "$depfile" fi rm -f "$tmpdepfile" "$tmpdepfile2" ;; tru64) # The Tru64 compiler uses -MD to generate dependencies as a side # effect. `cc -MD -o foo.o ...' puts the dependencies into `foo.o.d'. # At least on Alpha/Redhat 6.1, Compaq CCC V6.2-504 seems to put # dependencies in `foo.d' instead, so we check for that too. # Subdirectories are respected. dir=`echo "$object" | sed -e 's|/[^/]*$|/|'` test "x$dir" = "x$object" && dir= base=`echo "$object" | sed -e 's|^.*/||' -e 's/\.o$//' -e 's/\.lo$//'` if test "$libtool" = yes; then # With Tru64 cc, shared objects can also be used to make a # static library. This mechanism is used in libtool 1.4 series to # handle both shared and static libraries in a single compilation. # With libtool 1.4, dependencies were output in $dir.libs/$base.lo.d. # # With libtool 1.5 this exception was removed, and libtool now # generates 2 separate objects for the 2 libraries. These two # compilations output dependencies in $dir.libs/$base.o.d and # in $dir$base.o.d. We have to check for both files, because # one of the two compilations can be disabled. We should prefer # $dir$base.o.d over $dir.libs/$base.o.d because the latter is # automatically cleaned when .libs/ is deleted, while ignoring # the former would cause a distcleancheck panic. tmpdepfile1=$dir.libs/$base.lo.d # libtool 1.4 tmpdepfile2=$dir$base.o.d # libtool 1.5 tmpdepfile3=$dir.libs/$base.o.d # libtool 1.5 tmpdepfile4=$dir.libs/$base.d # Compaq CCC V6.2-504 "$@" -Wc,-MD else tmpdepfile1=$dir$base.o.d tmpdepfile2=$dir$base.d tmpdepfile3=$dir$base.d tmpdepfile4=$dir$base.d "$@" -MD fi stat=$? if test $stat -eq 0; then : else rm -f "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" "$tmpdepfile4" exit $stat fi for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" "$tmpdepfile4" do test -f "$tmpdepfile" && break done if test -f "$tmpdepfile"; then sed -e "s,^.*\.[a-z]*:,$object:," < "$tmpdepfile" > "$depfile" # That's a tab and a space in the []. sed -e 's,^.*\.[a-z]*:[ ]*,,' -e 's,$,:,' < "$tmpdepfile" >> "$depfile" else echo "#dummy" > "$depfile" fi rm -f "$tmpdepfile" ;; #nosideeffect) # This comment above is used by automake to tell side-effect # dependency tracking mechanisms from slower ones. dashmstdout) # Important note: in order to support this mode, a compiler *must* # always write the preprocessed file to stdout, regardless of -o. "$@" || exit $? # Remove the call to Libtool. if test "$libtool" = yes; then while test "X$1" != 'X--mode=compile'; do shift done shift fi # Remove `-o $object'. IFS=" " for arg do case $arg in -o) shift ;; $object) shift ;; *) set fnord "$@" "$arg" shift # fnord shift # $arg ;; esac done test -z "$dashmflag" && dashmflag=-M # Require at least two characters before searching for `:' # in the target name. This is to cope with DOS-style filenames: # a dependency such as `c:/foo/bar' could be seen as target `c' otherwise. "$@" $dashmflag | sed 's:^[ ]*[^: ][^:][^:]*\:[ ]*:'"$object"'\: :' > "$tmpdepfile" rm -f "$depfile" cat < "$tmpdepfile" > "$depfile" tr ' ' ' ' < "$tmpdepfile" | \ ## Some versions of the HPUX 10.20 sed can't process this invocation ## correctly. Breaking it into two sed invocations is a workaround. sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' | sed -e 's/$/ :/' >> "$depfile" rm -f "$tmpdepfile" ;; dashXmstdout) # This case only exists to satisfy depend.m4. It is never actually # run, as this mode is specially recognized in the preamble. exit 1 ;; makedepend) "$@" || exit $? # Remove any Libtool call if test "$libtool" = yes; then while test "X$1" != 'X--mode=compile'; do shift done shift fi # X makedepend shift cleared=no eat=no for arg do case $cleared in no) set ""; shift cleared=yes ;; esac if test $eat = yes; then eat=no continue fi case "$arg" in -D*|-I*) set fnord "$@" "$arg"; shift ;; # Strip any option that makedepend may not understand. Remove # the object too, otherwise makedepend will parse it as a source file. -arch) eat=yes ;; -*|$object) ;; *) set fnord "$@" "$arg"; shift ;; esac done obj_suffix=`echo "$object" | sed 's/^.*\././'` touch "$tmpdepfile" ${MAKEDEPEND-makedepend} -o"$obj_suffix" -f"$tmpdepfile" "$@" rm -f "$depfile" cat < "$tmpdepfile" > "$depfile" sed '1,2d' "$tmpdepfile" | tr ' ' ' ' | \ ## Some versions of the HPUX 10.20 sed can't process this invocation ## correctly. Breaking it into two sed invocations is a workaround. sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' | sed -e 's/$/ :/' >> "$depfile" rm -f "$tmpdepfile" "$tmpdepfile".bak ;; cpp) # Important note: in order to support this mode, a compiler *must* # always write the preprocessed file to stdout. "$@" || exit $? # Remove the call to Libtool. if test "$libtool" = yes; then while test "X$1" != 'X--mode=compile'; do shift done shift fi # Remove `-o $object'. IFS=" " for arg do case $arg in -o) shift ;; $object) shift ;; *) set fnord "$@" "$arg" shift # fnord shift # $arg ;; esac done "$@" -E | sed -n -e '/^# [0-9][0-9]* "\([^"]*\)".*/ s:: \1 \\:p' \ -e '/^#line [0-9][0-9]* "\([^"]*\)".*/ s:: \1 \\:p' | sed '$ s: \\$::' > "$tmpdepfile" rm -f "$depfile" echo "$object : \\" > "$depfile" cat < "$tmpdepfile" >> "$depfile" sed < "$tmpdepfile" '/^$/d;s/^ //;s/ \\$//;s/$/ :/' >> "$depfile" rm -f "$tmpdepfile" ;; msvisualcpp) # Important note: in order to support this mode, a compiler *must* # always write the preprocessed file to stdout. "$@" || exit $? # Remove the call to Libtool. if test "$libtool" = yes; then while test "X$1" != 'X--mode=compile'; do shift done shift fi IFS=" " for arg do case "$arg" in -o) shift ;; $object) shift ;; "-Gm"|"/Gm"|"-Gi"|"/Gi"|"-ZI"|"/ZI") set fnord "$@" shift shift ;; *) set fnord "$@" "$arg" shift shift ;; esac done "$@" -E 2>/dev/null | sed -n '/^#line [0-9][0-9]* "\([^"]*\)"/ s::\1:p' | $cygpath_u | sort -u > "$tmpdepfile" rm -f "$depfile" echo "$object : \\" > "$depfile" sed < "$tmpdepfile" -n -e 's% %\\ %g' -e '/^\(.*\)$/ s:: \1 \\:p' >> "$depfile" echo " " >> "$depfile" sed < "$tmpdepfile" -n -e 's% %\\ %g' -e '/^\(.*\)$/ s::\1\::p' >> "$depfile" rm -f "$tmpdepfile" ;; msvcmsys) # This case exists only to let depend.m4 do its work. It works by # looking at the text of this script. This case will never be run, # since it is checked for above. exit 1 ;; none) exec "$@" ;; *) echo "Unknown depmode $depmode" 1>&2 exit 1 ;; esac exit 0 # Local Variables: # mode: shell-script # sh-indentation: 2 # eval: (add-hook 'write-file-hooks 'time-stamp) # time-stamp-start: "scriptversion=" # time-stamp-format: "%:y-%02m-%02d.%02H" # time-stamp-time-zone: "UTC" # time-stamp-end: "; # UTC" # End: gmerlin-1.2.0~dfsg/tests/0000755000175000017500000000000011764363443015246 5ustar alessioalessiogmerlin-1.2.0~dfsg/tests/thumbnail.c0000644000175000017500000000441311764363402017372 0ustar alessioalessio/***************************************************************** * gmerlin - a general purpose multimedia framework and applications * * Copyright (c) 2001 - 2011 Members of the Gmerlin project * gmerlin-general@lists.sourceforge.net * http://gmerlin.sourceforge.net * * 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 of the License, 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 this program. If not, see . ******************************************************************/ #include #include #include #include #include int main(int argc, char ** argv) { bg_cfg_registry_t * cfg_reg; bg_plugin_registry_t * plugin_reg; char * tmp_path; bg_cfg_section_t * cfg_section; char * th_filename; gavl_video_format_t th_format; gavl_video_frame_t * th_frame; memset(&th_format, 0, sizeof(th_format)); /* Create registries */ cfg_reg = bg_cfg_registry_create(); tmp_path = bg_search_file_read("generic", "config.xml"); bg_cfg_registry_load(cfg_reg, tmp_path); if(tmp_path) free(tmp_path); cfg_section = bg_cfg_registry_find_section(cfg_reg, "plugins"); plugin_reg = bg_plugin_registry_create(cfg_section); /* Get thumbnail */ if(bg_get_thumbnail(argv[1], plugin_reg, &th_filename, &th_frame, &th_format)) { fprintf(stderr, "Thumbnail file: %s\n", th_filename); fprintf(stderr, "Thumbnail format:\n"); gavl_video_format_dump(&th_format); fprintf(stderr, "Thumbnail frame: %p\n", th_frame); gavl_video_frame_destroy(th_frame); free(th_filename); } bg_plugin_registry_destroy(plugin_reg); bg_cfg_registry_destroy(cfg_reg); return 0; } gmerlin-1.2.0~dfsg/tests/Makefile.am0000644000175000017500000000707011764363402017301 0ustar alessioalessioplugindir=$(pkglibdir)/plugins INCLUDES = -I$(top_srcdir)/include AM_CFLAGS = \ @GTK_CFLAGS@ \ @XML2_CFLAGS@ \ -DLOCALE_DIR=\"$(localedir)\" \ -DPLUGIN_DIR=\"$(plugindir)\" \ -DDOC_DIR=\"$(docdir)\" \ -DDATA_DIR=\"$(pkgdatadir)\" if HAVE_GTK gtk_programs = \ cfgtest \ playtree \ question \ message \ scrolltext \ auth \ chapter \ vumeter else gtk_programs = endif if HAVE_V4L v4l_programs = v4ltest \ v4ldump else v4l_programs = endif noinst_PROGRAMS = audioplayer1 \ videoplayer1 \ fvtest \ msgtest \ server \ client \ dump_plugins \ extractchannel \ insertchannel \ ocrtest \ textrenderer \ ladspa \ thumbnail \ visualization \ $(v4l_programs) \ $(gtk_programs) bin_PROGRAMS = gmerlin_imgconvert \ album2m3u \ album2pls \ gmerlin_imgdiff \ gmerlin_psnr \ gmerlin_ssim \ gmerlin_vanalyze \ gmerlin_vpsnr \ gmerlin_visualize # noinst_HEADERS = player1.h audioplayer1_SOURCES = audioplayer1.c audioplayer1_LDADD = ../lib/libgmerlin.la -ldl album2m3u_SOURCES = album2m3u.c album2m3u_LDADD = ../lib/libgmerlin.la -ldl album2pls_SOURCES = album2pls.c album2pls_LDADD = ../lib/libgmerlin.la -ldl ocrtest_SOURCES = ocrtest.c ocrtest_LDADD = ../lib/libgmerlin.la -ldl extractchannel_SOURCES = extractchannel.c extractchannel_LDADD = ../lib/libgmerlin.la -ldl insertchannel_SOURCES = insertchannel.c insertchannel_LDADD = ../lib/libgmerlin.la -ldl dump_plugins_SOURCES = dump_plugins.c dump_plugins_LDADD = ../lib/libgmerlin.la -ldl ladspa_SOURCES = ladspa.c ladspa_LDADD = -ldl thumbnail_SOURCES = thumbnail.c thumbnail_LDADD = ../lib/libgmerlin.la -ldl gmerlin_imgconvert_SOURCES = imgconvert.c gmerlin_imgconvert_LDADD = ../lib/libgmerlin.la -ldl gmerlin_psnr_SOURCES = gmerlin_psnr.c gmerlin_psnr_LDADD = ../lib/libgmerlin.la -ldl gmerlin_ssim_SOURCES = gmerlin_ssim.c gmerlin_ssim_LDADD = ../lib/libgmerlin.la -ldl gmerlin_vpsnr_SOURCES = gmerlin_vpsnr.c gmerlin_vpsnr_LDADD = ../lib/libgmerlin.la -ldl gmerlin_vanalyze_SOURCES = gmerlin_vanalyze.c gmerlin_vanalyze_LDADD = ../lib/libgmerlin.la -ldl gmerlin_visualize_SOURCES = gmerlin_visualize.c gmerlin_visualize_LDADD = ../lib/libgmerlin.la -ldl gmerlin_imgdiff_SOURCES = gmerlin_imgdiff.c gmerlin_imgdiff_LDADD = ../lib/libgmerlin.la -ldl msgtest_SOURCES = msgtest.c msgtest_LDADD = ../lib/libgmerlin.la -ldl textrenderer_SOURCES = textrenderer.c textrenderer_LDADD = ../lib/libgmerlin.la -ldl videoplayer1_SOURCES = videoplayer1.c videoplayer1_LDADD = ../lib/libgmerlin.la -ldl fvtest_SOURCES = fvtest.c fvtest_LDADD = ../lib/libgmerlin.la -ldl cfgtest_SOURCES = cfgtest.c cfgtest_LDADD = ../lib/libgmerlin.la ../lib/gtk/libgmerlin_gtk.la chapter_SOURCES = chapter.c chapter_LDADD = ../lib/libgmerlin.la ../lib/gtk/libgmerlin_gtk.la vumeter_SOURCES = vumeter.c vumeter_LDADD = ../lib/libgmerlin.la ../lib/gtk/libgmerlin_gtk.la v4ltest_SOURCES = v4ltest.c v4ltest_LDADD = ../lib/libgmerlin.la v4ldump_SOURCES = v4ldump.c v4ldump_LDADD = ../lib/libgmerlin.la visualization_SOURCES = visualization.c visualization_LDADD = ../lib/libgmerlin.la scrolltext_SOURCES = scrolltext.c scrolltext_LDADD = ../lib/libgmerlin.la ../lib/gtk/libgmerlin_gtk.la question_SOURCES = question.c question_LDADD = ../lib/libgmerlin.la ../lib/gtk/libgmerlin_gtk.la auth_SOURCES = auth.c auth_LDADD = ../lib/libgmerlin.la ../lib/gtk/libgmerlin_gtk.la message_SOURCES = message.c message_LDADD = ../lib/libgmerlin.la ../lib/gtk/libgmerlin_gtk.la playtree_SOURCES = playtree.c playtree_LDADD = ../lib/libgmerlin.la ../lib/gtk/libgmerlin_gtk.la server_SOURCES = server.c server_LDADD = ../lib/libgmerlin.la client_SOURCES = client.c client_LDADD = ../lib/libgmerlin.la gmerlin-1.2.0~dfsg/tests/v4ltest.c0000644000175000017500000001066111764363402017016 0ustar alessioalessio/***************************************************************** * gmerlin - a general purpose multimedia framework and applications * * Copyright (c) 2001 - 2011 Members of the Gmerlin project * gmerlin-general@lists.sourceforge.net * http://gmerlin.sourceforge.net * * 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 of the License, 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 this program. If not, see . * *****************************************************************/ #include #include #include #include #include int keep_going = 1; int main(int argc, char ** argv) { char * tmp_path; bg_cfg_section_t * section; bg_cfg_registry_t * cfg_reg; bg_plugin_registry_t * plugin_reg; gavl_video_converter_t * cnv; int do_convert; gavl_video_format_t input_format; gavl_video_format_t output_format; bg_plugin_handle_t * input_handle; bg_plugin_handle_t * output_handle; bg_recorder_plugin_t * input; bg_ov_plugin_t * output; const bg_plugin_info_t * info; gavl_video_frame_t * frame = NULL; gavl_video_frame_t * input_frame = NULL; /* Create config registry */ cfg_reg = bg_cfg_registry_create(); tmp_path = bg_search_file_read("generic", "config.xml"); bg_cfg_registry_load(cfg_reg, tmp_path); if(tmp_path) free(tmp_path); /* Create plugin registry */ section = bg_cfg_registry_find_section(cfg_reg, "plugins"); plugin_reg = bg_plugin_registry_create(section); /* Load v4l plugin */ info = bg_plugin_find_by_name(plugin_reg, "i_v4l"); if(!info) { fprintf(stderr, "Video4linux plugin not installed\n"); return -1; } input_handle = bg_plugin_load(plugin_reg, info); if(!input_handle) { fprintf(stderr, "Video4linux plugin could not be loaded\n"); return -1; } input = (bg_recorder_plugin_t*)input_handle->plugin; /* Load output plugin */ info = bg_plugin_registry_get_default(plugin_reg, BG_PLUGIN_OUTPUT_VIDEO, BG_PLUGIN_PLAYBACK); if(!info) { fprintf(stderr, "No video output plugin found\n"); return -1; } output_handle = bg_plugin_load(plugin_reg, info); if(!output_handle) { fprintf(stderr, "Video output plugin could not be loaded\n"); return -1; } output = (bg_ov_plugin_t*)output_handle->plugin; /* Open input */ if(!input->open(input_handle->priv, NULL, &input_format)) { fprintf(stderr, "Opening video device fauled\n"); return -1; } fprintf(stderr, "Opened input device, format:\n"); gavl_video_format_dump(&input_format); gavl_video_format_copy(&output_format, &input_format); /* Open output */ if(!output->open(output_handle->priv, &output_format, 1)) { fprintf(stderr, "Opening video device fauled\n"); return -1; } output->set_window_title(output_handle->priv, "Webcam"); if(output->show_window) output->show_window(output_handle->priv, 1); fprintf(stderr, "Opened output plugin, format:\n"); gavl_video_format_dump(&output_format); /* Fire up video converter */ cnv = gavl_video_converter_create(); do_convert = gavl_video_converter_init(cnv, &input_format, &output_format); /* Allocate video image */ if(do_convert) input_frame = gavl_video_frame_create(&input_format); while(keep_going) { frame = output->get_frame(output_handle->priv); if(do_convert) { if(!input->read_video(input_handle->priv, input_frame, 0)) { fprintf(stderr, "read_frame failed\n"); return -1; } gavl_video_convert(cnv, input_frame, frame); } else { // fprintf(stderr, "Get frame\n"); input->read_video(input_handle->priv, frame, 0); } // fprintf(stderr, "done\nPut frame..."); output->put_video(output_handle->priv, frame); // fprintf(stderr, "done\n"); } return 0; } gmerlin-1.2.0~dfsg/tests/gmerlin_visualize.c0000644000175000017500000003675411764363402021154 0ustar alessioalessio/***************************************************************** * gmerlin - a general purpose multimedia framework and applications * * Copyright (c) 2001 - 2011 Members of the Gmerlin project * gmerlin-general@lists.sourceforge.net * http://gmerlin.sourceforge.net * * 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 of the License, 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 this program. If not, see . * *****************************************************************/ #include #include #include #include #include #include #include #include #include #define LOG_DOMAIN "gmerlin_visualize" /* Globals */ static int width = 640; static int height = 480; static int fps_num = 25; static int fps_den = 1; bg_cfg_section_t * vis_section = NULL; bg_plugin_handle_t * vis_handle = NULL; bg_plugin_handle_t * enc_handle = NULL; bg_plugin_registry_t * plugin_reg = NULL; // int encode_audio = 0; int audio_index = -1; int video_index = -1; gavl_audio_converter_t * audio_cnv_v = NULL; gavl_audio_converter_t * audio_cnv_e = NULL; gavl_video_converter_t * video_cnv_e = NULL; int convert_audio_v = 0; int convert_audio_e = 0; int convert_video_e = 0; gavl_audio_frame_t * aframe_v = NULL; gavl_audio_frame_t * aframe_e = NULL; gavl_video_frame_t * vframe_v = NULL; gavl_video_frame_t * vframe_e = NULL; gavl_audio_format_t afmt_i, afmt_e, afmt_v; gavl_video_format_t vfmt_v, vfmt_e; gavl_time_t track_duration; gavl_time_t start_duration = 0; gavl_time_t end_duration = 0; static int load_input_file(bg_plugin_registry_t * plugin_reg, bg_plugin_handle_t ** input_handle, bg_input_plugin_t ** input_plugin, const char * file, gavl_audio_format_t * format) { bg_track_info_t * ti; *input_handle = NULL; if(!bg_input_plugin_load(plugin_reg, file, NULL, input_handle, NULL, 0)) { fprintf(stderr, "Cannot open %s\n", file); return 0; } *input_plugin = (bg_input_plugin_t*)((*input_handle)->plugin); ti = (*input_plugin)->get_track_info((*input_handle)->priv, 0); if((*input_plugin)->set_track) (*input_plugin)->set_track((*input_handle)->priv, 0); if(!ti->num_audio_streams) { fprintf(stderr, "File %s has no audio\n", file); return 0; } track_duration = ti->duration; /* Select first stream */ (*input_plugin)->set_audio_stream((*input_handle)->priv, 0, BG_STREAM_ACTION_DECODE); /* Start playback */ if((*input_plugin)->start) (*input_plugin)->start((*input_handle)->priv); /* Get video format */ gavl_audio_format_copy(format, &ti->audio_streams[0].format); return 1; } static void set_audio_parameter(void * priv, const char * name, const bg_parameter_value_t * val) { bg_encoder_plugin_t * plugin; bg_plugin_handle_t * handle = priv; plugin = (bg_encoder_plugin_t *)(handle)->plugin; plugin->set_audio_parameter(handle->priv, audio_index, name, val); } static void set_video_parameter(void * priv, const char * name, const bg_parameter_value_t * val) { bg_encoder_plugin_t * plugin; bg_plugin_handle_t * handle = priv; plugin = (bg_encoder_plugin_t *)(handle)->plugin; plugin->set_video_parameter(handle->priv, video_index, name, val); // fprintf(stderr, "Set video parameter %s\n", name); } static int open_encoder(bg_plugin_registry_t * plugin_reg, bg_plugin_handle_t ** handle, bg_encoder_plugin_t ** plugin, const char * file_prefix, gavl_audio_format_t * audio_format, gavl_video_format_t * video_format) { const bg_plugin_info_t * info; info = bg_plugin_registry_get_default(plugin_reg, BG_PLUGIN_ENCODER_VIDEO, BG_PLUGIN_FILE); if(!info) { bg_log(BG_LOG_ERROR, LOG_DOMAIN, "No encoder plugin present"); return 0; } *handle = bg_plugin_load(plugin_reg, info); if(!(*handle)) { bg_log(BG_LOG_ERROR, LOG_DOMAIN, "Cannot load plugin %s", info->name); return 0; } *plugin = (bg_encoder_plugin_t *)(*handle)->plugin; /* Open */ if(!(*plugin)->open((*handle)->priv, file_prefix, NULL, NULL)) { bg_log(BG_LOG_ERROR, LOG_DOMAIN, "Opening %s failed", file_prefix); } /* Add video stream */ video_index = (*plugin)->add_video_stream((*handle)->priv, NULL, video_format); /* Add audio stream */ if((*plugin)->add_audio_stream) audio_index = (*plugin)->add_audio_stream((*handle)->priv, NULL, audio_format); /* Set video parameters */ if((*plugin)->get_video_parameters) { bg_cfg_section_t * s; s = bg_plugin_registry_get_section(plugin_reg, info->name); s = bg_cfg_section_find_subsection(s, "$video"); bg_cfg_section_apply(s, (*plugin)->get_video_parameters((*handle)->priv), set_video_parameter, *handle); } /* Set audio parameters */ if((*plugin)->get_audio_parameters) { bg_cfg_section_t * s; s = bg_plugin_registry_get_section(plugin_reg, info->name); s = bg_cfg_section_find_subsection(s, "$audio"); bg_cfg_section_apply(s, (*plugin)->get_audio_parameters((*handle)->priv), set_audio_parameter, *handle); } if((*plugin)->start && !(*plugin)->start((*handle)->priv)) { bg_log(BG_LOG_ERROR, LOG_DOMAIN, "Starting %s failed", info->name); return 0; } if((*plugin)->add_audio_stream) (*plugin)->get_audio_format((*handle)->priv, audio_index, audio_format); (*plugin)->get_video_format((*handle)->priv, video_index, video_format); return 1; } static void opt_width(void * data, int * argc, char *** argv, int arg) { if(arg >= *argc) { fprintf(stderr, "Option -w requires an argument\n"); exit(-1); } width = atoi((*argv)[arg]); bg_cmdline_remove_arg(argc, argv, arg); } static void opt_height(void * data, int * argc, char *** argv, int arg) { if(arg >= *argc) { fprintf(stderr, "Option -h requires an argument\n"); exit(-1); } height = atoi((*argv)[arg]); bg_cmdline_remove_arg(argc, argv, arg); } static void opt_fps(void * data, int * argc, char *** argv, int arg) { if(arg >= *argc) { fprintf(stderr, "Option -fps requires an argument\n"); exit(-1); } if(sscanf((*argv)[arg], "%d:%d", &fps_num, &fps_den) < 2) { fprintf(stderr, "Framerate must be in the form num:den\n"); exit(-1); } bg_cmdline_remove_arg(argc, argv, arg); } static bg_parameter_info_t vis_parameters[] = { { .name = "plugin", .long_name = "Visualization plugin", .opt = "p", .type = BG_PARAMETER_MULTI_MENU, }, { /* End of parameters */ } }; static void set_vis_parameter(void * data, const char * name, const bg_parameter_value_t * val) { const bg_plugin_info_t * info; // fprintf(stderr, "set_vis_parameter: %s\n", name); if(name && !strcmp(name, "plugin")) { // fprintf(stderr, "set_vis_parameter: plugin: %s\n", val->val_str); info = bg_plugin_find_by_name(plugin_reg, val->val_str); vis_handle = bg_plugin_load(plugin_reg, info); } else { if(vis_handle && vis_handle->plugin && vis_handle->plugin->set_parameter) vis_handle->plugin->set_parameter(vis_handle->priv, name, val); } } static void opt_vis(void * data, int * argc, char *** _argv, int arg) { if(arg >= *argc) { fprintf(stderr, "Option -vis requires an argument\n"); exit(-1); } if(!bg_cmdline_apply_options(vis_section, set_vis_parameter, NULL, vis_parameters, (*_argv)[arg])) exit(-1); bg_cmdline_remove_arg(argc, _argv, arg); } static bg_cmdline_arg_t global_options[] = { { .arg = "-w", .help_arg = "", .help_string = "Image width", .callback = opt_width, }, { .arg = "-h", .help_arg = "", .help_string = "Image height", .callback = opt_height, }, { .arg = "-fps", .help_arg = "", .help_string = "Framerate", .callback = opt_fps, }, { .arg = "-vis", .help_arg = "", .help_string = "Set visualization plugin", .callback = opt_vis, .parameters = vis_parameters, }, { /* End of options */ } }; bg_cmdline_app_data_t app_data = { .package = PACKAGE, .version = VERSION, .name = "gmerlin_visualize", .synopsis = TRS("[-w width -h height -fps num:den] infile out_base\n"), .help_before = TRS("Visualize audio files and save as A/V files\n"), .args = (bg_cmdline_arg_array_t[]) { { TRS("Options"), global_options }, { } }, }; int64_t next_frame_time = 0; int64_t audio_time = 0; static void iteration(gavl_audio_frame_t * frame) { float percentage; bg_visualization_plugin_t * vis_plugin; bg_encoder_plugin_t * enc_plugin = (bg_encoder_plugin_t*)enc_handle->plugin; vis_plugin = (bg_visualization_plugin_t*)vis_handle->plugin; /* Update visualization */ if(convert_audio_v) { gavl_audio_convert(audio_cnv_v, frame, aframe_v); vis_plugin->update(vis_handle->priv, aframe_v); } else { vis_plugin->update(vis_handle->priv, frame); } audio_time += frame->valid_samples; /* Write audio */ if(audio_index >= 0) { if(convert_audio_e) { gavl_audio_convert(audio_cnv_e, frame, aframe_e); enc_plugin->write_audio_frame(enc_handle->priv, aframe_e, audio_index); } else { enc_plugin->write_audio_frame(enc_handle->priv, frame, audio_index); } } /* Write video */ if(gavl_time_rescale(afmt_i.samplerate, vfmt_e.timescale, audio_time) >= next_frame_time) { vis_plugin->draw_frame(vis_handle->priv, vframe_v); if(convert_audio_e) { gavl_video_convert(video_cnv_e, vframe_v, vframe_e); vframe_e->timestamp = next_frame_time; vframe_e->duration = vfmt_e.frame_duration; enc_plugin->write_video_frame(enc_handle->priv, vframe_e, video_index); } else { vframe_v->timestamp = next_frame_time; vframe_v->duration = vfmt_v.frame_duration; enc_plugin->write_video_frame(enc_handle->priv, vframe_v, video_index); } next_frame_time += vfmt_e.frame_duration; } percentage = ((double)audio_time / (double)afmt_i.samplerate) / gavl_time_to_seconds(track_duration + start_duration + end_duration); printf("Done %6.2f %%\r", percentage * 100.0); fflush(stdout); } int main(int argc, char ** argv) { char * tmp_path; bg_plugin_handle_t * input_handle; bg_input_plugin_t * input_plugin; bg_encoder_plugin_t * enc_plugin; bg_visualization_plugin_t * vis_plugin; bg_cfg_registry_t * cfg_reg; bg_cfg_section_t * cfg_section; char ** files; gavl_audio_frame_t * aframe_i = NULL; /* Initialize random generator */ srand(time(NULL)); /* Create registries */ cfg_reg = bg_cfg_registry_create(); tmp_path = bg_search_file_read("generic", "config.xml"); bg_cfg_registry_load(cfg_reg, tmp_path); if(tmp_path) free(tmp_path); cfg_section = bg_cfg_registry_find_section(cfg_reg, "plugins"); plugin_reg = bg_plugin_registry_create(cfg_section); /* Set the plugin parameter for the commandline */ bg_plugin_registry_set_parameter_info(plugin_reg, BG_PLUGIN_VISUALIZATION, BG_PLUGIN_VISUALIZE_FRAME, &vis_parameters[0]); vis_section = bg_cfg_section_create_from_parameters("vis", vis_parameters); /* Parse commandline */ bg_cmdline_init(&app_data); bg_cmdline_parse(global_options, &argc, &argv, NULL); files = bg_cmdline_get_locations_from_args(&argc, &argv); if(!files || !files[0] || !files[1] || files[2]) { bg_cmdline_print_help(argv[0], 0); return -1; } /* Open input */ if(!load_input_file(plugin_reg, &input_handle, &input_plugin, files[0], &afmt_i)) { bg_log(BG_LOG_ERROR, LOG_DOMAIN, "Cannot open %s", files[0]); return -1; } bg_log(BG_LOG_INFO, LOG_DOMAIN, "Opened %s", files[0]); // gavl_audio_format_dump(&afmt_i); /* Open visualization */ vis_plugin = (bg_visualization_plugin_t*)vis_handle->plugin; gavl_audio_format_copy(&afmt_v, &afmt_i); memset(&vfmt_v, 0, sizeof(vfmt_v)); vfmt_v.image_width = width; vfmt_v.image_height = height; vfmt_v.frame_width = width; vfmt_v.frame_height = height; vfmt_v.pixel_width = 1; vfmt_v.pixel_height = 1; vfmt_v.timescale = fps_num; vfmt_v.frame_duration = fps_den; if(!vis_plugin->open_ov(vis_handle->priv, &afmt_v, &vfmt_v)); gavl_video_format_dump(&vfmt_v); /* Open encoder */ gavl_audio_format_copy(&afmt_e, &afmt_i); gavl_video_format_copy(&vfmt_e, &vfmt_v); if(!open_encoder(plugin_reg, &enc_handle, &enc_plugin, files[1], &afmt_e, &vfmt_e)) { bg_log(BG_LOG_ERROR, LOG_DOMAIN, "Cannot open encoder"); return -1; } /* Initialize converters */ audio_cnv_v = gavl_audio_converter_create(); convert_audio_v = gavl_audio_converter_init(audio_cnv_v, &afmt_i, &afmt_v); if(audio_index >= 0) { audio_cnv_e = gavl_audio_converter_create(); convert_audio_e = gavl_audio_converter_init(audio_cnv_e, &afmt_i, &afmt_e); } gavl_video_format_dump(&vfmt_v); gavl_video_format_dump(&vfmt_e); video_cnv_e = gavl_video_converter_create(); convert_video_e = gavl_video_converter_init(video_cnv_e, &vfmt_v, &vfmt_e); /* Create frames */ afmt_e.samples_per_frame = afmt_v.samples_per_frame; afmt_i.samples_per_frame = afmt_v.samples_per_frame; aframe_i = gavl_audio_frame_create(&afmt_i); if(convert_audio_v) aframe_v = gavl_audio_frame_create(&afmt_v); if((audio_index >= 0) && (convert_audio_e)) aframe_e = gavl_audio_frame_create(&afmt_e); vframe_v = gavl_video_frame_create(&vfmt_v); if(convert_video_e) vframe_e = gavl_video_frame_create(&vfmt_e); while(1) { if(!input_plugin->read_audio(input_handle->priv, aframe_i, 0, afmt_i.samples_per_frame)) break; iteration(aframe_i); } enc_plugin->close(enc_handle->priv, 0); return 0; } gmerlin-1.2.0~dfsg/tests/dump_plugins.c0000644000175000017500000001505011764363402020114 0ustar alessioalessio/***************************************************************** * gmerlin - a general purpose multimedia framework and applications * * Copyright (c) 2001 - 2011 Members of the Gmerlin project * gmerlin-general@lists.sourceforge.net * http://gmerlin.sourceforge.net * * 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 of the License, 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 this program. If not, see . * *****************************************************************/ #include #include #include #include #include #define FORMAT_HTML 0 #define FORMAT_TEXI 1 int format = FORMAT_HTML; static struct { bg_plugin_type_t type; char * name; char * name_internal; } plugin_types[] = { { BG_PLUGIN_INPUT, "Media input", "plugin_i" }, { BG_PLUGIN_OUTPUT_AUDIO, "Audio output", "plugin_oa" }, { BG_PLUGIN_OUTPUT_VIDEO, "Video output", "plugin_ov" }, { BG_PLUGIN_RECORDER_AUDIO, "Audio recorder", "plugin_ra" }, { BG_PLUGIN_RECORDER_VIDEO, "Video recorder", "plugin_rv" }, { BG_PLUGIN_ENCODER_AUDIO, "Encoders for audio", "plugin_ea" }, { BG_PLUGIN_ENCODER_VIDEO, "Encoders for video", "plugin_ev" }, { BG_PLUGIN_ENCODER_SUBTITLE_TEXT, "Encoders for text subtitles", "plugin_est" }, { BG_PLUGIN_ENCODER_SUBTITLE_OVERLAY, "Encoders for overlay subtitles", "plugin_eso" }, { BG_PLUGIN_ENCODER, "Encoders for multiple stream types", "plugin_e" }, { BG_PLUGIN_ENCODER_PP, "Encoder postprocessors", "plugin_epp" }, { BG_PLUGIN_IMAGE_READER, "Image readers", "plugin_ir" }, { BG_PLUGIN_IMAGE_WRITER, "Image writers", "plugin_iw" }, { BG_PLUGIN_FILTER_AUDIO, "Audio filters", "plugin_fa" }, { BG_PLUGIN_FILTER_VIDEO, "Video filters", "plugin_fv" }, { BG_PLUGIN_VISUALIZATION, "Visualizations", "plugin_vis" }, { }, }; char * internal_name = "Internal plugin"; static const char * get_filename(const char * filename) { const char * pos; const char * ret = NULL; if(!filename) return internal_name; pos = filename; while(*pos != '\0') { if(*pos == '/') ret = pos+1; pos++; } return ret; } static void dump_plugins(bg_plugin_registry_t * plugin_reg, int type) { int i, num; const bg_plugin_info_t * info; num = bg_plugin_registry_get_num_plugins(plugin_reg, type, BG_PLUGIN_ALL); for(i = 0; i < num; i++) { info = bg_plugin_find_by_index(plugin_reg, i, type, BG_PLUGIN_ALL); if(info->api != BG_PLUGIN_API_GMERLIN) continue; if(format == FORMAT_HTML) { printf("\n"); printf(" \n", info->name); printf(" \n", info->long_name); printf(" \n", get_filename(info->module_filename)); printf(" \n", info->description); printf("
Internal name%s
External name%s
Module%s
Description%s

\n"); } else { printf("@subsection %s\n", info->long_name); printf("@table @i\n"); printf("@item Internal name\n%s\n", info->name); printf("@item Module\n%s\n", get_filename(info->module_filename)); printf("@item Description\n%s\n", info->description); printf("@end table\n"); } } } int main(int argc, char ** argv) { int i; char * tmp_path; bg_cfg_registry_t * cfg_reg; bg_cfg_section_t * cfg_section; bg_plugin_registry_t * plugin_reg; if(argc > 1) { if(!strcmp(argv[1], "-t")) format = FORMAT_TEXI; else { fprintf(stderr, "Usage: %s [-t]\n", argv[0]); return -1; } } /* Create config registry */ cfg_reg = bg_cfg_registry_create(); tmp_path = bg_search_file_read("generic", "config.xml"); bg_cfg_registry_load(cfg_reg, tmp_path); if(tmp_path) free(tmp_path); /* Get the config section for the plugins */ cfg_section = bg_cfg_registry_find_section(cfg_reg, "plugins"); /* Create plugin registry */ plugin_reg = bg_plugin_registry_create(cfg_section); /* @menu * Introduction: gui_intro. * Static and dynamic .parameters = gui_statdyn. * Configuring input plugins: gui_i. * Configuring filters: gui_f. * Log messages: gui_log. * Tips: gui_tips. @end menu */ if(format == FORMAT_TEXI) { printf("@menu\n"); } else { printf("\n"); printf("\n"); printf("\n"); printf(" Gmerlin\n"); printf(" \n"); printf("\n\n"); printf("\n"); printf("

Plugins

\n"); printf("The following are only the plugins, you can download from this site.\n"); printf("Gmerlin applications also load
ladspa, \n"); printf("libvisual \n"); printf("and frei0r plugins.\n"); printf("

\n"); } i = 0; while(plugin_types[i].name) { if(format == FORMAT_HTML) { printf("%s
\n", plugin_types[i].name_internal, plugin_types[i].name); } else { printf("* %s: %s.\n", plugin_types[i].name, plugin_types[i].name_internal); } i++; } if(format == FORMAT_TEXI) { printf("@end menu\n\n"); } i = 0; while(plugin_types[i].name) { if(format == FORMAT_HTML) { printf("

%s


\n", plugin_types[i].name_internal, plugin_types[i].name); } else { printf("@node %s\n@section %s\n\n", plugin_types[i].name_internal, plugin_types[i].name); } dump_plugins(plugin_reg, plugin_types[i].type); i++; } if(format == FORMAT_HTML) { printf("\n"); } return 0; } gmerlin-1.2.0~dfsg/tests/fvtest.c0000644000175000017500000002225711764363402016730 0ustar alessioalessio/***************************************************************** * gmerlin - a general purpose multimedia framework and applications * * Copyright (c) 2001 - 2011 Members of the Gmerlin project * gmerlin-general@lists.sourceforge.net * http://gmerlin.sourceforge.net * * 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 of the License, 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 this program. If not, see . * *****************************************************************/ #include #include #include #include #include #include #include #include bg_video_filter_chain_t * fc; const bg_parameter_info_t * fv_parameters; bg_cfg_section_t * fv_section = NULL; bg_cfg_section_t * opt_section = NULL; bg_gavl_video_options_t opt; int frameno = 0; int dump_format = 0; static void opt_frame(void * data, int * argc, char *** _argv, int arg) { if(arg >= *argc) { fprintf(stderr, "Option -frame requires an argument\n"); exit(-1); } frameno = atoi((*_argv)[arg]); bg_cmdline_remove_arg(argc, _argv, arg); } static void opt_df(void * data, int * argc, char *** _argv, int arg) { dump_format = 1; } static void opt_v(void * data, int * argc, char *** _argv, int arg) { int val, verbose = 0; if(arg >= *argc) { fprintf(stderr, "Option -v requires an argument\n"); exit(-1); } val = atoi((*_argv)[arg]); if(val > 0) verbose |= BG_LOG_ERROR; if(val > 1) verbose |= BG_LOG_WARNING; if(val > 2) verbose |= BG_LOG_INFO; if(val > 3) verbose |= BG_LOG_DEBUG; bg_log_set_verbose(verbose); bg_cmdline_remove_arg(argc, _argv, arg); } static void opt_fv(void * data, int * argc, char *** _argv, int arg) { if(arg >= *argc) { fprintf(stderr, "Option -fv requires an argument\n"); exit(-1); } if(!bg_cmdline_apply_options(fv_section, bg_video_filter_chain_set_parameter, fc, fv_parameters, (*_argv)[arg])) exit(-1); bg_cmdline_remove_arg(argc, _argv, arg); } static bg_parameter_info_t opt_parameters[] = { BG_GAVL_PARAM_THREADS, { /* */ }, }; static void opt_set_param(void * data, const char * name, const bg_parameter_value_t * val) { bg_gavl_video_set_parameter(data, name, val); } static void opt_opt(void * data, int * argc, char *** _argv, int arg) { if(arg >= *argc) { fprintf(stderr, "Option -opt requires an argument\n"); exit(-1); } if(!bg_cmdline_apply_options(opt_section, opt_set_param, &opt, opt_parameters, (*_argv)[arg])) exit(-1); bg_cmdline_remove_arg(argc, _argv, arg); } static bg_cmdline_arg_t global_options[] = { { .arg = "-fv", .help_arg = "", .help_string = "Set filter options", .callback = opt_fv, }, { .arg = "-opt", .help_arg = "