diff -Nur orig/CMakeLists.txt new/CMakeLists.txt --- orig/CMakeLists.txt 2011-03-26 19:43:04.693948673 +0100 +++ new/CMakeLists.txt 2011-03-26 19:42:48.293020823 +0100 @@ -1,6 +1,8 @@ # CMake project definition file. project(libgme) +include (CheckCXXCompilerFlag) + set(GME_VERSION 0.5.5 CACHE INTERNAL "libgme Version") # 2.6+ always assumes FATAL_ERROR, but 2.4 and below don't. @@ -54,6 +56,33 @@ SET(USE_GME_NSF 1 CACHE BOOL "Enable NES NSF music emulation" FORCE) endif() +# Check for GCC "visibility" support. +if (CMAKE_COMPILER_IS_GNUCXX) + check_cxx_compiler_flag (-fvisibility=hidden __LIBGME_TEST_VISIBILITY) + set (ENABLE_VISIBILITY OFF) + if (__LIBGME_TEST_VISIBILITY) + # get the gcc version + exec_program(${CMAKE_CXX_COMPILER} ARGS --version OUTPUT_VARIABLE _gcc_version_info) + string (REGEX MATCH "[3-9]\\.[0-9]\\.[0-9]" _gcc_version "${_gcc_version_info}") + + # gcc <4.1 had poor support for symbol visibility + if ((${_gcc_version} VERSION_GREATER "4.1") OR (${_gcc_version} VERSION_EQUAL "4.1")) + set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fvisibility=hidden") + set (ENABLE_VISIBILITY ON) + add_definitions (-DLIBGME_VISIBILITY) + + # GCC >= 4.2 also correctly supports making inline members have hidden + # visibility by default. + if ((${_gcc_version} VERSION_GREATER "4.2") OR (${_gcc_version} VERSION_EQUAL "4.2")) + set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fvisibility-inlines-hidden") + endif() + endif() + endif() # test visibility +endif (CMAKE_COMPILER_IS_GNUCXX) + +# Cache this result +set( LIBGME_HAVE_GCC_VISIBILITY ${ENABLE_VISIBILITY} CACHE BOOL "GCC support for hidden visibility") + # Shared library defined here add_subdirectory(gme) diff -Nur orig/gme/blargg_source.h new/gme/blargg_source.h --- orig/gme/blargg_source.h 2009-06-24 04:21:29.000000000 +0200 +++ new/gme/blargg_source.h 2011-03-26 19:42:48.292020827 +0100 @@ -66,6 +66,17 @@ #define byte byte_ typedef unsigned char byte; +// Setup compiler defines useful for exporting required public API symbols in gme.cpp +#ifndef BLARGG_EXPORT + #if defined (_WIN32) && defined(BLARGG_BUILD_DLL) + #define BLARGG_EXPORT __declspec(dllexport) + #elif defined (LIBGME_VISIBILITY) + #define BLARGG_EXPORT __attribute__((visibility ("default"))) + #else + #define BLARGG_EXPORT + #endif +#endif + // deprecated #define BLARGG_CHECK_ALLOC CHECK_ALLOC #define BLARGG_RETURN_ERR RETURN_ERR diff -Nur orig/gme/gme.cpp new/gme/gme.cpp --- orig/gme/gme.cpp 2009-07-27 06:14:46.000000000 +0200 +++ new/gme/gme.cpp 2011-03-26 19:42:48.291020831 +0100 @@ -22,7 +22,7 @@ #include "blargg_source.h" -gme_type_t const* gme_type_list() +BLARGG_EXPORT gme_type_t const* gme_type_list() { static gme_type_t const gme_type_list_ [] = { #ifdef USE_GME_AY @@ -61,7 +61,7 @@ return gme_type_list_; } -const char* gme_identify_header( void const* header ) +BLARGG_EXPORT const char* gme_identify_header( void const* header ) { switch ( get_be32( header ) ) { @@ -90,7 +90,7 @@ *out = 0; // extension too long } -gme_type_t gme_identify_extension( const char* extension_ ) +BLARGG_EXPORT gme_type_t gme_identify_extension( const char* extension_ ) { char const* end = strrchr( extension_, '.' ); if ( end ) @@ -105,7 +105,7 @@ return 0; } -gme_err_t gme_identify_file( const char* path, gme_type_t* type_out ) +BLARGG_EXPORT gme_err_t gme_identify_file( const char* path, gme_type_t* type_out ) { *type_out = gme_identify_extension( path ); // TODO: don't examine header if file has extension? @@ -120,7 +120,7 @@ return 0; } -gme_err_t gme_open_data( void const* data, long size, Music_Emu** out, int sample_rate ) +BLARGG_EXPORT gme_err_t gme_open_data( void const* data, long size, Music_Emu** out, int sample_rate ) { require( (data || !size) && out ); *out = 0; @@ -144,7 +144,7 @@ return err; } -gme_err_t gme_open_file( const char* path, Music_Emu** out, int sample_rate ) +BLARGG_EXPORT gme_err_t gme_open_file( const char* path, Music_Emu** out, int sample_rate ) { require( path && out ); *out = 0; @@ -181,7 +181,7 @@ return err; } -Music_Emu* gme_new_emu( gme_type_t type, int rate ) +BLARGG_EXPORT Music_Emu* gme_new_emu( gme_type_t type, int rate ) { if ( type ) { @@ -214,27 +214,27 @@ return 0; } -gme_err_t gme_load_file( Music_Emu* me, const char* path ) { return me->load_file( path ); } +BLARGG_EXPORT gme_err_t gme_load_file( Music_Emu* me, const char* path ) { return me->load_file( path ); } -gme_err_t gme_load_data( Music_Emu* me, void const* data, long size ) +BLARGG_EXPORT gme_err_t gme_load_data( Music_Emu* me, void const* data, long size ) { Mem_File_Reader in( data, size ); return me->load( in ); } -gme_err_t gme_load_custom( Music_Emu* me, gme_reader_t func, long size, void* data ) +BLARGG_EXPORT gme_err_t gme_load_custom( Music_Emu* me, gme_reader_t func, long size, void* data ) { Callback_Reader in( func, size, data ); return me->load( in ); } -void gme_delete( Music_Emu* me ) { delete me; } +BLARGG_EXPORT void gme_delete( Music_Emu* me ) { delete me; } -gme_type_t gme_type( Music_Emu const* me ) { return me->type(); } +BLARGG_EXPORT gme_type_t gme_type( Music_Emu const* me ) { return me->type(); } -const char* gme_warning( Music_Emu* me ) { return me->warning(); } +BLARGG_EXPORT const char* gme_warning( Music_Emu* me ) { return me->warning(); } -int gme_track_count( Music_Emu const* me ) { return me->track_count(); } +BLARGG_EXPORT int gme_track_count( Music_Emu const* me ) { return me->track_count(); } struct gme_info_t_ : gme_info_t { @@ -243,7 +243,7 @@ BLARGG_DISABLE_NOTHROW }; -gme_err_t gme_track_info( Music_Emu const* me, gme_info_t** out, int track ) +BLARGG_EXPORT gme_err_t gme_track_info( Music_Emu const* me, gme_info_t** out, int track ) { *out = NULL; @@ -309,12 +309,12 @@ return 0; } -void gme_free_info( gme_info_t* info ) +BLARGG_EXPORT void gme_free_info( gme_info_t* info ) { delete STATIC_CAST(gme_info_t_*,info); } -void gme_set_stereo_depth( Music_Emu* me, double depth ) +BLARGG_EXPORT void gme_set_stereo_depth( Music_Emu* me, double depth ) { #if !GME_DISABLE_STEREO_DEPTH if ( me->effects_buffer ) @@ -322,23 +322,25 @@ #endif } -void* gme_user_data ( Music_Emu const* me ) { return me->user_data(); } -void gme_set_user_data ( Music_Emu* me, void* new_user_data ) { me->set_user_data( new_user_data ); } -void gme_set_user_cleanup(Music_Emu* me, gme_user_cleanup_t func ) { me->set_user_cleanup( func ); } - -gme_err_t gme_start_track ( Music_Emu* me, int index ) { return me->start_track( index ); } -gme_err_t gme_play ( Music_Emu* me, int n, short* p ) { return me->play( n, p ); } -void gme_set_fade ( Music_Emu* me, int start_msec ) { me->set_fade( start_msec ); } -int gme_track_ended ( Music_Emu const* me ) { return me->track_ended(); } -int gme_tell ( Music_Emu const* me ) { return me->tell(); } -gme_err_t gme_seek ( Music_Emu* me, int msec ) { return me->seek( msec ); } -int gme_voice_count ( Music_Emu const* me ) { return me->voice_count(); } -void gme_ignore_silence ( Music_Emu* me, int disable ) { me->ignore_silence( disable != 0 ); } -void gme_set_tempo ( Music_Emu* me, double t ) { me->set_tempo( t ); } -void gme_mute_voice ( Music_Emu* me, int index, int mute ) { me->mute_voice( index, mute != 0 ); } -void gme_mute_voices ( Music_Emu* me, int mask ) { me->mute_voices( mask ); } +BLARGG_EXPORT void* gme_user_data ( Music_Emu const* me ) { return me->user_data(); } +BLARGG_EXPORT void gme_set_user_data ( Music_Emu* me, void* new_user_data ) { me->set_user_data( new_user_data ); } +BLARGG_EXPORT void gme_set_user_cleanup(Music_Emu* me, gme_user_cleanup_t func ) { me->set_user_cleanup( func ); } + +BLARGG_EXPORT gme_err_t gme_start_track ( Music_Emu* me, int index ) { return me->start_track( index ); } +BLARGG_EXPORT gme_err_t gme_play ( Music_Emu* me, int n, short* p ) { return me->play( n, p ); } +BLARGG_EXPORT void gme_set_fade ( Music_Emu* me, int start_msec ) { me->set_fade( start_msec ); } +BLARGG_EXPORT int gme_track_ended ( Music_Emu const* me ) { return me->track_ended(); } +BLARGG_EXPORT int gme_tell ( Music_Emu const* me ) { return me->tell(); } +BLARGG_EXPORT gme_err_t gme_seek ( Music_Emu* me, int msec ) { return me->seek( msec ); } +BLARGG_EXPORT int gme_voice_count ( Music_Emu const* me ) { return me->voice_count(); } +BLARGG_EXPORT void gme_ignore_silence ( Music_Emu* me, int disable ) { me->ignore_silence( disable != 0 ); } +BLARGG_EXPORT void gme_set_tempo ( Music_Emu* me, double t ) { me->set_tempo( t ); } +BLARGG_EXPORT void gme_mute_voice ( Music_Emu* me, int index, int mute ) { me->mute_voice( index, mute != 0 ); } +BLARGG_EXPORT void gme_mute_voices ( Music_Emu* me, int mask ) { me->mute_voices( mask ); } +BLARGG_EXPORT void gme_clear_playlist ( Music_Emu* me ) { me->clear_playlist(); } +BLARGG_EXPORT int gme_type_multitrack( gme_type_t t ) { return t->track_count != 1; } -void gme_set_equalizer ( Music_Emu* me, gme_equalizer_t const* eq ) +BLARGG_EXPORT void gme_set_equalizer ( Music_Emu* me, gme_equalizer_t const* eq ) { Music_Emu::equalizer_t e = me->equalizer(); e.treble = eq->treble; @@ -346,7 +348,7 @@ me->set_equalizer( e ); } -void gme_equalizer( Music_Emu const* me, gme_equalizer_t* out ) +BLARGG_EXPORT void gme_equalizer( Music_Emu const* me, gme_equalizer_t* out ) { gme_equalizer_t e = { }; e.treble = me->equalizer().treble; @@ -354,13 +356,13 @@ *out = e; } -const char* gme_voice_name( Music_Emu const* me, int i ) +BLARGG_EXPORT const char* gme_voice_name( Music_Emu const* me, int i ) { assert( (unsigned) i < (unsigned) me->voice_count() ); return me->voice_names() [i]; } -const char* gme_type_system( gme_type_t type ) +BLARGG_EXPORT const char* gme_type_system( gme_type_t type ) { assert( type ); return type->system; diff -Nur orig/gme/M3u_Playlist.cpp new/gme/M3u_Playlist.cpp --- orig/gme/M3u_Playlist.cpp 2009-07-27 06:14:46.000000000 +0200 +++ new/gme/M3u_Playlist.cpp 2011-03-26 19:42:48.291020831 +0100 @@ -52,9 +52,9 @@ blargg_err_t Gme_File::load_m3u( Data_Reader& in ) { return load_m3u_( playlist.load( in ) ); } -gme_err_t gme_load_m3u( Music_Emu* me, const char* path ) { return me->load_m3u( path ); } +BLARGG_EXPORT gme_err_t gme_load_m3u( Music_Emu* me, const char* path ) { return me->load_m3u( path ); } -gme_err_t gme_load_m3u_data( Music_Emu* me, const void* data, long size ) +BLARGG_EXPORT gme_err_t gme_load_m3u_data( Music_Emu* me, const void* data, long size ) { Mem_File_Reader in( data, size ); return me->load_m3u( in ); diff -Nur orig/player/Music_Player.cpp new/player/Music_Player.cpp --- orig/player/Music_Player.cpp 2009-07-27 06:14:46.000000000 +0200 +++ new/player/Music_Player.cpp 2011-03-26 19:42:48.293020823 +0100 @@ -2,12 +2,10 @@ #include "Music_Player.h" -#include "gme/Music_Emu.h" - #include #include -/* Copyright (C) 2005-2006 by Shay Green. Permission is hereby granted, free of +/* Copyright (C) 2005-2010 by Shay Green. Permission is hereby granted, free of charge, to any person obtaining a copy of this software module and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, @@ -22,7 +20,12 @@ IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -#include "blargg_source.h" +#define RETURN_ERR( expr ) \ + do {\ + gme_err_t err_ = (expr);\ + if ( err_ )\ + return err_;\ + } while ( 0 ) // Number of audio buffers per second. Adjust if you encounter audio skipping. const int fill_rate = 45; @@ -36,12 +39,13 @@ Music_Player::Music_Player() { - emu_ = 0; - scope_buf = 0; - paused = false; + emu_ = 0; + scope_buf = 0; + paused = false; + track_info_ = NULL; } -blargg_err_t Music_Player::init( long rate ) +gme_err_t Music_Player::init( long rate ) { sample_rate = rate; @@ -56,17 +60,18 @@ void Music_Player::stop() { sound_stop(); - delete emu_; - emu_ = 0; + gme_delete( emu_ ); + emu_ = NULL; } Music_Player::~Music_Player() { stop(); sound_cleanup(); + gme_free_info( track_info_ ); } -blargg_err_t Music_Player::load_file( const char* path ) +gme_err_t Music_Player::load_file( const char* path ) { stop(); @@ -79,34 +84,36 @@ if ( !p ) p = m3u_path + strlen( m3u_path ); strcpy( p, ".m3u" ); - if ( emu_->load_m3u( m3u_path ) ) { } // ignore error + if ( gme_load_m3u( emu_, m3u_path ) ) { } // ignore error return 0; } int Music_Player::track_count() const { - return emu_ ? emu_->track_count() : false; + return emu_ ? gme_track_count( emu_ ) : false; } -blargg_err_t Music_Player::start_track( int track ) +gme_err_t Music_Player::start_track( int track ) { if ( emu_ ) { + gme_free_info( track_info_ ); + track_info_ = NULL; + RETURN_ERR( gme_track_info( emu_, &track_info_, track ) ); + // Sound must not be running when operating on emulator sound_stop(); - RETURN_ERR( emu_->start_track( track ) ); + RETURN_ERR( gme_start_track( emu_, track ) ); // Calculate track length - if ( !emu_->track_info( &track_info_ ) ) - { - if ( track_info_.length <= 0 ) - track_info_.length = track_info_.intro_length + - track_info_.loop_length * 2; - } - if ( track_info_.length <= 0 ) - track_info_.length = (long) (2.5 * 60 * 1000); - emu_->set_fade( track_info_.length ); + if ( track_info_->length <= 0 ) + track_info_->length = track_info_->intro_length + + track_info_->loop_length * 2; + + if ( track_info_->length <= 0 ) + track_info_->length = (long) (2.5 * 60 * 1000); + gme_set_fade( emu_, track_info_->length ); paused = false; sound_start(); @@ -137,7 +144,7 @@ bool Music_Player::track_ended() const { - return emu_ ? emu_->track_ended() : false; + return emu_ ? gme_track_ended( emu_ ) : false; } void Music_Player::set_stereo_depth( double tempo ) @@ -150,15 +157,15 @@ void Music_Player::set_tempo( double tempo ) { suspend(); - emu_->set_tempo( tempo ); + gme_set_tempo( emu_, tempo ); resume(); } void Music_Player::mute_voices( int mask ) { suspend(); - emu_->mute_voices( mask ); - emu_->ignore_silence( mask != 0 ); + gme_mute_voices( emu_, mask ); + gme_ignore_silence( emu_, mask != 0 ); resume(); } @@ -167,7 +174,7 @@ Music_Player* self = (Music_Player*) data; if ( self->emu_ ) { - if ( self->emu_->play( count, out ) ) { } // ignore error + if ( gme_play( self->emu_, count, out ) ) { } // ignore error if ( self->scope_buf ) memcpy( self->scope_buf, out, self->scope_buf_size * sizeof *self->scope_buf ); diff -Nur orig/player/Music_Player.h new/player/Music_Player.h --- orig/player/Music_Player.h 2009-07-27 06:14:46.000000000 +0200 +++ new/player/Music_Player.h 2011-03-26 19:42:48.292020827 +0100 @@ -4,18 +4,18 @@ #ifndef MUSIC_PLAYER_H #define MUSIC_PLAYER_H -#include "gme/Music_Emu.h" +#include "gme.h" class Music_Player { public: // Initialize player and set sample rate - blargg_err_t init( long sample_rate = 44100 ); + gme_err_t init( long sample_rate = 44100 ); // Load game music file. NULL on success, otherwise error string. - blargg_err_t load_file( const char* path ); + gme_err_t load_file( const char* path ); // (Re)start playing track. Tracks are numbered from 0 to track_count() - 1. - blargg_err_t start_track( int track ); + gme_err_t start_track( int track ); // Stop playing current file void stop(); @@ -26,7 +26,7 @@ int track_count() const; // Info for current track - track_info_t const& track_info() const { return track_info_; } + gme_info_t const& track_info() const { return *track_info_; } // Pause/resume playing current track. void pause( int ); @@ -59,7 +59,7 @@ long sample_rate; int scope_buf_size; bool paused; - track_info_t track_info_; + gme_info_t* track_info_; void suspend(); void resume();