Tuesday, 30 April 2013

Music player, using external library and making routine!

Today's post is about many topics, but all around the same main argument: using external programs or libraries.
If already exists a program that it does what you want, you avoid a lot of work using it.
For example you may write in rebol a GUI for a command line program to see a video:

call "vlc --no-osd myvideo.avi"


Sometime you don't need to launch a big external program, you just need some feature of the external program, so probably you want to use a library. A library is like an external software, but very tiny and for just some purpose. Using a library it's quickly than a normal external software. An external library on windows usually ends with .dll extension, on Linux with .so. The following guide will use a windows DLL, but it's totally the same on Linux and Mac.

First of all you have to load the library and giving it a name, for example "lib":
lib: load/library %libwmp3.dll

now lib is a rebol library and you can interact with it using the routine!. A Library expects a command, that is case sensitive, and returns a status or an error. Let's see an example:

Mp3_SetVolume: make routine! [
return: [integer!]
initialized [integer!]
nLeftVolume [integer!]
nRightVolume [integer!]
] lib "Mp3_SetVolume"


The Mp3_SetVolume routine can now be used to set sound volume, you may use it this way:
Mp3_SetVolume myinitialized 100 100
as you see we launch the routine with all parameters declared: initialized resource, left volume, right volume. It returns 0 or 1 if all went ok or not.

You have to read library documentation to know which routines are available and what parameters they want.

Now I implemented a MP3 player using a Nick Antonaccio script, turn up the volume to listen it well:




here is the source:
REBOL [
    File: %mp3-player-libwmp.r
    Date: 9-Aug-2009
    Title: "mp3-player-demo-using-libwmp3.dll"
    Author:   ["Nick Antonaccio" "Massimilino Vessi"]
    Purpose: {
        Demo of how to play mp3 files in REBOL using libwmp3.dll
        ( http://www.inet.hr/~zcindori/libwmp3/index.html )
        Taken from the tutorial at http://musiclessonz.com/rebol.html
    }
]
if not exists? %libwmp3.dll [
    ; "Downloading libwmp3.dll..."
  request-download/to http://musiclessonz.com/rebol_tutorial/libwmp3.dll   %libwmp3.dll
]
lib: load/library %libwmp3.dll
; ---------------------------------------------------------
; Required functions in libwmp3.dll:
; ---------------------------------------------------------

Mp3_Initialize: make routine! [
    return: [integer!]
] lib "Mp3_Initialize"
Mp3_Destroy: make routine! [
    return: [integer!]
    initialized [integer!]
] lib "Mp3_Destroy"
Mp3_OpenFile: make routine! [
    return: [integer!]
    class [integer!]
    filename [string!]
    nWaveBufferLengthMs [integer!]
    nSeekFromStart [integer!]
    nFileSize [integer!]
] lib "Mp3_OpenFile"
Mp3_Play: make routine! [
    return: [integer!]
    initialized [integer!]
] lib "Mp3_Play"
; ---------------------------------------------------------
; Some more useful values and functions:
; ---------------------------------------------------------

status: make struct! [
    fPlay [integer!]          
    ; if song is playing this value is nonzero
    fPause [integer!]          
    ; if song is paused this value is nonzero
    fStop [integer!]          
    ; if song is stoped this value is nonzero
    fEcho [integer!]          
    ; if echo is enabled this value is nonzero
    nSfxMode [integer!]        
    ; return current echo mode
    fExternalEQ [integer!]    
    ; if external equalizer is enabled this value is nonzero
    fInternalEQ [integer!]    
    ; if internal equalizer is enabled this value is nonzero    
    fVocalCut [integer!]      
    ; if vocal cut is enabled this value is nonzero
    fChannelMix [integer!]    
    ; if channel mixing is enabled this value is nonzero
    fFadeIn [integer!]        
    ; if song is in "fade in" interval this value is nonzero
    fFadeOut [integer!]        
    ; if song is in "fade out" interval this value is nonzero
    fInternalVolume [integer!]
    ; if internal volume is enabled this value is nonzero
    fLoop [integer!]          
    ; if song is in loop this value is nonzero
    fReverse [integer!]        
    ; if song is in reverse mode this value is nonzero
] none
Mp3_GetStatus: make routine! [
    return: [integer!]
    initialized [integer!]
    status [struct! []]
] lib "Mp3_GetStatus"
Mp3_Time: make struct! [
    ms [integer!]
    sec [integer!]
    bytes [integer!]
    frames [integer!]
    hms_hour [integer!]
    hms_minute [integer!]
    hms_second [integer!]
    hms_millisecond [integer!]
] none
TIME_FORMAT_MS: 1
TIME_FORMAT_SEC: 2
TIME_FORMAT_HMS: 4
TIME_FORMAT_BYTES: 8
SONG_BEGIN: 1
SONG_END: 2
SONG_CURRENT_FORWARD: 4
SONG_CURRENT_BACKWARD: 8
Mp3_Seek: make routine! [
    return: [integer!]
    initialized [integer!]
    fFormat [integer!]
    pTime [struct! []]
    nMoveMethod [integer!]
] lib "Mp3_Seek"
; Mp3_Seek stops play.   ALWAYS CALL Mp3_Play AFTER USING IT.

Mp3_PlayLoop: make routine! [
    return: [integer!]
    initialized [integer!]
    fFormatStartTime [integer!]
    pStartTime [struct! []]
    fFormatEndTime [integer!]
    pEndTime [struct! []]
    nNumOfRepeat [integer!]
] lib "Mp3_PlayLoop"
Mp3_GetPosition: make routine! [
    return: [integer!]
    initialized [integer!]
    pTime [struct! []]
] lib "Mp3_GetPosition"
Mp3_Pause: make routine! [
    return: [integer!]
    initialized [integer!]
] lib "Mp3_Pause"
Mp3_Resume: make routine! [
    return: [integer!]
    initialized [integer!]
] lib "Mp3_Resume"
Mp3_SetVolume: make routine! [
    return: [integer!]
    initialized [integer!]
    nLeftVolume [integer!]
    nRightVolume [integer!]
] lib "Mp3_SetVolume"
; volume range is 0 to 100

Mp3_SetMasterVolume: make routine! [
    return: [integer!]
    initialized [integer!]
    nLeftVolume [integer!]
    nRightVolume [integer!]
] lib "Mp3_SetMasterVolume"
; SetMasterVolume sets output volume of wave out device driver
; (the master volue of all sounds on the computer):

Mp3_VocalCut: make routine! [
    return: [integer!]
    initialized [integer!]
    fEnable [integer!]
] lib "Mp3_VocalCut"
; 1 enables vocal cut, 0 disables vocal cut

Mp3_ReverseMode: make routine! [
    return: [integer!]
    initialized [integer!]
    fEnable [integer!]
] lib "Mp3_ReverseMode"
; 1 enables playing mp3 in reverse, 0 plays normal (forward)

Mp3_Stop: make routine! [
    return: [integer!]
    initialized [integer!]
] lib "Mp3_Stop"
Mp3_Close: make routine! [
    return: [integer!]
    initialized [integer!]
] lib "Mp3_Close"
; There are MANY more powerful functions in libmp3.dll.  
; The functions above will get mp3s playing, and enable
; some basic capabilities such as pause/resume, volume
; control, seeking (fast forward and rewind), looping, as
; well as some interesting tools such as reverse play and
; vocal removal (for stereo tracks only).
; The prototypes above should provide clear enough examples
; to demonstrate how to use all the other functions in the
; library:   equalizer settings, stream playing, retrieval
; of ID field and recorded data info, effect application
; (echo, etc.), and more.   I drew these function prototypes
; from the Visual Basic example that ships with libwmp3.
; Converting the rest of the functions should be easy...
; (Wrap everything in a nice GUI and we'll have a killer
; REBOL mp3 player (on my to do list... ;))

; ---------------------------------------------------------
; Required REBOL code starts here:
; ---------------------------------------------------------

; 1st, call the Initialize function:

initialized: Mp3_Initialize
; Then open an mp3 file (change the string to select a
; different file):

view layout [
across
title "MP3 player"
return
song: h2 red 420   ;song title
return
button "open" [
    title: first request-file/filter   "*.mp3"
    song/text: second split-path title
    file: to-string to-local-file to-file title
    Mp3_OpenFile initialized file 1000 0 0
    show song
    ]
toggle "reverse mode" [either face/state [Mp3_ReverseMode initialized 1] [Mp3_ReverseMode initialized 0]]
toggle "Vocal" "No vocal" [either face/state [Mp3_VocalCut initialized 1] [Mp3_VocalCut initialized 0]]
return
across
button "<<" [
    ptime: make struct! Mp3_Time [0 -10 0 0 0 0 0 0]
    Mp3_Seek initialized TIME_FORMAT_SEC ptime SONG_CURRENT_FORWARD
    Mp3_Play initialized
    ]
toggle {||} [either face/state [ Mp3_Pause initialized] [Mp3_Resume initialized] ]
toggle ">" "Stop" [either face/state [Mp3_Play initialized] [Mp3_Stop initialized ]]
button ">>" [
    ptime: make struct! Mp3_Time [0 10 0 0 0 0 0 0]
    Mp3_Seek initialized TIME_FORMAT_SEC ptime SONG_CURRENT_FORWARD
    Mp3_Play initialized
    ]  
return  
label   "Volume:"
slider 330x20 0.5 [
    Mp3_SetVolume initialized   (to-integer (100 * face/data)) (to-integer (100 * face/data))
    vl/text: to-string (to-integer (100 * face/data))
    show vl
    ]
vl: txt 40 "50"
]

No comments:

Post a Comment