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"
]

1 comment:

  1. If you want your ex-girlfriend or ex-boyfriend to come crawling back to you on their knees (even if they're dating somebody else now) you must watch this video
    right away...

    (VIDEO) Want your ex CRAWLING back to you...?

    ReplyDelete