📄 vorbis.c
字号:
pthread_mutex_unlock(&vf_mutex); timercount = vorbis_ip.output->output_time(); last_section = current_section; } if (!(vi->bitrate_upper == vi->bitrate_lower == vi->bitrate_nominal) && (vorbis_ip.output->output_time() > timercount + 1000 || vorbis_ip.output->output_time() < timercount)) { /* * simple hack to avoid updating too * often */ long br; pthread_mutex_lock(&vf_mutex); br = ov_bitrate_instant(&vf); pthread_mutex_unlock(&vf_mutex); if (br > 0) vorbis_ip.set_info(title, time, br, samplerate, channels); timercount = vorbis_ip.output->output_time(); } } if (!output_error) vorbis_ip.output->close_audio(); /* fall through intentional */ play_cleanup: if (title) g_free(title); g_free(filename); /* * ov_clear closes the stream if its open. Safe to call on an * uninitialized structure as long as we've zeroed it */ pthread_mutex_lock(&vf_mutex); ov_clear(&vf); pthread_mutex_unlock(&vf_mutex); vorbis_is_streaming = 0; return NULL;}static void vorbis_play(char *filename){ vorbis_playing = 1; vorbis_bytes_streamed = 0; vorbis_eos = 0; output_error = FALSE; pthread_create(&tid, NULL, vorbis_play_loop, g_strdup(filename));} static void vorbis_stop(void){ if (vorbis_playing) { vorbis_playing = 0; pthread_join(tid, NULL); }}static void vorbis_pause(short p){ vorbis_ip.output->pause(p);}static int vorbis_time(void){ if (output_error) return -2; if (vorbis_eos && !vorbis_ip.output->buffer_playing()) return -1; return vorbis_ip.output->output_time();}static void vorbis_seek(int time){ if (vorbis_is_streaming) return; seekneeded = time; while (seekneeded != -1) xmms_usleep(20000);}static void vorbis_get_song_info(char *filename, char **title, int *length){ FILE *stream; OggVorbis_File vf; /* avoid thread interaction */ if (strncasecmp(filename, "http://", 7)) { if ((stream = fopen(filename, "r")) == NULL) return; /* * The open function performs full stream detection and * machine initialization. If it returns zero, the stream * *is* Vorbis and we're fully ready to decode. */ pthread_mutex_lock(&vf_mutex); if (ov_open(stream, &vf, NULL, 0) < 0) { pthread_mutex_unlock(&vf_mutex); fclose(stream); return; } /* Retrieve the length */ *length = ov_time_total(&vf, -1) * 1000; *title = NULL; *title = vorbis_generate_title(&vf, filename); /* * once the ov_open succeeds, the stream belongs to * vorbisfile.a. ov_clear will fclose it */ ov_clear(&vf); pthread_mutex_unlock(&vf_mutex); } else { /* streaming song info */ *length = -1; *title = (char *)vorbis_http_get_title(filename); }}static gchar *extname(const char *filename){ gchar *ext = strrchr(filename, '.'); if (ext != NULL) ++ext; return ext;}/* Make sure you've locked vf_mutex */static gboolean vorbis_update_replaygain(float *scale){ vorbis_comment *comment; char *rg_gain = NULL, *rg_peak_str = NULL; float rg_peak; if (!vorbis_cfg.use_replaygain && !vorbis_cfg.use_anticlip) return FALSE; if ((comment = ov_comment(&vf, -1)) == NULL) return FALSE; *scale = 1.0; if (vorbis_cfg.use_replaygain) { if (vorbis_cfg.replaygain_mode == REPLAYGAIN_MODE_ALBUM) { rg_gain = vorbis_comment_query(comment, "replaygain_album_gain", 0); if (!rg_gain) /* Obsolete name */ rg_gain = vorbis_comment_query(comment, "rg_audiophile", 0); } if (!rg_gain) rg_gain = vorbis_comment_query(comment, "replaygain_track_gain", 0); if (!rg_gain) /* Obsolete name */ rg_gain = vorbis_comment_query(comment, "rg_radio", 0); /* FIXME: Make sure this string is the correct format first? */ if (rg_gain) *scale = pow(10., atof(rg_gain)/20); } if (vorbis_cfg.use_anticlip) { if (vorbis_cfg.replaygain_mode == REPLAYGAIN_MODE_ALBUM) rg_peak_str = vorbis_comment_query(comment, "replaygain_album_peak", 0); if (!rg_peak_str) rg_peak_str = vorbis_comment_query(comment, "replaygain_track_peak", 0); if (!rg_peak_str) /* Obsolete name */ rg_peak_str = vorbis_comment_query(comment, "rg_peak", 0); if (rg_peak_str) rg_peak = atof(rg_peak_str); else rg_peak = 1; if (*scale * rg_peak > 1.0) *scale = 1.0 / rg_peak; } if (*scale != 1.0 || vorbis_cfg.use_booster) { if (*scale > 15.0) *scale = 15.0; return TRUE; } return FALSE;}static long vorbis_process_replaygain(float **pcm, int samples, int ch, char *pcmout, float rg_scale){ int i, j; /* ReplayGain processing */ for (i = 0; i < samples; i++) for (j = 0; j < ch; j++) { float sample = pcm[j][i] * rg_scale; int value; if (vorbis_cfg.use_booster) { sample *= 2; /* hard 6dB limiting */ if (sample < -0.5) sample = tanh((sample + 0.5) / 0.5) * 0.5 - 0.5; else if (sample > 0.5) sample = tanh((sample - 0.5) / 0.5) * 0.5 + 0.5; } value = sample * 32767; if (value > 32767) value = 32767; else if (value < -32767) value = -32767; *pcmout++ = GET_BYTE1(value); *pcmout++ = GET_BYTE2(value); } return 2 * ch * samples;} static char *vorbis_generate_title(OggVorbis_File *vorbisfile, char *fn){ /* Caller should hold vf_mutex */ char *displaytitle = NULL, *tmp, *path, *temp; vorbis_comment *comment; TitleInput *input; XMMS_NEW_TITLEINPUT(input); path = g_strdup(fn); temp = strrchr(path, '/'); if (temp) *temp = '\0'; input->file_name = g_basename(fn); input->file_ext = extname(fn); input->file_path = g_strdup_printf("%s/", path); if ((comment = ov_comment(vorbisfile, -1)) != NULL) { input->track_name = convert_from_utf8(vorbis_comment_query(comment, "title", 0)); input->performer = convert_from_utf8(vorbis_comment_query(comment, "artist", 0)); input->album_name = convert_from_utf8(vorbis_comment_query(comment, "album", 0)); if ((tmp = vorbis_comment_query(comment, "tracknumber", 0)) != NULL) input->track_number = atoi(tmp); input->date = convert_from_utf8(vorbis_comment_query(comment, "date", 0)); if ((tmp = vorbis_comment_query(comment, "year", 0)) != NULL) input->year = atoi(tmp); input->genre = convert_from_utf8(vorbis_comment_query(comment, "genre", 0)); /* "comment" = user comment, not "" */ input->comment = convert_from_utf8(vorbis_comment_query(comment, "comment", 0)); } displaytitle = xmms_get_titlestring(vorbis_cfg.tag_override ? vorbis_cfg.tag_format : xmms_get_gentitle_format(), input); g_free(input->track_name); g_free(input->performer); g_free(input->album_name); g_free(input->date); g_free(input->genre); g_free(input->comment); g_free(input); g_free(path); if (!displaytitle) { if (!vorbis_is_streaming) { char *tmp; displaytitle = g_strdup(g_basename(fn)); if ((tmp = strrchr(displaytitle, '.')) != NULL) *tmp = '\0'; } else displaytitle = vorbis_http_get_title(fn); } return displaytitle;}static void vorbis_aboutbox(){ static GtkWidget *about_window; if (about_window) gdk_window_raise(about_window->window); about_window = xmms_show_message( _("About Ogg Vorbis Plugin"), /* * I18N: UTF-8 Translation: "Haavard Kvaalen" -> * "H\303\245vard Kv\303\245len" */ _("Ogg Vorbis Plugin by the Xiph.org Foundation\n\n" "Original code by\n" "Tony Arcieri <bascule@inferno.tusculum.edu>\n" "Contributions from\n" "Chris Montgomery <monty@xiph.org>\n" "Peter Alm <peter@xmms.org>\n" "Michael Smith <msmith@labyrinth.edu.au>\n" "Jack Moffitt <jack@icecast.org>\n" "Jorn Baayen <jorn@nl.linux.org>\n" "Haavard Kvaalen <havardk@xmms.org>\n" "Gian-Carlo Pascutto <gcp@sjeng.org>\n\n" "Visit the Xiph.org Foundation at http://www.xiph.org/\n"), _("Ok"), FALSE, NULL, NULL); gtk_signal_connect(GTK_OBJECT(about_window), "destroy", GTK_SIGNAL_FUNC(gtk_widget_destroyed), &about_window);}static void vorbis_init(void){ ConfigFile *cfg; memset(&vorbis_cfg, 0, sizeof(vorbis_config_t)); vorbis_cfg.http_buffer_size = 128; vorbis_cfg.http_prebuffer = 25; vorbis_cfg.proxy_port = 8080; vorbis_cfg.proxy_use_auth = FALSE; vorbis_cfg.proxy_user = NULL; vorbis_cfg.proxy_pass = NULL; vorbis_cfg.tag_override = FALSE; vorbis_cfg.tag_format = NULL; vorbis_cfg.use_anticlip = FALSE; vorbis_cfg.use_replaygain = FALSE; vorbis_cfg.replaygain_mode = REPLAYGAIN_MODE_TRACK; vorbis_cfg.use_booster = FALSE; cfg = xmms_cfg_open_default_file(); xmms_cfg_read_int(cfg, "vorbis", "http_buffer_size", &vorbis_cfg.http_buffer_size); xmms_cfg_read_int(cfg, "vorbis", "http_prebuffer", &vorbis_cfg.http_prebuffer); xmms_cfg_read_boolean(cfg, "vorbis", "save_http_stream", &vorbis_cfg.save_http_stream); if (!xmms_cfg_read_string(cfg, "vorbis", "save_http_path", &vorbis_cfg.save_http_path)) vorbis_cfg.save_http_path = g_strdup(g_get_home_dir()); xmms_cfg_read_boolean(cfg, "vorbis", "use_proxy", &vorbis_cfg.use_proxy); if (!xmms_cfg_read_string(cfg, "vorbis", "proxy_host", &vorbis_cfg.proxy_host)) vorbis_cfg.proxy_host = g_strdup("localhost"); xmms_cfg_read_int(cfg, "vorbis", "proxy_port", &vorbis_cfg.proxy_port); xmms_cfg_read_boolean(cfg, "vorbis", "proxy_use_auth", &vorbis_cfg.proxy_use_auth); xmms_cfg_read_string(cfg, "vorbis", "proxy_user", &vorbis_cfg.proxy_user); xmms_cfg_read_string(cfg, "vorbis", "proxy_pass", &vorbis_cfg.proxy_pass); xmms_cfg_read_boolean(cfg, "vorbis", "tag_override", &vorbis_cfg.tag_override); if (!xmms_cfg_read_string(cfg, "vorbis", "tag_format", &vorbis_cfg.tag_format)) vorbis_cfg.tag_format = g_strdup("%p - %t"); xmms_cfg_read_boolean(cfg, "vorbis", "use_anticlip", &vorbis_cfg.use_anticlip); xmms_cfg_read_boolean(cfg, "vorbis", "use_replaygain", &vorbis_cfg.use_replaygain); xmms_cfg_read_int(cfg, "vorbis", "replaygain_mode", &vorbis_cfg.replaygain_mode); xmms_cfg_read_boolean(cfg, "vorbis", "use_booster", &vorbis_cfg.use_booster); xmms_cfg_free(cfg);}static size_t ovcb_read(void *ptr, size_t size, size_t nmemb, void *datasource){ size_t tmp; if (vorbis_is_streaming) { /* this is a stream */ tmp = vorbis_http_read(ptr, size * nmemb); vorbis_bytes_streamed += tmp; return tmp; } return fread(ptr, size, nmemb, (FILE *)datasource);}static int ovcb_seek(void *datasource, int64_t offset, int whence){ if (vorbis_is_streaming) { /* this is a stream */ /* streams aren't seekable */ return -1; } return fseek((FILE *)datasource, offset, whence);}static int ovcb_close(void *datasource){ if (vorbis_is_streaming) { /* this is a stream */ vorbis_http_close(); return 0; } return fclose((FILE *)datasource);}static long ovcb_tell(void *datasource){ if (vorbis_is_streaming) { /* this is a stream */ /* return bytes read */ return vorbis_bytes_streamed; } return ftell((FILE *)datasource);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -