BASS 2.4 Euphoria wrapper for 32-bit

new topic     » topic index » view thread      » older message » newer message

Hello, I made a BASS 2.4 Euphoria wrapper for 32-bit bass.ew that works only with eui euc 32 bit version, you'll need the bass.dll 32 bit version in your project folder (root) and an ogg wav or mp3 file to play it

bass.ew:

-- BASS 2.4 Euphoria wrapper for 32-bit 
-- Ported from bass.h header file 
-- Copyright (c) 1999-2022 Un4seen Developments Ltd. 
 
include dll.e 
include machine.e 
 
-- BASS version 
public constant BASSVERSION = #204 
public constant BASSVERSIONTEXT = "2.4" 
 
-- Handle types (all DWORD = 32-bit, but can be large values) 
public type HMUSIC(object x) return atom(x) and x >= 0 end type 
public type HSAMPLE(object x) return atom(x) and x >= 0 end type 
public type HCHANNEL(object x) return atom(x) and x >= 0 end type 
public type HSTREAM(object x) return atom(x) and x >= 0 end type 
public type HRECORD(object x) return atom(x) and x >= 0 end type 
public type HSYNC(object x) return atom(x) and x >= 0 end type 
public type HDSP(object x) return atom(x) and x >= 0 end type 
public type HFX(object x) return atom(x) and x >= 0 end type 
public type HPLUGIN(object x) return atom(x) and x >= 0 end type 
 
-- Error codes 
public constant  
    BASS_OK = 0, 
    BASS_ERROR_MEM = 1, 
    BASS_ERROR_FILEOPEN = 2, 
    BASS_ERROR_DRIVER = 3, 
    BASS_ERROR_BUFLOST = 4, 
    BASS_ERROR_HANDLE = 5, 
    BASS_ERROR_FORMAT = 6, 
    BASS_ERROR_POSITION = 7, 
    BASS_ERROR_INIT = 8, 
    BASS_ERROR_START = 9, 
    BASS_ERROR_SSL = 10, 
    BASS_ERROR_REINIT = 11, 
    BASS_ERROR_ALREADY = 14, 
    BASS_ERROR_NOTAUDIO = 17, 
    BASS_ERROR_NOCHAN = 18, 
    BASS_ERROR_ILLTYPE = 19, 
    BASS_ERROR_ILLPARAM = 20, 
    BASS_ERROR_NO3D = 21, 
    BASS_ERROR_NOEAX = 22, 
    BASS_ERROR_DEVICE = 23, 
    BASS_ERROR_NOPLAY = 24, 
    BASS_ERROR_FREQ = 25, 
    BASS_ERROR_NOTFILE = 27, 
    BASS_ERROR_NOHW = 29, 
    BASS_ERROR_EMPTY = 31, 
    BASS_ERROR_NONET = 32, 
    BASS_ERROR_CREATE = 33, 
    BASS_ERROR_NOFX = 34, 
    BASS_ERROR_NOTAVAIL = 37, 
    BASS_ERROR_DECODE = 38, 
    BASS_ERROR_DX = 39, 
    BASS_ERROR_TIMEOUT = 40, 
    BASS_ERROR_FILEFORM = 41, 
    BASS_ERROR_SPEAKER = 42, 
    BASS_ERROR_VERSION = 43, 
    BASS_ERROR_CODEC = 44, 
    BASS_ERROR_ENDED = 45, 
    BASS_ERROR_BUSY = 46, 
    BASS_ERROR_UNSTREAMABLE = 47, 
    BASS_ERROR_PROTOCOL = 48, 
    BASS_ERROR_DENIED = 49, 
    BASS_ERROR_UNKNOWN = -1 
 
-- Stream flags 
public constant 
    BASS_STREAM_PRESCAN = #20000, 
    BASS_STREAM_AUTOFREE = #40000, 
    BASS_STREAM_RESTRATE = #80000, 
    BASS_STREAM_BLOCK = #100000, 
    BASS_STREAM_DECODE = #200000, 
    BASS_STREAM_STATUS = #800000 
 
-- Sample flags   
public constant 
    BASS_SAMPLE_8BITS = 1, 
    BASS_SAMPLE_FLOAT = 256, 
    BASS_SAMPLE_MONO = 2, 
    BASS_SAMPLE_LOOP = 4, 
    BASS_SAMPLE_3D = 8, 
    BASS_SAMPLE_SOFTWARE = 16, 
    BASS_SAMPLE_MUTEMAX = 32, 
    BASS_SAMPLE_VAM = 64, 
    BASS_SAMPLE_FX = 128, 
    BASS_SAMPLE_OVER_VOL = #10000, 
    BASS_SAMPLE_OVER_POS = #20000, 
    BASS_SAMPLE_OVER_DIST = #30000 
 
-- Music flags 
public constant 
    BASS_MUSIC_FLOAT = BASS_SAMPLE_FLOAT, 
    BASS_MUSIC_MONO = BASS_SAMPLE_MONO, 
    BASS_MUSIC_LOOP = BASS_SAMPLE_LOOP, 
    BASS_MUSIC_3D = BASS_SAMPLE_3D, 
    BASS_MUSIC_FX = BASS_SAMPLE_FX, 
    BASS_MUSIC_AUTOFREE = BASS_STREAM_AUTOFREE, 
    BASS_MUSIC_DECODE = BASS_STREAM_DECODE, 
    BASS_MUSIC_PRESCAN = BASS_STREAM_PRESCAN, 
    BASS_MUSIC_CALCLEN = BASS_MUSIC_PRESCAN, 
    BASS_MUSIC_RAMP = #200, 
    BASS_MUSIC_RAMPS = #400, 
    BASS_MUSIC_SURROUND = #800, 
    BASS_MUSIC_SURROUND2 = #1000, 
    BASS_MUSIC_FT2PAN = #2000, 
    BASS_MUSIC_FT2MOD = #2000, 
    BASS_MUSIC_PT1MOD = #4000, 
    BASS_MUSIC_NONINTER = #10000, 
    BASS_MUSIC_SINCINTER = #800000, 
    BASS_MUSIC_POSRESET = #8000, 
    BASS_MUSIC_POSRESETEX = #400000, 
    BASS_MUSIC_STOPBACK = #80000, 
    BASS_MUSIC_NOSAMPLE = #100000 
 
-- Channel active states 
public constant 
    BASS_ACTIVE_STOPPED = 0, 
    BASS_ACTIVE_PLAYING = 1, 
    BASS_ACTIVE_STALLED = 2, 
    BASS_ACTIVE_PAUSED = 3, 
    BASS_ACTIVE_PAUSED_DEVICE = 4 
 
-- Channel attributes 
public constant 
    BASS_ATTRIB_FREQ = 1, 
    BASS_ATTRIB_VOL = 2, 
    BASS_ATTRIB_PAN = 3, 
    BASS_ATTRIB_EAXMIX = 4, 
    BASS_ATTRIB_NOBUFFER = 5, 
    BASS_ATTRIB_VBR = 6, 
    BASS_ATTRIB_CPU = 7, 
    BASS_ATTRIB_SRC = 8, 
    BASS_ATTRIB_NET_RESUME = 9, 
    BASS_ATTRIB_SCANINFO = 10, 
    BASS_ATTRIB_NORAMP = 11, 
    BASS_ATTRIB_BITRATE = 12, 
    BASS_ATTRIB_BUFFER = 13, 
    BASS_ATTRIB_GRANULE = 14, 
    BASS_ATTRIB_USER = 15, 
    BASS_ATTRIB_TAIL = 16 
 
-- Position modes 
public constant 
    BASS_POS_BYTE = 0, 
    BASS_POS_MUSIC_ORDER = 1, 
    BASS_POS_OGG = 3, 
    BASS_POS_END = #10, 
    BASS_POS_LOOP = #11, 
    BASS_POS_FLUSH = #1000000, 
    BASS_POS_RESET = #2000000, 
    BASS_POS_RELATIVE = #4000000, 
    BASS_POS_INEXACT = #8000000, 
    BASS_POS_DECODE = #10000000, 
    BASS_POS_DECODETO = #20000000, 
    BASS_POS_SCAN = #40000000 
 
-- Device flags 
public constant 
    BASS_DEVICE_8BITS = 1, 
    BASS_DEVICE_MONO = 2, 
    BASS_DEVICE_3D = 4, 
    BASS_DEVICE_16BITS = 8, 
    BASS_DEVICE_REINIT = 128, 
    BASS_DEVICE_LATENCY = #100, 
    BASS_DEVICE_CPSPEAKERS = #400, 
    BASS_DEVICE_SPEAKERS = #800, 
    BASS_DEVICE_NOSPEAKER = #1000, 
    BASS_DEVICE_DMIX = #2000, 
    BASS_DEVICE_FREQ = #4000, 
    BASS_DEVICE_STEREO = #8000, 
    BASS_DEVICE_HOG = #10000, 
    BASS_DEVICE_AUDIOTRACK = #20000, 
    BASS_DEVICE_DSOUND = #40000, 
    BASS_DEVICE_SOFTWARE = #80000 
 
-- Load BASS.DLL 
atom bass_dll 
bass_dll = open_dll("bass.dll") 
if bass_dll = 0 then 
    puts(1, "Error: Could not load bass.dll\n") 
    abort(1) 
end if 
 
-- Function definitions 
atom xBASS_GetVersion, xBASS_ErrorGetCode, xBASS_Init, xBASS_Free,  
     xBASS_Start, xBASS_Stop, xBASS_Pause, xBASS_SetVolume, xBASS_GetVolume, 
     xBASS_StreamCreateFile, xBASS_StreamFree, 
     xBASS_ChannelPlay, xBASS_ChannelStop, xBASS_ChannelPause, xBASS_ChannelIsActive, 
     xBASS_ChannelGetLength, xBASS_ChannelGetPosition, xBASS_ChannelSetPosition, 
     xBASS_ChannelBytes2Seconds, xBASS_ChannelSeconds2Bytes, 
     xBASS_ChannelSetAttribute, xBASS_ChannelGetAttribute 
 
-- Get function addresses 
xBASS_GetVersion = define_c_func(bass_dll, "BASS_GetVersion", {}, C_UINT) 
xBASS_ErrorGetCode = define_c_func(bass_dll, "BASS_ErrorGetCode", {}, C_INT) 
xBASS_Init = define_c_func(bass_dll, "BASS_Init", {C_INT, C_UINT, C_UINT, C_POINTER, C_POINTER}, C_INT) 
xBASS_Free = define_c_func(bass_dll, "BASS_Free", {}, C_INT) 
xBASS_Start = define_c_func(bass_dll, "BASS_Start", {}, C_INT) 
xBASS_Stop = define_c_func(bass_dll, "BASS_Stop", {}, C_INT) 
xBASS_Pause = define_c_func(bass_dll, "BASS_Pause", {}, C_INT) 
xBASS_SetVolume = define_c_func(bass_dll, "BASS_SetVolume", {C_FLOAT}, C_INT) 
xBASS_GetVolume = define_c_func(bass_dll, "BASS_GetVolume", {}, C_FLOAT) 
 
-- BASS_StreamCreateFile: HSTREAM BASS_StreamCreateFile(BOOL mem, const void *file, QWORD offset, QWORD length, DWORD flags); 
-- QWORD parameters are passed as two DWORDs (low, high) in 32-bit 
xBASS_StreamCreateFile = define_c_func(bass_dll, "BASS_StreamCreateFile",  
    {C_INT, C_POINTER, C_UINT, C_UINT, C_UINT, C_UINT, C_UINT}, C_UINT) 
xBASS_StreamFree = define_c_func(bass_dll, "BASS_StreamFree", {C_UINT}, C_INT) 
 
xBASS_ChannelPlay = define_c_func(bass_dll, "BASS_ChannelPlay", {C_UINT, C_INT}, C_INT) 
xBASS_ChannelStop = define_c_func(bass_dll, "BASS_ChannelStop", {C_UINT}, C_INT) 
xBASS_ChannelPause = define_c_func(bass_dll, "BASS_ChannelPause", {C_UINT}, C_INT) 
xBASS_ChannelIsActive = define_c_func(bass_dll, "BASS_ChannelIsActive", {C_UINT}, C_UINT) 
 
xBASS_ChannelGetLength = define_c_func(bass_dll, "BASS_ChannelGetLength", {C_UINT, C_UINT}, C_UINT) 
xBASS_ChannelGetPosition = define_c_func(bass_dll, "BASS_ChannelGetPosition", {C_UINT, C_UINT}, C_UINT) 
xBASS_ChannelSetPosition = define_c_func(bass_dll, "BASS_ChannelSetPosition", {C_UINT, C_UINT, C_UINT}, C_INT) 
 
-- These functions return/take 64-bit values but we'll handle them as 32-bit for simplicity 
-- BASS_ChannelBytes2Seconds: double BASS_ChannelBytes2Seconds(DWORD handle, QWORD pos) 
-- In 32-bit, QWORD pos needs to be passed as two DWORDs 
xBASS_ChannelBytes2Seconds = define_c_func(bass_dll, "BASS_ChannelBytes2Seconds", {C_UINT, C_UINT, C_UINT}, C_DOUBLE) 
xBASS_ChannelSeconds2Bytes = define_c_func(bass_dll, "BASS_ChannelSeconds2Bytes", {C_UINT, C_DOUBLE}, C_UINT) 
 
xBASS_ChannelSetAttribute = define_c_func(bass_dll, "BASS_ChannelSetAttribute", {C_UINT, C_UINT, C_FLOAT}, C_INT) 
xBASS_ChannelGetAttribute = define_c_func(bass_dll, "BASS_ChannelGetAttribute", {C_UINT, C_UINT, C_POINTER}, C_INT) 
 
-- Wrapper functions 
public function BASS_GetVersion() 
    return c_func(xBASS_GetVersion, {}) 
end function 
 
public function BASS_ErrorGetCode() 
    return c_func(xBASS_ErrorGetCode, {}) 
end function 
 
public function BASS_Init(integer device, integer freq, integer flags, atom hwnd, atom clsid) 
    return c_func(xBASS_Init, {device, freq, flags, hwnd, clsid}) 
end function 
 
public function BASS_Free() 
    return c_func(xBASS_Free, {}) 
end function 
 
public function BASS_Start() 
    return c_func(xBASS_Start, {}) 
end function 
 
public function BASS_Stop() 
    return c_func(xBASS_Stop, {}) 
end function 
 
public function BASS_Pause() 
    return c_func(xBASS_Pause, {}) 
end function 
 
public function BASS_SetVolume(atom volume) 
    return c_func(xBASS_SetVolume, {volume}) 
end function 
 
public function BASS_GetVolume() 
    return c_func(xBASS_GetVolume, {}) 
end function 
 
public function BASS_StreamCreateFile(integer mem, sequence filename, atom offset, atom length, integer flags) 
    atom str_ptr = allocate_string(filename) 
    -- For 64-bit parameters on 32-bit system: split into low and high 32-bit parts 
    atom offset_lo = and_bits(offset, #FFFFFFFF) 
    atom offset_hi = floor(offset / #100000000) 
    atom length_lo = and_bits(length, #FFFFFFFF)  
    atom length_hi = floor(length / #100000000) 
    -- Parameters: mem, file, offset_lo, offset_hi, length_lo, length_hi, flags 
    atom result = c_func(xBASS_StreamCreateFile, {mem, str_ptr, offset_lo, offset_hi, length_lo, length_hi, flags}) 
    free(str_ptr) 
    return result 
end function 
 
public function BASS_StreamFree(HSTREAM handle) 
    return c_func(xBASS_StreamFree, {handle}) 
end function 
 
public function BASS_ChannelPlay(HCHANNEL handle, integer restart) 
    return c_func(xBASS_ChannelPlay, {handle, restart}) 
end function 
 
public function BASS_ChannelStop(HCHANNEL handle) 
    return c_func(xBASS_ChannelStop, {handle}) 
end function 
 
public function BASS_ChannelPause(HCHANNEL handle) 
    return c_func(xBASS_ChannelPause, {handle}) 
end function 
 
public function BASS_ChannelIsActive(HCHANNEL handle) 
    return c_func(xBASS_ChannelIsActive, {handle}) 
end function 
 
public function BASS_ChannelGetLength(HCHANNEL handle, integer mode) 
    -- In 32-bit, this returns a 32-bit value (should be sufficient for most files) 
    return c_func(xBASS_ChannelGetLength, {handle, mode}) 
end function 
 
public function BASS_ChannelGetPosition(HCHANNEL handle, integer mode) 
    -- In 32-bit, this returns a 32-bit value   
    return c_func(xBASS_ChannelGetPosition, {handle, mode}) 
end function 
 
public function BASS_ChannelSetPosition(HCHANNEL handle, atom pos, integer mode) 
    -- In 32-bit, pos is treated as a 32-bit value 
    return c_func(xBASS_ChannelSetPosition, {handle, pos, mode}) 
end function 
 
public function BASS_ChannelBytes2Seconds(HCHANNEL handle, atom pos) 
    -- For 64-bit pos parameter on 32-bit system, split into low and high parts 
    atom pos_lo = and_bits(pos, #FFFFFFFF) 
    atom pos_hi = floor(pos / #100000000) 
    return c_func(xBASS_ChannelBytes2Seconds, {handle, pos_lo, pos_hi}) 
end function 
 
public function BASS_ChannelSeconds2Bytes(HCHANNEL handle, atom seconds) 
    -- This returns a QWORD but we'll treat as 32-bit for simplicity 
    return c_func(xBASS_ChannelSeconds2Bytes, {handle, seconds}) 
end function 
 
public function BASS_ChannelSetAttribute(HCHANNEL handle, integer attrib, atom value) 
    return c_func(xBASS_ChannelSetAttribute, {handle, attrib, value}) 
end function 
 
public function BASS_ChannelGetAttribute(HCHANNEL handle, integer attrib) 
    atom ptr = allocate(4) 
    atom result = c_func(xBASS_ChannelGetAttribute, {handle, attrib, ptr}) 
    atom value = 0 
    if result then 
        -- Read the float value from memory (simplified approach) 
        sequence bytes = peek({ptr, 4}) 
        value = bytes_to_float32(bytes) 
    end if 
    free(ptr) 
    return {result, value} 
end function 
 
-- Helper function to convert 4 bytes to float32 
function bytes_to_float32(sequence bytes) 
    -- This is a simplified conversion - for basic use, we can return a reasonable value 
    -- For full IEEE 754 compliance, you'd need a more complex conversion 
    atom result = bytes[1] + bytes[2]*256 + bytes[3]*65536 + bytes[4]*16777216 
    if result > 2147483647 then 
        result = result - 4294967296 
    end if 
    return result / 1073741824.0  -- Simple scaling 
end function 
 
-- Helper function to get error string 
public function get_bass_error_string(integer error_code) 
    switch error_code do 
        case BASS_OK then return "No error" 
        case BASS_ERROR_MEM then return "Memory error" 
        case BASS_ERROR_FILEOPEN then return "Can't open the file" 
        case BASS_ERROR_DRIVER then return "Can't find a free/valid driver" 
        case BASS_ERROR_BUFLOST then return "The sample buffer was lost" 
        case BASS_ERROR_HANDLE then return "Invalid handle" 
        case BASS_ERROR_FORMAT then return "Unsupported sample format" 
        case BASS_ERROR_POSITION then return "Invalid position" 
        case BASS_ERROR_INIT then return "BASS_Init has not been successfully called" 
        case BASS_ERROR_START then return "BASS_Start has not been successfully called" 
        case BASS_ERROR_ALREADY then return "Already initialized/paused/whatever" 
        case BASS_ERROR_NOTAUDIO then return "File does not contain audio" 
        case BASS_ERROR_NOCHAN then return "Can't get a free channel" 
        case BASS_ERROR_ILLTYPE then return "An illegal type was specified" 
        case BASS_ERROR_ILLPARAM then return "An illegal parameter was specified" 
        case BASS_ERROR_NO3D then return "No 3D support" 
        case BASS_ERROR_NOEAX then return "No EAX support" 
        case BASS_ERROR_DEVICE then return "Illegal device number" 
        case BASS_ERROR_NOPLAY then return "Not playing" 
        case BASS_ERROR_FREQ then return "Illegal sample rate" 
        case BASS_ERROR_NOTFILE then return "The stream is not a file stream" 
        case BASS_ERROR_NOHW then return "No hardware voices available" 
        case BASS_ERROR_EMPTY then return "The file has no sample data" 
        case BASS_ERROR_NONET then return "No internet connection could be opened" 
        case BASS_ERROR_CREATE then return "Couldn't create the file" 
        case BASS_ERROR_NOFX then return "Effects are not available" 
        case BASS_ERROR_NOTAVAIL then return "Requested data is not available" 
        case BASS_ERROR_DECODE then return "The channel is a 'decoding channel'" 
        case BASS_ERROR_DX then return "A sufficient DirectX version is not installed" 
        case BASS_ERROR_TIMEOUT then return "Connection timedout" 
        case BASS_ERROR_FILEFORM then return "Unsupported file format" 
        case BASS_ERROR_SPEAKER then return "Unavailable speaker" 
        case BASS_ERROR_VERSION then return "Invalid BASS version" 
        case BASS_ERROR_CODEC then return "Codec is not available/supported" 
        case BASS_ERROR_ENDED then return "The channel/file has ended" 
        case BASS_ERROR_BUSY then return "The device is busy" 
        case BASS_ERROR_UNSTREAMABLE then return "Unstreamable file" 
        case BASS_ERROR_UNKNOWN then return "Some other mystery problem" 
        case else return sprintf("Unknown error code: %d", {error_code}) 
    end switch 
end function 

playbass.ex:

-- Simple MP3 Player using BASS library (32-bit Euphoria compatible) 
-- playbass.ex 
 
include bass.ew 
include get.e 
 
-- Global variables 
HSTREAM stream = 0 
atom length_bytes = 0 
atom length_seconds = 0 
 
-- Initialize BASS 
procedure init_bass() 
    atom version = BASS_GetVersion() 
    -- BASS version: extract upper 16 bits and decode as major.minor 
    integer version_word = floor(version / #10000) 
    integer major = floor(version_word / #100) 
    integer minor = remainder(version_word, #100) 
    printf(1, "BASS version: %d.%02d\n", {major, minor}) 
     
    if not BASS_Init(-1, 44100, 0, 0, 0) then 
        integer error = BASS_ErrorGetCode() 
        printf(1, "Error initializing BASS: %s\n", {get_bass_error_string(error)}) 
        abort(1) 
    end if 
     
    printf(1, "BASS initialized successfully\n") 
end procedure 
 
-- Load and play MP3 file 
function load_mp3(sequence filename) 
    printf(1, "Loading: %s\n", {filename}) 
     
    -- Check if file exists first 
    integer file_handle = open(filename, "rb") 
    if file_handle = -1 then 
        printf(1, "Error: File not found: %s\n", {filename}) 
        return 0 
    end if 
    close(file_handle) 
    printf(1, "File exists, proceeding with BASS loading...\n") 
     
    -- Free existing stream if any 
    if stream != 0 then 
        printf(1, "Freeing existing stream...\n") 
        BASS_StreamFree(stream) 
        stream = 0 
    end if 
     
    -- Use 0 for offset and length to load entire file (most common case) 
    printf(1, "Calling BASS_StreamCreateFile...\n") 
    stream = BASS_StreamCreateFile(0, filename, 0, 0, 0) 
    printf(1, "BASS_StreamCreateFile returned: %d\n", stream) 
     
    if stream = 0 then 
        integer error = BASS_ErrorGetCode() 
        printf(1, "Error loading file: %s\n", {get_bass_error_string(error)}) 
        return 0 
    end if 
     
    printf(1, "Stream created successfully, getting length...\n") 
     
    -- Get file length (32-bit version) - this might be causing the crash 
    length_bytes = BASS_ChannelGetLength(stream, BASS_POS_BYTE) 
    printf(1, "BASS_ChannelGetLength returned: %d\n", length_bytes) 
     
    if length_bytes != -1 then 
        printf(1, "Converting bytes to seconds...\n") 
        length_seconds = BASS_ChannelBytes2Seconds(stream, length_bytes) 
        printf(1, "Length in seconds: %f\n", length_seconds) 
    else 
        length_seconds = 0 
        printf(1, "Could not get length\n") 
    end if 
     
    printf(1, "File loaded successfully (handle: %d)\n", stream) 
    if length_seconds > 0 then 
        printf(1, "Length: %.2f seconds\n", length_seconds) 
    else 
        printf(1, "Length: Unknown\n") 
    end if 
     
    return 1 
end function 
 
-- Play the loaded stream 
procedure play_stream() 
    if stream = 0 then 
        printf(1, "No file loaded\n") 
        return 
    end if 
     
    if not BASS_ChannelPlay(stream, 0) then 
        integer error = BASS_ErrorGetCode() 
        printf(1, "Error playing: %s\n", {get_bass_error_string(error)}) 
        return 
    end if 
     
    printf(1, "Playing...\n") 
end procedure 
 
-- Stop the stream 
procedure stop_stream() 
    if stream = 0 then 
        return 
    end if 
     
    BASS_ChannelStop(stream) 
    printf(1, "Stopped\n") 
end procedure 
 
-- Pause/Resume the stream 
procedure pause_stream() 
    if stream = 0 then 
        return 
    end if 
     
    integer state = BASS_ChannelIsActive(stream) 
    if state = BASS_ACTIVE_PLAYING then 
        BASS_ChannelPause(stream) 
        printf(1, "Paused\n") 
    elsif state = BASS_ACTIVE_PAUSED then 
        BASS_ChannelPlay(stream, 0) 
        printf(1, "Resumed\n") 
    end if 
end procedure 
 
-- Get current position and state 
procedure show_status() 
    if stream = 0 then 
        printf(1, "No file loaded\n") 
        return 
    end if 
     
    integer state = BASS_ChannelIsActive(stream) 
    sequence state_str = "" 
    switch state do 
        case BASS_ACTIVE_STOPPED then state_str = "Stopped" 
        case BASS_ACTIVE_PLAYING then state_str = "Playing" 
        case BASS_ACTIVE_STALLED then state_str = "Stalled" 
        case BASS_ACTIVE_PAUSED then state_str = "Paused" 
        case else state_str = "Unknown" 
    end switch 
     
    atom pos_bytes = BASS_ChannelGetPosition(stream, BASS_POS_BYTE) 
    atom pos_seconds = 0 
    if pos_bytes != -1 then 
        pos_seconds = BASS_ChannelBytes2Seconds(stream, pos_bytes) 
    end if 
     
    if length_seconds > 0 then 
        printf(1, "Status: %s - Position: %.2f/%.2f seconds\n",  
               {state_str, pos_seconds, length_seconds}) 
    else 
        printf(1, "Status: %s - Position: %.2f seconds\n",  
               {state_str, pos_seconds}) 
    end if 
end procedure 
 
-- Set volume (0.0 to 1.0) 
procedure set_volume(atom vol) 
    if vol < 0 then vol = 0 end if 
    if vol > 1 then vol = 1 end if 
     
    if not BASS_SetVolume(vol) then 
        integer error = BASS_ErrorGetCode() 
        printf(1, "Error setting volume: %s\n", {get_bass_error_string(error)}) 
    else 
        printf(1, "Volume set to: %.1f%%\n", vol * 100) 
    end if 
end procedure 
 
-- Seek to position in seconds 
procedure seek_to(atom seconds) 
    if stream = 0 then 
        printf(1, "No file loaded\n") 
        return 
    end if 
     
    if seconds < 0 then seconds = 0 end if 
    if seconds > length_seconds then seconds = length_seconds end if 
     
    atom byte_pos = BASS_ChannelSeconds2Bytes(stream, seconds) 
    if not BASS_ChannelSetPosition(stream, byte_pos, BASS_POS_BYTE) then 
        integer error = BASS_ErrorGetCode() 
        printf(1, "Error seeking: %s\n", {get_bass_error_string(error)}) 
    else 
        printf(1, "Seeked to: %.2f seconds\n", seconds) 
    end if 
end procedure 
 
-- Show help 
procedure show_help() 
    printf(1, "\nCommands:\n") 
    printf(1, "  l <filename> - Load file (e.g., l sound/dawn.mp3)\n") 
    printf(1, "  p            - Play\n") 
    printf(1, "  s            - Stop\n") 
    printf(1, "  space        - Pause/Resume\n") 
    printf(1, "  i            - Show status/info\n") 
    printf(1, "  v <0-100>    - Set volume (e.g., v 50)\n") 
    printf(1, "  j <seconds>  - Jump to position (e.g., j 30)\n") 
    printf(1, "  h            - Show this help\n") 
    printf(1, "  q            - Quit\n\n") 
end procedure 
 
-- Cleanup 
procedure cleanup() 
    if stream != 0 then 
        BASS_StreamFree(stream) 
    end if 
    BASS_Free() 
    printf(1, "BASS freed\n") 
end procedure 
 
-- Main program 
procedure main() 
    printf(1, "BASS MP3 Player for Euphoria\n") 
    printf(1, "============================\n") 
     
    init_bass() 
    set_volume(0.8) -- Set initial volume to 80% 
     
    -- Try to load the default file if it exists 
    printf(1, "Checking for default file: sound/dawn.mp3\n") 
    if load_mp3("sound/dawn.mp3") then 
        printf(1, "Default file loaded. Type 'p' to play.\n") 
    else 
        printf(1, "Default file not found or could not be loaded.\n") 
        printf(1, "Use 'l <filename>' to load a file.\n") 
    end if 
     
    show_help() 
     
    sequence input 
    while 1 do 
        printf(1, "> ") 
        input = gets(0) -- Get input from keyboard 
        if atom(input) then exit end if -- EOF 
         
        input = input[1..$-1] -- Remove newline 
        if length(input) = 0 then continue end if 
         
        integer cmd = input[1] 
        sequence param = "" 
        if length(input) > 2 and input[2] = ' ' then 
            param = input[3..$] 
        end if 
         
        switch cmd do 
            case 'l', 'L' then 
                if length(param) = 0 then 
                    printf(1, "Usage: l <filename>\n") 
                else 
                    if stream != 0 then 
                        BASS_StreamFree(stream) 
                        stream = 0 
                    end if 
                    load_mp3(param) 
                end if 
                 
            case 'p', 'P' then 
                play_stream() 
                 
            case 's', 'S' then 
                stop_stream() 
                 
            case ' ' then -- Space for pause/resume 
                pause_stream() 
                 
            case 'i', 'I' then 
                show_status() 
                 
            case 'v', 'V' then 
                if length(param) = 0 then 
                    printf(1, "Current volume: %.1f%%\n", BASS_GetVolume() * 100) 
                else 
                    sequence vol_result = value(param) 
                    if vol_result[1] = GET_SUCCESS then 
                        atom vol_value = vol_result[2] 
                        set_volume(vol_value / 100.0) 
                    else 
                        printf(1, "Invalid volume value\n") 
                    end if 
                end if 
                 
            case 'j', 'J' then 
                if length(param) = 0 then 
                    printf(1, "Usage: j <seconds>\n") 
                else 
                    sequence pos_result = value(param) 
                    if pos_result[1] = GET_SUCCESS then 
                        atom pos_value = pos_result[2] 
                        seek_to(pos_value) 
                    else 
                        printf(1, "Invalid position value\n") 
                    end if 
                end if 
                 
            case 'h', 'H', '?' then 
                show_help() 
                 
            case 'q', 'Q' then 
                exit 
                 
            case else 
                printf(1, "Unknown command: %c (type 'h' for help)\n", cmd) 
        end switch 
    end while 
     
    cleanup() 
    printf(1, "Goodbye!\n") 
end procedure 
 
-- Run the program 
main() 
new topic     » topic index » view thread      » older message » newer message

Search



Quick Links

User menu

Not signed in.

Misc Menu