static int Demux (demux_t *demux) { demux_sys_t *sys = demux->p_sys; /* Next track */ if (gme_track_ended (sys->emu)) { msg_Dbg (demux, "track %u ended", sys->track_id); if (++sys->track_id >= (unsigned)gme_track_count (sys->emu)) return 0; demux->info.i_update |= INPUT_UPDATE_TITLE; demux->info.i_title = sys->track_id; gme_start_track (sys->emu, sys->track_id); } block_t *block = block_Alloc (2 * 2 * SAMPLES); if (unlikely(block == NULL)) return 0; gme_err_t ret = gme_play (sys->emu, 2 * SAMPLES, (void *)block->p_buffer); if (ret != NULL) { block_Release (block); msg_Err (demux, "%s", ret); return 0; } block->i_pts = block->i_dts = VLC_TS_0 + date_Get (&sys->pts); es_out_Control (demux->out, ES_OUT_SET_PCR, block->i_pts); es_out_Send (demux->out, sys->es, block); date_Increment (&sys->pts, SAMPLES); return 1; }
JNIEXPORT jstring JNICALL Java_com_ssb_droidsound_plugins_GMEPlugin_N_1getStringInfo(JNIEnv *env, jobject obj, jlong song, jint what) { GMEInfo *info = (GMEInfo*)song; int track_count = gme_track_count(info->emu); switch(what) { case INFO_TITLE: return NewString(env, info->mainTitle); case INFO_SUBTUNE_TITLE: if(track_count > 1) { return NewString(env, info->lastTrack->song); } else { return 0; } case INFO_AUTHOR: return NewString(env, info->lastTrack->author); case INFO_COPYRIGHT: return NewString(env, info->lastTrack->copyright); case INFO_TYPE: return NewString(env, info->lastTrack->system); case INFO_GAME: return NewString(env, info->lastTrack->game); } return 0; }
Playlist::Entries GME::fetchTracks(const QString &url, bool &ok) { Playlist::Entries entries; if (open(url, true)) { const int tracks = gme_track_count(m_gme); for (int i = 0; i < tracks; ++i) { gme_info_t *info = NULL; if (!gme_track_info(m_gme, &info, i) && info) { Playlist::Entry entry; entry.url = GMEName + QString("://{%1}%2").arg(m_url).arg(i); entry.name = getTitle(info, i); entry.length = getLength(info); gme_free_info(info); entries.append(entry); } } if (entries.length() > 1) { for (int i = 0; i < entries.length(); ++i) entries[i].parent = 1; Playlist::Entry entry; entry.name = Functions::fileName(m_url, false); entry.url = m_url; entry.GID = 1; entries.prepend(entry); } } ok = !entries.isEmpty(); return entries; }
GmeDecoder::GmeDecoder(Data *data, const std::string &ext, int bufferSize) : Decoder(data, ext, bufferSize) , emu(0) , num_tracks(0) , cur_track(0) { void *d = data->getData(); int s = data->getSize(); if (gme_open_data(d, s, &emu, sampleRate) != 0) throw love::Exception("Could not open game music file"); num_tracks = gme_track_count(emu); try { if (num_tracks <= 0) throw love::Exception("Game music file has no tracks"); if (gme_start_track(emu, cur_track) != 0) throw love::Exception("Could not start game music playback"); } catch (love::Exception &) { gme_delete(emu); throw; } }
jlong setUp(Music_Emu *emu) { gme_err_t err; gme_info_t* track0; gme_info_t* track1; err = gme_track_info(emu, &track0, 0); int track_count = gme_track_count(emu); //info->gme_track_count(); __android_log_print(ANDROID_LOG_VERBOSE, "GMEPlugin", "(RC %s) -> SONG '%s' GAME '%s' LEN '%d' COUNT '%d'", err, track0->song, track0->game, track0->length, track_count); if(!err) { GMEInfo *info = new GMEInfo(); if(!strlen(track0->song)) { bool nameOk = false; // If name is all upper case it is most likely a rom name for(int i=0; i<strlen(track0->game); i++) { char c = track0->game[i]; if(isalpha(c) && !isupper(c)) { nameOk = true; } } if(nameOk) { strcpy(info->mainTitle, track0->game); } else { info->mainTitle[0] = 0; } } else { strcpy(info->mainTitle, track0->song); if(track_count > 1) { err = gme_track_info(emu, &track1, 1); __android_log_print(ANDROID_LOG_VERBOSE, "GMEPlugin", "'%s' vs '%s'", track0->song, track1->song); if(!err && strcmp(track0->song, track1->song) != 0) { // We have more than one subsong, and their names differ strcpy(info->mainTitle, track0->game); } } } info->started = false; info->emu = emu; info->currentSong = 0; //info->emu->ignore_silence(true); info->lastTrack = track0; info->trackCount = track_count; return (jlong)info; } return 0; }
jint Java_de_illogical_modo_GmeDecoder_gmeTracks(JNIEnv* env, jclass clazz) { if (emu == NULL) { return -1; } return gme_track_count(emu); }
QString GME::getTitle(gme_info_t *info, int track) const { const QString title = info->game; const QString author = info->author; QString ret; if (!author.isEmpty() && !title.isEmpty()) ret = author + " - " + title; else ret = title; if (gme_track_count(m_gme) > 1) return tr("Track") + QString(" %1%2").arg(track + 1).arg(ret.isEmpty() ? QString() : (" - " + ret)); return ret; }
boolean I_SetSongTrack(INT32 track) { if (track != current_track) // If the track's already playing, then why bother? { FMOD_RESULT e; #ifdef HAVE_LIBGME // If the specified track is within the number of tracks playing, then change it if (gme) { if (track >= 0 && track < gme_track_count(gme)) { gme_err_t gme_e = gme_start_track(gme,track); if (gme_e == NULL) { current_track = track; return true; } else CONS_Alert(CONS_ERROR, "Encountered GME error: %s\n", gme_e); } return false; } #endif // HAVE_LIBGME // Try to set it via FMOD e = FMOD_Channel_SetPosition(music_channel, (UINT32)track, FMOD_TIMEUNIT_MODORDER); if (e == FMOD_OK) // We good { current_track = track; return true; } else if (e == FMOD_ERR_UNSUPPORTED // Only music modules, numbnuts! || e == FMOD_ERR_INVALID_POSITION) // Out-of-bounds! return false; else // Congrats, you horribly broke it somehow { FMR_MUSIC(e); return false; } } return false; }
static int load_metadata(AVFormatContext *s) { GMEContext *gme = s->priv_data; gme_info_t *info = gme->info; char buf[30]; add_meta(s, "system", info->system); add_meta(s, "game", info->game); add_meta(s, "song", info->song); add_meta(s, "author", info->author); add_meta(s, "copyright", info->copyright); add_meta(s, "comment", info->comment); add_meta(s, "dumper", info->dumper); snprintf(buf, sizeof(buf), "%d", (int)gme_track_count(gme->music_emu)); add_meta(s, "tracks", buf); return 0; }
static int gme_probe(metadata_t *md, const char *url, fa_handle_t *fh) { uint8_t b4[4], *buf; gme_err_t err; Music_Emu *emu; gme_info_t *info; int tracks; size_t size; const char *type; if(fa_read(fh, b4, 4) != 4) return 0; type = gme_identify_header(b4); if(*type == 0) return 0; size = fa_fsize(fh); if(size == -1) return -1; buf = malloc(size); fa_seek(fh, 0, SEEK_SET); if(fa_read(fh, buf, size) != size) { free(buf); return 0; } err = gme_open_data(buf, size, &emu, gme_info_only); free(buf); if(err != NULL) return 0; err = gme_track_info(emu, &info, 0); if(err != NULL) { gme_delete(emu); return 0; } tracks = gme_track_count(emu); #if 0 printf("tracks : %d\n", tracks); printf("system : %s\n", info->system); printf("game : %s\n", info->game); printf("song : %s\n", info->song); printf("author : %s\n", info->author); printf("copyright: %s\n", info->copyright); printf("comment : %s\n", info->comment); printf("dumper : %s\n", info->dumper); #endif if(tracks == 1) { md->md_title = info->song[0] ? rstr_alloc(info->song) : NULL; md->md_album = info->game[0] ? rstr_alloc(info->game) : NULL; md->md_artist = info->author[0] ? rstr_alloc(info->author) : NULL; md->md_duration = info->play_length / 1000.0; md->md_contenttype = CONTENT_AUDIO; } else { md->md_title = info->game[0] ? rstr_alloc(info->game) : NULL; md->md_artist = info->author[0] ? rstr_alloc(info->author) : NULL; md->md_contenttype = CONTENT_ALBUM; metdata_set_redirect(md, "gmefile://%s/", url); } gme_free_info(info); gme_delete(emu); return 1; }
struct MUSIC_GME *GME_LoadSongRW(SDL_RWops *src, int trackNum) { if(src != NULL) { void *bytes=0; long spcsize; Sint64 length=0; length = SDL_RWseek(src, 0, RW_SEEK_END); if (length < 0) { Mix_SetError("GAME-EMU: wrong file\n"); return NULL; } SDL_RWseek(src, 0, RW_SEEK_SET); bytes = malloc(length); long bytes_l; unsigned char byte[1]; spcsize=0; while( (bytes_l=SDL_RWread(src, &byte, sizeof(unsigned char), 1))!=0) { ((unsigned char*)bytes)[spcsize] = byte[0]; spcsize++; } if (spcsize == 0) { Mix_SetError("GAME-EMU: wrong file\n"); return NULL; } Music_Emu* game_emu; char *err = (char*)gme_open_data( bytes, spcsize, &game_emu, gme_t_sample_rate ); //spc_load_spc( snes_spc, bytes, spcsize ); free(bytes); if(err!=0) { Mix_SetError("GAME-EMU: %s", err); return NULL; } if((trackNum<0)||(trackNum >= gme_track_count(game_emu))) trackNum = gme_track_count(game_emu)-1; err = (char*)gme_start_track( game_emu, trackNum ); if(err!=0) { Mix_SetError("GAME-EMU: %s", err); return NULL; } struct MUSIC_GME *spcSpec = (struct MUSIC_GME*)malloc(sizeof(struct MUSIC_GME)); spcSpec->game_emu=game_emu; spcSpec->playing=0; spcSpec->gme_t_sample_rate=mixer.freq; spcSpec->volume=MIX_MAX_VOLUME; spcSpec->mus_title=NULL; spcSpec->mus_artist=NULL; spcSpec->mus_album=NULL; spcSpec->mus_copyright=NULL; gme_info_t *musInfo; err = (char*)gme_track_info(spcSpec->game_emu, &musInfo, trackNum); if(err!=0) { gme_delete(spcSpec->game_emu); free(spcSpec); Mix_SetError("GAME-EMU: %s", err); return NULL; } spcSpec->mus_title = (char *)SDL_malloc(sizeof(char)*strlen(musInfo->song)+1); strcpy(spcSpec->mus_title, musInfo->song); spcSpec->mus_artist = (char *)SDL_malloc(sizeof(char)*strlen(musInfo->author)+1); strcpy(spcSpec->mus_artist, musInfo->author); spcSpec->mus_album = (char *)SDL_malloc(sizeof(char)*strlen(musInfo->game)+1); strcpy(spcSpec->mus_album, musInfo->game); spcSpec->mus_copyright = (char *)SDL_malloc(sizeof(char)*strlen(musInfo->copyright)+1); strcpy(spcSpec->mus_copyright, musInfo->copyright); gme_free_info( musInfo ); SDL_BuildAudioCVT(&spcSpec->cvt, AUDIO_S16, 2, mixer.freq, mixer.format, mixer.channels, mixer.freq); return spcSpec; } return NULL; }
static gboolean xmms_gme_init (xmms_xform_t *xform) { xmms_gme_data_t *data; gme_err_t init_error; GString *file_contents; /* The raw data from the file. */ gme_info_t *metadata = NULL; xmms_config_property_t *val; int loops; int maxlength; const char *subtune_str; int subtune = 0; long fadelen = -1; int samplerate; double stereodepth; g_return_val_if_fail (xform, FALSE); data = g_new0 (xmms_gme_data_t, 1); xmms_xform_private_data_set (xform, data); val = xmms_xform_config_lookup (xform, "samplerate"); samplerate = xmms_config_property_get_int (val); if (samplerate < 1) samplerate = GME_DEFAULT_SAMPLE_RATE; data->samplerate = samplerate; xmms_xform_outdata_type_add (xform, XMMS_STREAM_TYPE_MIMETYPE, "audio/pcm", /* PCM samples */ XMMS_STREAM_TYPE_FMT_FORMAT, XMMS_SAMPLE_FORMAT_S16, /* 16-bit signed */ XMMS_STREAM_TYPE_FMT_CHANNELS, 2, /* stereo */ XMMS_STREAM_TYPE_FMT_SAMPLERATE, samplerate, XMMS_STREAM_TYPE_END); file_contents = g_string_new (""); for (;;) { xmms_error_t error; gchar buf[4096]; gint ret; ret = xmms_xform_read (xform, buf, sizeof (buf), &error); if (ret == -1) { XMMS_DBG ("Error reading emulated music data"); return FALSE; } if (ret == 0) { break; } g_string_append_len (file_contents, buf, ret); } init_error = gme_open_data (file_contents->str, file_contents->len, &data->emu, samplerate); g_string_free (file_contents, TRUE); if (init_error) { XMMS_DBG ("gme_open_data returned an error: %s", init_error); return FALSE; } if (xmms_xform_metadata_get_str (xform, "subtune", &subtune_str)) { subtune = strtol (subtune_str, NULL, 10); XMMS_DBG ("Setting subtune to %d", subtune); if ((subtune < 0 || subtune > gme_track_count (data->emu))) { XMMS_DBG ("Invalid subtune index"); return FALSE; } } else { xmms_xform_metadata_set_int (xform, XMMS_MEDIALIB_ENTRY_PROPERTY_SUBTUNES, gme_track_count (data->emu)); } /* * Get metadata here */ init_error = gme_track_info (data->emu, &metadata, subtune); if (init_error) { XMMS_DBG ("Couldn't get GME track info: %s", init_error); init_error = ""; } else { xmms_xform_metadata_set_str (xform, XMMS_MEDIALIB_ENTRY_PROPERTY_TITLE, metadata->song); xmms_xform_metadata_set_str (xform, XMMS_MEDIALIB_ENTRY_PROPERTY_ARTIST, metadata->author); xmms_xform_metadata_set_str (xform, XMMS_MEDIALIB_ENTRY_PROPERTY_ALBUM, metadata->game); xmms_xform_metadata_set_str (xform, XMMS_MEDIALIB_ENTRY_PROPERTY_COMMENT, metadata->comment); xmms_xform_metadata_set_str (xform, XMMS_MEDIALIB_ENTRY_PROPERTY_YEAR, metadata->copyright); xmms_xform_metadata_set_str (xform, XMMS_MEDIALIB_ENTRY_PROPERTY_GENRE, metadata->system); /* I mapped genre to the system type */ val = xmms_xform_config_lookup (xform, "loops"); loops = xmms_config_property_get_int (val); XMMS_DBG ("intro_length = %d, loops = %d, loop_length = %d", metadata->intro_length, loops, metadata->loop_length); if (metadata->intro_length > 0) { if ((loops > 0) && (metadata->loop_length > 0)) { fadelen = metadata->intro_length + loops * metadata->loop_length; XMMS_DBG ("fadelen now = %ld", fadelen); } else { fadelen = metadata->length; XMMS_DBG ("fadelen now = %ld", fadelen); } } } val = xmms_xform_config_lookup (xform, "maxlength"); maxlength = xmms_config_property_get_int (val); XMMS_DBG ("maxlength = %d seconds", maxlength); if (maxlength > 0 && (fadelen < 0 || (maxlength * 1000L < fadelen))) { fadelen = maxlength * 1000L; XMMS_DBG ("fadelen now = %ld", fadelen); } XMMS_DBG ("gme.fadelen = %ld", fadelen); val = xmms_xform_config_lookup (xform, "stereodepth"); stereodepth = xmms_config_property_get_float (val); if (stereodepth >= 0.0 && stereodepth <= 1.0) { XMMS_DBG ("Setting stereo depth to %f.", stereodepth); gme_set_stereo_depth (data->emu, stereodepth); } else { XMMS_DBG ("gme.stereodepth = %f out of range 0.0 - 1.0; not setting.", stereodepth); } init_error = gme_start_track (data->emu, subtune); if (init_error) { XMMS_DBG ("gme_start_track returned an error: %s", init_error); gme_free_info (metadata); return FALSE; } if (fadelen > 0) { XMMS_DBG ("Setting song length and fade length..."); xmms_xform_metadata_set_int (xform, XMMS_MEDIALIB_ENTRY_PROPERTY_DURATION, fadelen); gme_set_fade (data->emu, fadelen); } gme_free_info (metadata); return TRUE; }
static DB_playItem_t * cgme_insert (ddb_playlist_t *plt, DB_playItem_t *after, const char *fname) { Music_Emu *emu; trace ("gme_open_file %s\n", fname); gme_err_t res = "gme uninitialized"; const char *ext = strrchr (fname, '.'); char *buffer; int sz; if (!read_gzfile (fname, &buffer, &sz)) { res = gme_open_data (fname, buffer, sz, &emu, gme_info_only); free (buffer); } if (res) { DB_FILE *f = deadbeef->fopen (fname); if (!f) { return NULL; } int64_t sz = deadbeef->fgetlength (f); if (sz <= 0) { deadbeef->fclose (f); return NULL; } char *buf = malloc (sz); if (!buf) { deadbeef->fclose (f); return NULL; } int64_t rb = deadbeef->fread (buf, 1, sz, f); deadbeef->fclose(f); if (rb != sz) { free (buf); return NULL; } res = gme_open_data (fname, buf, sz, &emu, gme_info_only); free (buf); } if (!res) { int cnt = gme_track_count (emu); trace ("track cnt %d\n", cnt); for (int i = 0; i < cnt; i++) { #ifdef GME_VERSION_055 gme_info_t *inf; const char *ret = gme_track_info (emu, &inf, i); #else track_info_t _inf; const char *ret = gme_track_info (emu, &inf, i); track_info_t *inf = &_inf; #endif if (!ret) { DB_playItem_t *it = deadbeef->pl_item_alloc_init (fname, plugin.plugin.id); char str[1024]; if (inf->song[0]) { snprintf (str, sizeof(str), "%d %s - %s", i, inf->game, inf->song); } else { snprintf (str, sizeof(str), "%d %s - ?", i, inf->game); } trace ("track subtune %d %s, length=%d\n", i, str, inf->length); deadbeef->pl_set_meta_int (it, ":TRACKNUM", i); // add metadata cgme_add_meta (it, "system", inf->system); cgme_add_meta (it, "album", inf->game); int tl = sizeof (inf->song); int n; for (n = 0; i < tl && inf->song[n] && inf->song[n] == ' '; n++); if (n == tl || !inf->song[n]) { deadbeef->pl_add_meta (it, "title", NULL); } else { cgme_add_meta (it, "title", inf->song); } cgme_add_meta (it, "artist", inf->author); cgme_add_meta (it, "copyright", inf->copyright); cgme_add_meta (it, "comment", inf->comment); cgme_add_meta (it, "dumper", inf->dumper); char trk[10]; snprintf (trk, 10, "%d", i+1); cgme_add_meta (it, "track", trk); snprintf (str, sizeof(str), "%d", inf->length); deadbeef->pl_add_meta (it, ":GME_LENGTH", str); snprintf (str, sizeof(str), "%d", inf->intro_length); deadbeef->pl_add_meta (it, ":GME_INTRO_LENGTH", str); snprintf (str, sizeof(str), "%d", inf->loop_length); deadbeef->pl_add_meta (it, ":GME_LOOP_LENGTH", str); if (inf->length == -1 || inf->length == 0) { float songlength; if (inf->loop_length > 0 && conf_loopcount > 0) { songlength = inf->intro_length / 1000.f; if (songlength < 0) { songlength = 0; } songlength += (inf->loop_length * conf_loopcount) / 1000.f; } else { songlength = deadbeef->conf_get_float ("gme.songlength", 3) * 60.f; } deadbeef->plt_set_item_duration (plt, it, songlength); } else { deadbeef->plt_set_item_duration (plt, it, (float)inf->length/1000.f); } const char *ext = fname + strlen (fname) - 1; while (ext >= fname && *ext != '.') { ext--; } if (*ext == '.') { ext++; for (int i = 0; plugin.exts[i]; i++) { if (!strcasecmp (ext, plugin.exts[i])) { deadbeef->pl_add_meta (it, ":FILETYPE", plugin.exts[i]); break; } } } if (cnt > 1) { deadbeef->pl_set_item_flags (it, deadbeef->pl_get_item_flags (it) | DDB_IS_SUBTRACK); } after = deadbeef->plt_insert_item (plt, after, it); deadbeef->pl_item_unref (it); } else { trace ("gme error: %s\n", ret); } } if (emu) { gme_delete (emu); } } else { trace ("gme_open_file/data failed with error %s\n", res); } return after; }
int bmx_gme_track_count(MaxMusicEmu * emu) { return gme_track_count(emu->emu); }
bool GME::open(const QString &_url, bool tracksOnly) { QString prefix, url, param; const bool hasPluginPrefix = Functions::splitPrefixAndUrlIfHasPluginPrefix(_url, &prefix, &url, ¶m); if (tracksOnly == hasPluginPrefix) return false; int track = 0; if (!hasPluginPrefix) { if (url.startsWith(GMEName "://")) return false; url = _url; } else { if (prefix != GMEName) return false; bool ok; track = param.toInt(&ok); if (track < 0 || !ok) return false; } if (Reader::create(url, m_reader)) { const QByteArray data = m_reader->read(m_reader->size()); m_reader.clear(); gme_open_data(data.data(), data.size(), &m_gme, m_srate); if (!m_gme) return false; if (!hasPluginPrefix) { m_aborted = true; m_url = url; return true; } if (track >= gme_track_count(m_gme)) return false; gme_info_t *info = NULL; if (!gme_track_info(m_gme, &info, track) && info) { m_title = getTitle(info, track); m_length = getLength(info); if (*info->game) m_tags << qMakePair(QString::number(QMPLAY2_TAG_TITLE), QString(info->game)); if (*info->author) m_tags << qMakePair(QString::number(QMPLAY2_TAG_ARTIST), QString(info->author)); if (*info->system) m_tags << qMakePair(tr("System"), QString(info->system)); if (*info->copyright) m_tags << qMakePair(tr("Copyright"), QString(info->copyright)); if (*info->comment) m_tags << qMakePair(tr("Comment"), QString(info->comment)); gme_free_info(info); } QString voices; const int numVoices = gme_voice_count(m_gme); for (int i = 0; i < numVoices; ++i) { voices += gme_voice_name(m_gme, i); voices += ", "; } voices.chop(2); m_tags << qMakePair(tr("Voices"), voices); m_tags << qMakePair(tr("Track"), QString::number(track + 1)); streams_info += new StreamInfo(m_srate, 2); gme_set_stereo_depth(m_gme, 0.5); return !gme_start_track(m_gme, track); } return false; }
static int Control (demux_t *demux, int query, va_list args) { demux_sys_t *sys = demux->p_sys; switch (query) { case DEMUX_CAN_SEEK: *va_arg (args, bool *) = true; return VLC_SUCCESS; case DEMUX_GET_POSITION: { double *pos = va_arg (args, double *); if (unlikely(sys->track_id >= sys->titlec) || (sys->titlev[sys->track_id]->i_length == 0)) *pos = 0.; else { int offset = gme_tell (sys->emu); *pos = (double)offset / (double)(sys->titlev[sys->track_id]->i_length / 1000); } return VLC_SUCCESS; } case DEMUX_SET_POSITION: { double pos = va_arg (args, double); if (unlikely(sys->track_id >= sys->titlec) || (sys->titlev[sys->track_id]->i_length == 0)) break; int seek = (sys->titlev[sys->track_id]->i_length / 1000) * pos; if (gme_seek (sys->emu, seek)) break; return VLC_SUCCESS; } case DEMUX_GET_LENGTH: { int64_t *v = va_arg (args, int64_t *); if (unlikely(sys->track_id >= sys->titlec) || (sys->titlev[sys->track_id]->i_length == 0)) break; *v = sys->titlev[sys->track_id]->i_length; return VLC_SUCCESS; } case DEMUX_GET_TIME: { int64_t *v = va_arg (args, int64_t *); *v = gme_tell (sys->emu) * INT64_C(1000); return VLC_SUCCESS; } case DEMUX_SET_TIME: { int64_t v = va_arg (args, int64_t) / 1000; if (v > INT_MAX || gme_seek (sys->emu, v)) break; return VLC_SUCCESS; } case DEMUX_GET_TITLE_INFO: { input_title_t ***titlev = va_arg (args, input_title_t ***); int *titlec = va_arg (args, int *); *(va_arg (args, int *)) = 0; /* Title offset */ *(va_arg (args, int *)) = 0; /* Chapter offset */ unsigned n = sys->titlec; *titlev = malloc (sizeof (**titlev) * n); if (unlikely(*titlev == NULL)) n = 0; *titlec = n; for (unsigned i = 0; i < n; i++) (*titlev)[i] = vlc_input_title_Duplicate (sys->titlev[i]); return VLC_SUCCESS; } case DEMUX_SET_TITLE: { int track_id = va_arg (args, int); if (track_id >= gme_track_count (sys->emu)) break; gme_start_track (sys->emu, track_id); demux->info.i_update |= INPUT_UPDATE_TITLE; demux->info.i_title = track_id; sys->track_id = track_id; return VLC_SUCCESS; } } return VLC_EGENERIC; }
static int Open (vlc_object_t *obj) { demux_t *demux = (demux_t *)obj; int64_t size = stream_Size (demux->s); if (size > LONG_MAX /* too big for GME */) return VLC_EGENERIC; /* Auto detection */ const uint8_t *peek; if (stream_Peek (demux->s, &peek, 4) < 4) return VLC_EGENERIC; const char *type = gme_identify_header (peek); if (!*type) return VLC_EGENERIC; msg_Dbg (obj, "detected file type %s", type); block_t *data = NULL; if (size <= 0) { data = stream_Block (demux->s, 1 << 24); if (data == NULL) return VLC_EGENERIC; } /* Initialization */ demux_sys_t *sys = malloc (sizeof (*sys)); if (unlikely(sys == NULL)) return VLC_ENOMEM; sys->emu = gme_new_emu (gme_identify_extension (type), RATE); if (sys->emu == NULL) { free (sys); return VLC_ENOMEM; } if (data) { gme_load_custom (sys->emu, ReaderBlock, data->i_buffer, data); block_Release(data); } else { gme_load_custom (sys->emu, ReaderStream, size, demux->s); } gme_start_track (sys->emu, sys->track_id = 0); es_format_t fmt; es_format_Init (&fmt, AUDIO_ES, VLC_CODEC_S16N); fmt.audio.i_rate = RATE; fmt.audio.i_bytes_per_frame = 4; fmt.audio.i_frame_length = 4; fmt.audio.i_channels = 2; fmt.audio.i_blockalign = 4; fmt.audio.i_bitspersample = 16; fmt.i_bitrate = RATE * 4; sys->es = es_out_Add (demux->out, &fmt); date_Init (&sys->pts, RATE, 1); date_Set (&sys->pts, 0); /* Titles */ unsigned n = gme_track_count (sys->emu); sys->titlev = malloc (n * sizeof (*sys->titlev)); if (unlikely(sys->titlev == NULL)) n = 0; sys->titlec = n; for (unsigned i = 0; i < n; i++) { input_title_t *title = vlc_input_title_New (); sys->titlev[i] = title; if (unlikely(title == NULL)) continue; gme_info_t *infos; if (gme_track_info (sys->emu, &infos, i)) continue; msg_Dbg (obj, "track %u: %s %d ms", i, infos->song, infos->length); if (infos->length != -1) title->i_length = infos->length * INT64_C(1000); if (infos->song[0]) title->psz_name = strdup (infos->song); gme_free_info (infos); } /* Callbacks */ demux->pf_demux = Demux; demux->pf_control = Control; demux->p_sys = sys; return VLC_SUCCESS; }
static int gmefile_scandir(fa_dir_t *fd, const char *url, char *errbuf, size_t errlen) { char *p, *fpath = mystrdupa(url); char name[32]; char turl[URL_MAX]; int tracks, i; fa_dir_entry_t *fde; const char *title; Music_Emu *emu; gme_info_t *info; gme_err_t err; if((p = strrchr(fpath, '/')) == NULL) { snprintf(errbuf, errlen, "Invalid filename"); return -1; } *p = 0; buf_t *b; if((b = fa_load(fpath, NULL, errbuf, errlen, NULL, 0, NULL, NULL)) == NULL) return -1; err = gme_open_data(b->b_ptr, b->b_size, &emu, gme_info_only); buf_release(b); if(err != NULL) return 0; tracks = gme_track_count(emu); for(i = 0; i < tracks; i++) { snprintf(turl, sizeof(turl), "gmeplayer:%s/%d", fpath, i + 1); err = gme_track_info(emu, &info, i); if(err == NULL && info->song[0]) { title = info->song; } else { snprintf(name, sizeof(name), "Track %02d", i + 1); title = name; } fde = fa_dir_add(fd, turl, title, CONTENT_AUDIO); fde->fde_probestatus = FDE_PROBE_DEEP; fde->fde_metadata = prop_create_root("metadata"); prop_set_string(prop_create(fde->fde_metadata, "title"), title); if(err == NULL) { if(info->game[0]) prop_set_string(prop_create(fde->fde_metadata, "album"), info->game); if(info->author[0]) prop_set_string(prop_create(fde->fde_metadata, "artist"), info->author); prop_set_float(prop_create(fde->fde_metadata, "duration"), info->play_length / 1000.0); gme_free_info(info); } } gme_delete(emu); return 0; }
int Music_Player::track_count() const { return emu_ ? gme_track_count( emu_ ) : false; }