static const struct audio_format * ao_filter_open(struct audio_output *ao, struct audio_format *audio_format, GError **error_r) { assert(audio_format_valid(audio_format)); /* the replay_gain filter cannot fail here */ if (ao->replay_gain_filter != NULL) filter_open(ao->replay_gain_filter, audio_format, error_r); if (ao->other_replay_gain_filter != NULL) filter_open(ao->other_replay_gain_filter, audio_format, error_r); const struct audio_format *af = filter_open(ao->filter, audio_format, error_r); if (af == NULL) { if (ao->replay_gain_filter != NULL) filter_close(ao->replay_gain_filter); if (ao->other_replay_gain_filter != NULL) filter_close(ao->other_replay_gain_filter); } return af; }
static void ao_filter_close(struct audio_output *ao) { if (ao->replay_gain_filter != NULL) filter_close(ao->replay_gain_filter); if (ao->other_replay_gain_filter != NULL) filter_close(ao->other_replay_gain_filter); filter_close(ao->filter); }
static void autoconvert_filter_close(struct filter *_filter) { struct autoconvert_filter *filter = (struct autoconvert_filter *)_filter; if (filter->convert != NULL) { filter_close(filter->convert); filter_free(filter->convert); } filter_close(filter->filter); }
static const struct audio_format * autoconvert_filter_open(struct filter *_filter, struct audio_format *in_audio_format, GError **error_r) { struct autoconvert_filter *filter = (struct autoconvert_filter *)_filter; const struct audio_format *out_audio_format; assert(audio_format_valid(in_audio_format)); /* open the "real" filter */ filter->in_audio_format = *in_audio_format; out_audio_format = filter_open(filter->filter, &filter->in_audio_format, error_r); if (out_audio_format == NULL) return NULL; /* need to convert? */ if (!audio_format_equals(&filter->in_audio_format, in_audio_format)) { /* yes - create a convert_filter */ struct audio_format audio_format2 = *in_audio_format; const struct audio_format *audio_format3; filter->convert = filter_new(&convert_filter_plugin, NULL, error_r); if (filter->convert == NULL) { filter_close(filter->filter); return NULL; } audio_format3 = filter_open(filter->convert, &audio_format2, error_r); if (audio_format3 == NULL) { filter_free(filter->convert); filter_close(filter->filter); return NULL; } assert(audio_format_equals(&audio_format2, in_audio_format)); convert_filter_set(filter->convert, &filter->in_audio_format); } else /* no */ filter->convert = NULL; return out_audio_format; }
static void chain_close_child(gpointer data, G_GNUC_UNUSED gpointer user_data) { struct filter *filter = data; filter_close(filter); }
static const struct audio_format * chain_open_child(struct filter *filter, const struct audio_format *prev_audio_format, GError **error_r) { struct audio_format conv_audio_format = *prev_audio_format; const struct audio_format *next_audio_format; next_audio_format = filter_open(filter, &conv_audio_format, error_r); if (next_audio_format == NULL) return NULL; if (!audio_format_equals(&conv_audio_format, prev_audio_format)) { struct audio_format_string s; filter_close(filter); g_set_error(error_r, filter_quark(), 0, "Audio format not supported by filter '%s': %s", filter->plugin->name, audio_format_to_string(prev_audio_format, &s)); return NULL; } return next_audio_format; }
static void ao_reopen_filter(struct audio_output *ao) { const struct audio_format *filter_audio_format; GError *error = NULL; filter_close(ao->filter); filter_audio_format = filter_open(ao->filter, &ao->in_audio_format, &error); if (filter_audio_format == NULL) { g_warning("Failed to open filter for \"%s\" [%s]: %s", ao->name, ao->plugin->name, error->message); g_error_free(error); /* this is a little code duplication fro ao_close(), but we cannot call this function because we must not call filter_close(ao->filter) again */ ao->pipe = NULL; ao->chunk = NULL; ao->open = false; ao->fail_timer = g_timer_new(); g_mutex_unlock(ao->mutex); ao_plugin_close(ao->plugin, ao->data); g_mutex_lock(ao->mutex); return; } convert_filter_set(ao->convert_filter, &ao->out_audio_format); }
static void quh_signal_handler (int signum) { switch (signum) { case SIGINT: case SIGTERM: if (quh.filter_chain) filter_close (quh.filter_chain, &quh.nfo); fflush (stdout); fputs ("Quh: break", stderr); exit (0); break; default: break; } }
/** * Close all filters in the chain until #until is reached. #until * itself is not closed. */ static void chain_close_until(struct filter_chain *chain, const struct filter *until) { GSList *i = chain->children; struct filter *filter; while (true) { /* this assertion fails if #until does not exist (anymore) */ assert(i != NULL); if (i->data == until) /* don't close this filter */ break; /* close this filter */ filter = i->data; filter_close(filter); i = g_slist_next(i); } }
static void ao_close(struct audio_output *ao, bool drain) { assert(ao->open); ao->pipe = NULL; ao->chunk = NULL; ao->open = false; g_mutex_unlock(ao->mutex); if (drain) ao_plugin_drain(ao->plugin, ao->data); else ao_plugin_cancel(ao->plugin, ao->data); ao_plugin_close(ao->plugin, ao->data); filter_close(ao->filter); g_mutex_lock(ao->mutex); g_debug("closed plugin=%s name=\"%s\"", ao->plugin->name, ao->name); }
int main(int argc, char **argv) { struct audio_format audio_format; struct audio_format_string af_string; bool success; GError *error = NULL; struct filter *filter; const struct audio_format *out_audio_format; char buffer[4096]; size_t frame_size; if (argc < 3 || argc > 4) { g_printerr("Usage: run_filter CONFIG NAME [FORMAT] <IN\n"); return 1; } audio_format_init(&audio_format, 44100, SAMPLE_FORMAT_S16, 2); /* initialize GLib */ g_thread_init(NULL); g_log_set_default_handler(my_log_func, NULL); /* read configuration file (mpd.conf) */ config_global_init(); success = config_read_file(argv[1], &error); if (!success) { g_printerr("%s:", error->message); g_error_free(error); return 1; } /* parse the audio format */ if (argc > 3) { success = audio_format_parse(&audio_format, argv[3], false, &error); if (!success) { g_printerr("Failed to parse audio format: %s\n", error->message); g_error_free(error); return 1; } } /* initialize the filter */ filter = load_filter(argv[2]); if (filter == NULL) return 1; /* open the filter */ out_audio_format = filter_open(filter, &audio_format, &error); if (out_audio_format == NULL) { g_printerr("Failed to open filter: %s\n", error->message); g_error_free(error); filter_free(filter); return 1; } g_printerr("audio_format=%s\n", audio_format_to_string(out_audio_format, &af_string)); frame_size = audio_format_frame_size(&audio_format); /* play */ while (true) { ssize_t nbytes; size_t length; const void *dest; nbytes = read(0, buffer, sizeof(buffer)); if (nbytes <= 0) break; dest = filter_filter(filter, buffer, (size_t)nbytes, &length, &error); if (dest == NULL) { g_printerr("Filter failed: %s\n", error->message); filter_close(filter); filter_free(filter); return 1; } nbytes = write(1, dest, length); if (nbytes < 0) { g_printerr("Failed to write: %s\n", strerror(errno)); filter_close(filter); filter_free(filter); return 1; } } /* cleanup and exit */ filter_close(filter); filter_free(filter); config_global_finish(); return 0; }
int main(int argc, char **argv){ /* extract program name from path. e.g. /path/to/MArCd -> MArCd */ const char* separator = strrchr(argv[0], '/'); if ( separator ){ program_name = separator + 1; } else { program_name = argv[0]; } struct filter filter; if ( filter_from_argv(&argc, argv, &filter) != 0 ){ return 0; /* error already shown */ } int op, option_index = -1; while ( (op = getopt_long(argc, argv, shortopts, longopts, &option_index)) != -1 ){ switch (op){ case 0: /* long opt */ case '?': /* unknown opt */ break; case '1': case '2': case '3': case '4': { const unsigned int mask = (7<<FORMAT_LAYER_BIT); flags &= ~mask; /* reset all layer bits */ flags |= (op-'0')<<FORMAT_LAYER_BIT; break; } case 'd': /* --calender */ flags |= FORMAT_DATE_STR | FORMAT_DATE_UTC; break; case 'D': /* --localtime */ flags |= FORMAT_DATE_STR | FORMAT_DATE_LOCALTIME; break; case 'a': /* --absolute */ flags &= ~FORMAT_REL_TIMESTAMP; break; case 'r': /* --relative */ flags |= FORMAT_REL_TIMESTAMP; break; case 'H': /* --headers */ flags |= FORMAT_HEADER; break; case 'p': /* --packets */ max_packets = atoi(optarg); break; case 'c': /* --packets */ max_matched_packets = atoi(optarg); break; case 't': /* --timeout */ { int tmp = atoi(optarg); timeout.tv_sec = tmp / 1000; timeout.tv_usec = tmp % 1000 * 1000; } break; case 'x': /* --hexdump */ flags |= FORMAT_HEXDUMP; break; case 'i': /* --iface */ iface = optarg; break; case ARGUMENT_VERSION: /* --version */ show_version(); return 0; case 'h': /* --help */ show_usage(); return 0; default: fprintf (stderr, "%s: argument '-%c' declared but not handled\n", argv[0], op); } } int ret; /* Open stream(s) */ struct stream* stream; if ( (ret=stream_from_getopt(&stream, argv, optind, argc, iface, "-", program_name, 0)) != 0 ) { return ret; /* Error already shown */ } const stream_stat_t* stat = stream_get_stat(stream); stream_print_info(stream, stderr); /* handle C-c */ signal(SIGINT, handle_sigint); /* setup formatter */ struct format format; format_setup(&format, flags); uint64_t matched = 0; while ( keep_running ) { /* A short timeout is used to allow the application to "breathe", i.e * terminate if SIGINT was received. */ struct timeval tv = timeout; /* Read the next packet */ cap_head* cp; ret = stream_read(stream, &cp, NULL, &tv); if ( ret == EAGAIN ){ continue; /* timeout */ } else if ( ret != 0 ){ break; /* shutdown or error */ } /* identify connection even if filter doesn't match so id will be * deterministic when changing the filter */ connection_id(cp); if ( filter_match(&filter, cp->payload, cp) ){ format_pkg(stdout, &format, cp); matched++; } else { format_ignore(stdout, &format, cp); } if ( max_packets > 0 && stat->matched >= max_packets) { /* Read enough pkts lets break. */ break; } if ( max_matched_packets > 0 && matched >= max_matched_packets) { /* Read enough pkts lets break. */ break; } } /* if ret == -1 the stream was closed properly (e.g EOF or TCP shutdown) * In addition EINTR should not give any errors because it is implied when the * user presses C-c */ if ( ret > 0 && ret != EINTR ){ fprintf(stderr, "stream_read() returned 0x%08X: %s\n", ret, caputils_error_string(ret)); } /* Write stats */ fprintf(stderr, "%"PRIu64" packets read.\n", stat->read); fprintf(stderr, "%"PRIu64" packets matched filter.\n", matched); /* Release resources */ stream_close(stream); filter_close(&filter); return 0; }
static void ao_open(struct audio_output *ao) { bool success; GError *error = NULL; const struct audio_format *filter_audio_format; struct audio_format_string af_string; assert(!ao->open); assert(ao->fail_timer == NULL); assert(ao->pipe != NULL); assert(ao->chunk == NULL); /* enable the device (just in case the last enable has failed) */ if (!ao_enable(ao)) /* still no luck */ return; /* open the filter */ filter_audio_format = filter_open(ao->filter, &ao->in_audio_format, &error); if (filter_audio_format == NULL) { g_warning("Failed to open filter for \"%s\" [%s]: %s", ao->name, ao->plugin->name, error->message); g_error_free(error); ao->fail_timer = g_timer_new(); return; } ao->out_audio_format = *filter_audio_format; audio_format_mask_apply(&ao->out_audio_format, &ao->config_audio_format); g_mutex_unlock(ao->mutex); success = ao_plugin_open(ao->plugin, ao->data, &ao->out_audio_format, &error); g_mutex_lock(ao->mutex); assert(!ao->open); if (!success) { g_warning("Failed to open \"%s\" [%s]: %s", ao->name, ao->plugin->name, error->message); g_error_free(error); filter_close(ao->filter); ao->fail_timer = g_timer_new(); return; } convert_filter_set(ao->convert_filter, &ao->out_audio_format); ao->open = true; g_debug("opened plugin=%s name=\"%s\" " "audio_format=%s", ao->plugin->name, ao->name, audio_format_to_string(&ao->out_audio_format, &af_string)); if (!audio_format_equals(&ao->in_audio_format, &ao->out_audio_format)) g_debug("converting from %s", audio_format_to_string(&ao->in_audio_format, &af_string)); }