static bool_t id3v24_write_tag (const Tuple * tuple, VFSFile * f) { int version, header_size, data_size, footer_size; bool_t syncsafe; int64_t offset; if (! read_header (f, & version, & syncsafe, & offset, & header_size, & data_size, & footer_size)) return FALSE; //read all frames into generic frames; GHashTable * dict = g_hash_table_new_full (g_str_hash, g_str_equal, (GDestroyNotify) str_unref, (GDestroyNotify) free_frame_list); read_all_frames (f, version, syncsafe, data_size, dict); //make the new frames from tuple and replace in the dictionary the old frames with the new ones add_frameFromTupleStr (tuple, FIELD_TITLE, ID3_TITLE, dict); add_frameFromTupleStr (tuple, FIELD_ARTIST, ID3_ARTIST, dict); add_frameFromTupleStr (tuple, FIELD_ALBUM, ID3_ALBUM, dict); add_frameFromTupleInt (tuple, FIELD_YEAR, ID3_YEAR, dict); add_frameFromTupleInt (tuple, FIELD_TRACK_NUMBER, ID3_TRACKNR, dict); add_frameFromTupleStr (tuple, FIELD_GENRE, ID3_GENRE, dict); char * comment = tuple_get_str (tuple, FIELD_COMMENT); add_comment_frame (comment, dict); str_unref (comment); if (! offset) { if (! cut_beginning_tag (f, header_size + data_size + footer_size)) goto ERR; } else { if (offset + header_size + data_size + footer_size != vfs_fsize (f)) goto ERR; if (vfs_ftruncate (f, offset)) goto ERR; } offset = vfs_fsize (f); if (offset < 0 || vfs_fseek (f, offset, SEEK_SET) || ! write_header (f, 0, FALSE)) goto ERR; data_size = write_all_frames (f, dict); if (! write_header (f, data_size, TRUE) || vfs_fseek (f, offset, SEEK_SET) || ! write_header (f, data_size, FALSE)) goto ERR; g_hash_table_destroy (dict); return TRUE; ERR: g_hash_table_destroy (dict); return FALSE; }
static gboolean id3v24_write_tag (const Tuple * tuple, VFSFile * f) { gint version, header_size, data_size, footer_size; gboolean syncsafe; gint64 offset; if (! read_header (f, & version, & syncsafe, & offset, & header_size, & data_size, & footer_size)) return FALSE; //read all frames into generic frames; mowgli_dictionary_t * dict = mowgli_dictionary_create (strcasecmp); read_all_frames (f, version, syncsafe, data_size, dict); //make the new frames from tuple and replace in the dictionary the old frames with the new ones add_frameFromTupleStr (tuple, FIELD_TITLE, ID3_TITLE, dict); add_frameFromTupleStr (tuple, FIELD_ARTIST, ID3_ARTIST, dict); add_frameFromTupleStr (tuple, FIELD_ALBUM, ID3_ALBUM, dict); add_frameFromTupleInt (tuple, FIELD_YEAR, ID3_YEAR, dict); add_frameFromTupleInt (tuple, FIELD_TRACK_NUMBER, ID3_TRACKNR, dict); add_frameFromTupleStr (tuple, FIELD_GENRE, ID3_GENRE, dict); add_comment_frame (tuple_get_string (tuple, FIELD_COMMENT, NULL), dict); if (! offset) { if (! cut_beginning_tag (f, header_size + data_size + footer_size)) goto ERR; } else { if (offset + header_size + data_size + footer_size != vfs_fsize (f)) goto ERR; if (vfs_ftruncate (f, offset)) goto ERR; } offset = vfs_fsize (f); if (offset < 0 || vfs_fseek (f, offset, SEEK_SET) || ! write_header (f, 0, FALSE)) goto ERR; data_size = writeAllFramesToFile (f, dict); if (! write_header (f, data_size, TRUE) || vfs_fseek (f, offset, SEEK_SET) || ! write_header (f, data_size, FALSE)) goto ERR; mowgli_dictionary_destroy (dict, free_frame_cb, NULL); return TRUE; ERR: mowgli_dictionary_destroy (dict, free_frame_cb, NULL); return FALSE; }
void metadata_callback(const FLAC__StreamDecoder *decoder, const FLAC__StreamMetadata *metadata, void *client_data) { callback_info *info = (callback_info*) client_data; gsize size; if (metadata->type == FLAC__METADATA_TYPE_STREAMINFO) { info->stream.samples = metadata->data.stream_info.total_samples; AUDDBG("total_samples=%lld\n", (long long) metadata->data.stream_info.total_samples); info->stream.bits_per_sample = metadata->data.stream_info.bits_per_sample; AUDDBG("bits_per_sample=%d\n", metadata->data.stream_info.bits_per_sample); info->stream.channels = metadata->data.stream_info.channels; AUDDBG("channels=%d\n", metadata->data.stream_info.channels); info->stream.samplerate = metadata->data.stream_info.sample_rate; AUDDBG("sample_rate=%d\n", metadata->data.stream_info.sample_rate); size = vfs_fsize(info->fd); if (size == -1 || info->stream.samples == 0) info->bitrate = 0; else info->bitrate = 8 * size * (gint64) info->stream.samplerate / info->stream.samples; AUDDBG("bitrate=%d\n", info->bitrate); info->metadata_changed = TRUE; } }
static gint64 seek_cb (void * file, gint64 offset, gint whence) { if (whence == AVSEEK_SIZE) return vfs_fsize (file); if (vfs_fseek (file, offset, whence & ~(gint) AVSEEK_FORCE)) return -1; return vfs_ftell (file); }
static uint32_t wv_get_length(void *id) { VFSFile *file = (VFSFile *) id; if (file == NULL) return 0; return vfs_fsize(file); }
/* Load a file to a buffer, return 0 on success, negative value on error */ gint xs_fload_buffer(const gchar *filename, guint8 **buf, size_t *bufSize) { xs_file_t *f; glong seekPos; /* Open file, get file size */ if ((f = xs_fopen(filename, "rb")) == NULL) return -1; #ifdef __AUDACIOUS_NEWVFS__ seekPos = vfs_fsize(f); #else xs_fseek(f, 0L, SEEK_END); seekPos = xs_ftell(f); #endif if (seekPos > 0) { size_t readSize = seekPos; if (readSize >= *bufSize || *buf == NULL) { /* Only re-allocate if the required size > current */ if (*buf != NULL) { g_free(*buf); *buf = NULL; } *bufSize = seekPos; *buf = (guint8 *) g_malloc(*bufSize * sizeof(guint8)); if (*buf == NULL) { xs_fclose(f); return -2; } } /* Read data */ if (xs_fseek(f, 0, SEEK_SET)) readSize = 0; else readSize = xs_fread(*buf, 1, *bufSize, f); xs_fclose(f); if (readSize != *bufSize) return -3; else return 0; } else { xs_fclose(f); return -4; } }
static char * read_win_text (VFSFile * file) { int64_t size = vfs_fsize (file); if (size < 1) return NULL; char * raw = malloc (size + 1); size = vfs_fread (raw, 1, size, file); raw[size] = 0; strip_char (raw, '\r'); char * text = str_to_utf8 (raw); free (raw); return text; }
FLAC__StreamDecoderLengthStatus length_callback(const FLAC__StreamDecoder *decoder, FLAC__uint64 *length, void *client_data) { callback_info *info = (callback_info*) client_data; if ((*length = vfs_fsize(info->fd)) == -1) { /* * Could not get the stream size. This is not necessarily an * error, maybe the stream has no fixed size (think streaming * audio) */ AUDDBG("Stream length is unknown.\n"); *length = 0; return FLAC__STREAM_DECODER_LENGTH_STATUS_UNSUPPORTED; } AUDDBG ("Stream length is %d bytes\n", (gint) * length); return FLAC__STREAM_DECODER_LENGTH_STATUS_OK; }
EXPORT void vfs_file_read_all (VFSFile * file, void * * bufp, int64_t * sizep) { char * buf = NULL; int64_t size = vfs_fsize (file); if (size >= 0) { size = MIN (size, SIZE_MAX - 1); buf = malloc (size + 1); size = vfs_fread (buf, 1, size, file); } else { size = 0; size_t bufsize = 4096; buf = malloc (bufsize); size_t readsize; while ((readsize = vfs_fread (buf + size, 1, bufsize - 1 - size, file))) { size += readsize; if (size == bufsize - 1) { if (bufsize > SIZE_MAX - 4096) break; bufsize += 4096; buf = realloc (buf, bufsize); } } } buf[size] = 0; // nul-terminate * bufp = buf; if (sizep) * sizep = size; }
gchar * load_text_file (const gchar * filename) { VFSFile * file; gint size; gchar * buffer; file = vfs_fopen (filename, "r"); if (file == NULL) return NULL; size = vfs_fsize (file); size = MAX (0, size); buffer = g_malloc (size + 1); size = vfs_fread (buffer, 1, size, file); size = MAX (0, size); buffer[size] = 0; vfs_fclose (file); return buffer; }
static int64_t probe_buffer_fsize (VFSFile * file) { return vfs_fsize (((ProbeBuffer *) vfs_get_handle (file))->file); }
Tuple *flac_probe_for_tuple(const char *filename, VFSFile *fd) { AUDDBG("Probe for tuple.\n"); Tuple *tuple = NULL; FLAC__Metadata_Iterator *iter; FLAC__Metadata_Chain *chain; FLAC__StreamMetadata *metadata = NULL; FLAC__Metadata_ChainStatus status; FLAC__StreamMetadata_VorbisComment_Entry *entry; char *key; char *value; tuple = tuple_new_from_filename(filename); tuple_set_str(tuple, FIELD_CODEC, NULL, "Free Lossless Audio Codec (FLAC)"); tuple_set_str(tuple, FIELD_QUALITY, NULL, _("lossless")); chain = FLAC__metadata_chain_new(); if (!FLAC__metadata_chain_read_with_callbacks(chain, fd, io_callbacks)) goto ERR; iter = FLAC__metadata_iterator_new(); FLAC__metadata_iterator_init(iter, chain); do { switch (FLAC__metadata_iterator_get_block_type(iter)) { case FLAC__METADATA_TYPE_VORBIS_COMMENT: if (FLAC__metadata_iterator_get_block_type(iter) == FLAC__METADATA_TYPE_VORBIS_COMMENT) { metadata = FLAC__metadata_iterator_get_block(iter); AUDDBG("Vorbis comment contains %d fields\n", metadata->data.vorbis_comment.num_comments); AUDDBG("Vendor string: %s\n", metadata->data.vorbis_comment.vendor_string.entry); entry = metadata->data.vorbis_comment.comments; for (int i = 0; i < metadata->data.vorbis_comment.num_comments; i++, entry++) { if (FLAC__metadata_object_vorbiscomment_entry_to_name_value_pair(*entry, &key, &value) == false) AUDDBG("Could not parse comment\n"); else { parse_comment(tuple, key, value); free(key); free(value); } } } break; case FLAC__METADATA_TYPE_STREAMINFO: metadata = FLAC__metadata_iterator_get_block(iter); /* Calculate the stream length (milliseconds) */ if (metadata->data.stream_info.sample_rate == 0) { FLACNG_ERROR("Invalid sample rate for stream!\n"); tuple_set_int(tuple, FIELD_LENGTH, NULL, -1); } else { tuple_set_int(tuple, FIELD_LENGTH, NULL, (metadata->data.stream_info.total_samples / metadata->data.stream_info.sample_rate) * 1000); AUDDBG("Stream length: %d seconds\n", tuple_get_int(tuple, FIELD_LENGTH, NULL)); } int64_t size = vfs_fsize(fd); if (size == -1 || metadata->data.stream_info.total_samples == 0) tuple_set_int(tuple, FIELD_BITRATE, NULL, 0); else { int bitrate = 8 * size * (int64_t) metadata->data.stream_info.sample_rate / metadata->data.stream_info.total_samples; tuple_set_int(tuple, FIELD_BITRATE, NULL, (bitrate + 500) / 1000); } break; default: ; } } while (FLAC__metadata_iterator_next(iter)); FLAC__metadata_iterator_delete(iter); FLAC__metadata_chain_delete(chain); return tuple; ERR: status = FLAC__metadata_chain_status(chain); FLAC__metadata_chain_delete(chain); FLACNG_ERROR("An error occured: %s\n", FLAC__Metadata_ChainStatusString[status]); return tuple; }
static bool_t read_header (VFSFile * handle, int * version, bool_t * syncsafe, int64_t * offset, int * header_size, int * data_size, int * footer_size) { ID3v2Header header, footer; if (vfs_fseek (handle, 0, SEEK_SET)) return FALSE; if (vfs_fread (& header, 1, sizeof (ID3v2Header), handle) != sizeof (ID3v2Header)) return FALSE; if (validate_header (& header, FALSE)) { * offset = 0; * version = header.version; * header_size = sizeof (ID3v2Header); * data_size = header.size; if (header.flags & ID3_HEADER_HAS_FOOTER) { if (vfs_fseek (handle, header.size, SEEK_CUR)) return FALSE; if (vfs_fread (& footer, 1, sizeof (ID3v2Header), handle) != sizeof (ID3v2Header)) return FALSE; if (! validate_header (& footer, TRUE)) return FALSE; * footer_size = sizeof (ID3v2Header); } else * footer_size = 0; } else { int64_t end = vfs_fsize (handle); if (end < 0) return FALSE; if (vfs_fseek (handle, end - sizeof (ID3v2Header), SEEK_SET)) return FALSE; if (vfs_fread (& footer, 1, sizeof (ID3v2Header), handle) != sizeof (ID3v2Header)) return FALSE; if (! validate_header (& footer, TRUE)) return FALSE; * offset = end - 2 * sizeof (ID3v2Header) - footer.size; * version = footer.version; * header_size = sizeof (ID3v2Header); * data_size = footer.size; * footer_size = sizeof (ID3v2Header); if (vfs_fseek (handle, * offset, SEEK_SET)) return FALSE; if (vfs_fread (& header, 1, sizeof (ID3v2Header), handle) != sizeof (ID3v2Header)) return FALSE; if (! validate_header (& header, FALSE)) return FALSE; } * syncsafe = (header.flags & ID3_HEADER_SYNCSAFE) ? TRUE : FALSE; if (header.flags & ID3_HEADER_HAS_EXTENDED_HEADER) { int extended_size = 0; if (header.version == 3) { if (! skip_extended_header_3 (handle, & extended_size)) return FALSE; } else if (header.version == 4) { if (! skip_extended_header_4 (handle, & extended_size)) return FALSE; } * header_size += extended_size; * data_size -= extended_size; } TAGDBG ("Offset = %d, header size = %d, data size = %d, footer size = " "%d.\n", (int) * offset, * header_size, * data_size, * footer_size); return TRUE; }
INIFile * open_ini_file (VFSFile * file) { GHashTable *ini_file = NULL; GHashTable *section = NULL; GString *section_name, *key_name, *value; gpointer section_hash, key_hash; gsize off = 0; gint64 filesize = vfs_fsize (file); if (filesize < 1) return NULL; gchar * buffer = g_malloc (filesize); filesize = vfs_fread (buffer, 1, filesize, file); section_name = g_string_new(""); key_name = g_string_new(NULL); value = g_string_new(NULL); ini_file = g_hash_table_new_full(NULL, NULL, NULL, close_ini_file_free_section); section = g_hash_table_new_full(NULL, NULL, NULL, close_ini_file_free_value); /* make a nameless section which should store all entries that are not * embedded in a section */ section_hash = GINT_TO_POINTER(g_string_hash(section_name)); g_hash_table_insert(ini_file, section_hash, section); while (off < filesize) { /* ignore the following characters */ if (buffer[off] == '\r' || buffer[off] == '\n' || buffer[off] == ' ' || buffer[off] == '\t') { if (buffer[off] == '\n') { g_string_free(key_name, TRUE); g_string_free(value, TRUE); key_name = g_string_new(NULL); value = g_string_new(NULL); } off++; continue; } /* if we encounter a possible section statement */ if (buffer[off] == '[') { g_string_free(section_name, TRUE); section_name = g_string_new(NULL); off++; if (off >= filesize) goto return_sequence; while (buffer[off] != ']') { /* if the section statement has not been closed before a * linebreak */ if (buffer[off] == '\n') break; g_string_append_c(section_name, buffer[off]); off++; if (off >= filesize) goto return_sequence; } if (buffer[off] == '\n') continue; if (buffer[off] == ']') { off++; if (off >= filesize) goto return_sequence; strip_lower_string(section_name); section_hash = GINT_TO_POINTER(g_string_hash(section_name)); /* if this section already exists, we don't make a new one, * but reuse the old one */ if (g_hash_table_lookup(ini_file, section_hash) != NULL) section = g_hash_table_lookup(ini_file, section_hash); else { section = g_hash_table_new_full(NULL, NULL, NULL, close_ini_file_free_value); g_hash_table_insert(ini_file, section_hash, section); } continue; } } if (buffer[off] == '=') { off++; if (off >= filesize) goto return_sequence; while (buffer[off] != '\n' && buffer[off] != '\r') { g_string_append_c(value, buffer[off]); off++; if (off >= filesize) break; } strip_lower_string(key_name); key_hash = GINT_TO_POINTER(g_string_hash(key_name)); strip_string(value); if (key_name->len > 0 && value->len > 0) g_hash_table_insert(section, key_hash, g_strdup(value->str)); } else { g_string_append_c(key_name, buffer[off]); off++; if (off >= filesize) goto return_sequence; } } return_sequence: g_string_free(section_name, TRUE); g_string_free(key_name, TRUE); g_string_free(value, TRUE); g_free(buffer); return ini_file; }
static size_t get_size_vfs(VFSSTREAMFILE *streamfile) { return vfs_fsize(streamfile->vfsFile); }
static gint64 probe_buffer_fsize (VFSFile * file) { return vfs_fsize (((ProbeBuffer *) file->handle)->file); }