{-# LANGUAGE ForeignFunctionInterface #-}

-- Copyright 2010 Evgeniy Vodolazskiy (waterlaz@gmail.com)
--
-- This library is free software; you can redistribute it and/or
-- modify it under the terms of the GNU Lesser General Public
-- License as published by the Free Software Foundation; either
-- version 2.1 of the License, or (at your option) any later version.
--
-- This library is distributed in the hope that it will be useful,
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-- Lesser General Public License for more details.

module Network.XMMS.Playback (
    SeekMode(..),
    tickle,
    stop,
    pause,
    start,
    seekmsAbs,
    seekmsRel,
    seekms,
    seekSamplesAbs,
    seekSamplesRel, 
    seekSamples,
    broadcastStatus,
    status,
    broadcastCurrentID,
    currentID,
    signalPlaytime,
    playtime,
    volumeGet,
    volumeSet,
    broadcastVolumeChanged
) where

--import Network.XMMS
import Network.XMMS.Constants
import Network.XMMS.Types
import Network.XMMS.Utilities

import Foreign
import Foreign.Ptr
import Foreign.C.Types
import Network.XMMS.UTF8Strings
import Foreign.ForeignPtr
import Foreign.Marshal.Alloc


--xmmsc_result_t  * 	xmmsc_playback_tickle  (xmmsc_connection_t  *c)
foreign import ccall unsafe "xmmsclient/xmmsclient.h xmmsc_playback_tickle" 
    xmmsc_playback_tickle :: Ptr C_xmmsc_connection -> IO (Ptr C_xmmsc_result)
-- |Stop decoding of current song. 
-- /Usefull to implement things like next, prev etc/
tickle :: Connection -> IO Result
tickle = wrapCallResult xmmsc_playback_tickle


--xmmsc_result_t * 	xmmsc_playback_stop (xmmsc_connection_t *c)
foreign import ccall unsafe "xmmsclient/xmmsclient.h xmmsc_playback_stop" 
    xmmsc_playback_stop :: Ptr C_xmmsc_connection -> IO (Ptr C_xmmsc_result)
-- |Stops the current playback. 
stop :: Connection -> IO Result
stop = wrapCallResult xmmsc_playback_stop


--xmmsc_result_t * 	xmmsc_playback_pause (xmmsc_connection_t *c)
foreign import ccall unsafe "xmmsclient/xmmsclient.h xmmsc_playback_pause" 
    xmmsc_playback_pause :: Ptr C_xmmsc_connection -> IO (Ptr C_xmmsc_result)
-- |Pause the current playback, will tell the output to not read nor write. 
pause :: Connection -> IO Result
pause = wrapCallResult xmmsc_playback_pause

 
--xmmsc_result_t * xmmsc_playback_start  (xmmsc_connection_t *c)
foreign import ccall unsafe "xmmsclient/xmmsclient.h xmmsc_playback_start" 
    xmmsc_playback_start :: Ptr C_xmmsc_connection -> IO (Ptr C_xmmsc_result)
-- |Starts playback if server is idle.
start :: Connection -> IO Result
start = wrapCallResult xmmsc_playback_start 	


--xmmsc_result_t * 	xmmsc_playback_seek_ms_abs (xmmsc_connection_t *c, int milliseconds)
foreign import ccall unsafe "xmmsclient/xmmsclient.h xmmsc_playback_seek_ms_abs" 
    xmmsc_playback_seek_ms_abs :: Ptr C_xmmsc_connection -> CInt -> IO (Ptr C_xmmsc_result)
-- |Seek to an absolute time in the current playback.
seekmsAbs :: Connection -> Int -> IO Result
seekmsAbs = flip $ wrapCallResult.(flip xmmsc_playback_seek_ms_abs).fromIntegral


--xmmsc_result_t * 	xmmsc_playback_seek_ms_rel (xmmsc_connection_t *c, int milliseconds)
foreign import ccall unsafe "xmmsclient/xmmsclient.h xmmsc_playback_seek_ms_rel" 
    xmmsc_playback_seek_ms_rel :: Ptr C_xmmsc_connection -> CInt -> IO (Ptr C_xmmsc_result)
-- |Seek to a time relative to the current position in the current playback. 	
seekmsRel :: Connection -> Int -> IO Result
seekmsRel = flip $ wrapCallResult.(flip xmmsc_playback_seek_ms_rel).fromIntegral


--xmmsc_result_t  * xmmsc_playback_seek_ms  (xmmsc_connection_t  *c, int milliseconds, xmms_playback_seek_mode_t  whence)
foreign import ccall unsafe "xmmsclient/xmmsclient.h xmmsc_playback_seek_ms" 
    xmmsc_playback_seek_ms :: Ptr C_xmmsc_connection -> CInt -> CInt -> IO (Ptr C_xmmsc_result)
-- |Seek to a position given in milliseconds in the current playback. 
seekms :: Connection -> Int -> SeekMode -> IO Result
seekms connection ms mode = 
    wrapCallResult (\c -> xmmsc_playback_seek_ms c 
                                (fromIntegral ms) 
                                (fromSeekMode mode)) connection


--xmmsc_result_t * 	xmmsc_playback_seek_samples_abs (xmmsc_connection_t *c, int samples)
foreign import ccall unsafe "xmmsclient/xmmsclient.h xmmsc_playback_seek_samples_abs" 
    xmmsc_playback_seek_samples_abs :: Ptr C_xmmsc_connection -> CInt -> IO (Ptr C_xmmsc_result)
-- |Seek to a absoulte number of samples in the current playback.
seekSamplesAbs :: Connection -> Int -> IO Result
seekSamplesAbs = flip $ wrapCallResult.(flip xmmsc_playback_seek_samples_abs).fromIntegral
 	

--xmmsc_result_t * 	xmmsc_playback_seek_samples_rel (xmmsc_connection_t *c, int samples)
foreign import ccall unsafe "xmmsclient/xmmsclient.h xmmsc_playback_seek_samples_rel" 
    xmmsc_playback_seek_samples_rel :: Ptr C_xmmsc_connection -> CInt -> IO (Ptr C_xmmsc_result)
-- |Seek to a number of samples relative to the current position in the current playback.
seekSamplesRel :: Connection -> Int -> IO Result
seekSamplesRel = flip $ wrapCallResult.(flip xmmsc_playback_seek_samples_rel).fromIntegral


--xmmsc_result_t  * xmmsc_playback_seek_samples  (xmmsc_connection_t  *c, int samples, xmms_playback_seek_mode_t  whence)
foreign import ccall unsafe "xmmsclient/xmmsclient.h xmmsc_playback_seek_samples" 
    xmmsc_playback_seek_samples :: Ptr C_xmmsc_connection -> CInt -> CInt -> IO (Ptr C_xmmsc_result)
-- |Seek to a position given in samples in the current playback. 
seekSamples :: Connection -> Int -> SeekMode -> IO Result
seekSamples connection samples mode = 
    wrapCallResult (\c -> xmmsc_playback_seek_samples c 
                                (fromIntegral samples) 
                                (fromSeekMode mode)) connection
    

--xmmsc_result_t * 	xmmsc_broadcast_playback_status (xmmsc_connection_t *c)
foreign import ccall unsafe "xmmsclient/xmmsclient.h xmmsc_broadcast_playback_status" 
    xmmsc_broadcast_playback_status :: Ptr C_xmmsc_connection -> IO (Ptr C_xmmsc_result)
-- |Requests the playback status broadcast.
broadcastStatus :: Connection -> IO Result
broadcastStatus = wrapCallResult xmmsc_broadcast_playback_status
 	

--xmmsc_result_t * 	xmmsc_playback_status (xmmsc_connection_t *c)
foreign import ccall unsafe "xmmsclient/xmmsclient.h xmmsc_playback_status" 
    xmmsc_playback_status :: Ptr C_xmmsc_connection -> IO (Ptr C_xmmsc_result)
-- |Make server emit the playback status.
status :: Connection -> IO Result
status = wrapCallResult xmmsc_playback_status


--xmmsc_result_t * 	xmmsc_broadcast_playback_current_id (xmmsc_connection_t *c)
foreign import ccall unsafe "xmmsclient/xmmsclient.h xmmsc_broadcast_playback_current_id" 
    xmmsc_broadcast_playback_current_id :: Ptr C_xmmsc_connection -> IO (Ptr C_xmmsc_result)
-- |Request the current id broadcast. 	
broadcastCurrentID :: Connection -> IO Result
broadcastCurrentID = wrapCallResult xmmsc_broadcast_playback_current_id


--xmmsc_result_t * xmmsc_playback_current_id  (xmmsc_connection_t *c)
foreign import ccall unsafe "xmmsclient/xmmsclient.h xmmsc_playback_current_id" 
    xmmsc_playback_current_id :: Ptr C_xmmsc_connection -> IO (Ptr C_xmmsc_result)
-- |Make server emit the current id.
currentID :: Connection -> IO Result
currentID = wrapCallResult xmmsc_playback_current_id


--xmmsc_result_t * 	xmmsc_signal_playback_playtime (xmmsc_connection_t *c)
foreign import ccall unsafe "xmmsclient/xmmsclient.h xmmsc_signal_playback_playtime" 
    xmmsc_signal_playback_playtime :: Ptr C_xmmsc_connection -> IO (Ptr C_xmmsc_result)
-- |Request the playback_playtime signal.
signalPlaytime :: Connection -> IO Result
signalPlaytime = wrapCallResult xmmsc_signal_playback_playtime


--xmmsc_result_t * 	xmmsc_playback_playtime (xmmsc_connection_t *c)
foreign import ccall unsafe "xmmsclient/xmmsclient.h xmmsc_playback_playtime" 
    xmmsc_playback_playtime :: Ptr C_xmmsc_connection -> IO (Ptr C_xmmsc_result)
-- |Make server emit the current playtime.
playtime :: Connection -> IO Result
playtime = wrapCallResult xmmsc_playback_playtime


--xmmsc_result_t * 	xmmsc_playback_volume_set (xmmsc_connection_t *c, const char *channel, int volume)
foreign import ccall unsafe "xmmsclient/xmmsclient.h xmmsc_playback_volume_set" 
    xmmsc_playback_volume_set :: Ptr C_xmmsc_connection -> CString -> CInt -> IO (Ptr C_xmmsc_result)
volumeSet :: Connection -> String -> Int -> IO Result
volumeSet connection name volume = do
    c_name <- newCString name
    res <- wrapCallResult (\c -> xmmsc_playback_volume_set c 
                                    c_name 
                                    (fromIntegral volume)) connection
    free c_name
    return res


--xmmsc_result_t * 	xmmsc_playback_volume_get (xmmsc_connection_t *c)
foreign import ccall unsafe "xmmsclient/xmmsclient.h xmmsc_playback_volume_get" 
    xmmsc_playback_volume_get :: Ptr C_xmmsc_connection -> IO (Ptr C_xmmsc_result)
volumeGet :: Connection -> IO Result
volumeGet = wrapCallResult xmmsc_playback_volume_get


--xmmsc_result_t * 	xmmsc_broadcast_playback_volume_changed (xmmsc_connection_t *c)
foreign import ccall unsafe "xmmsclient/xmmsclient.h xmmsc_broadcast_playback_volume_changed" 
    xmmsc_broadcast_playback_volume_changed :: Ptr C_xmmsc_connection -> IO (Ptr C_xmmsc_result)
broadcastVolumeChanged :: Connection -> IO Result
broadcastVolumeChanged = wrapCallResult xmmsc_broadcast_playback_volume_changed