mIRC Socket Client for AMIP
by Serge Baranov (CrazyCoder)

Purpose:
==========================
Allows to communitcate with AMIP using socket transport instead of
buggy DDE transport.

As a side feature you can run AMIP and mIRC on different machines
and control your player from mIRC remotely among with getting the
now playing song info from the remote machine with running AMIP like:

//echo -s now playing: $dll(ac,meval,var_name)


Installation:
==========================
Copy ac.dll, ac.irc and ac.ini files into the mIRC directory
(<SYSDRIVE>:\Users\<USER>\AppData\Roaming\mIRC on Vista),
run mIRC and type:

/load -rs ac.irc

This will make ac.irc script to load automatically when you start
your mIRC. ac.irc script will load the ac.dll in memory and will
initialize the server part which accepts connections from AMIP.

You should see the following in the mIRC Status:

*** AMIP Socket Client initialized
*** AMIP Socket Server started


Configuration:
==========================
<IMPORTANT>
  
  In the AMIP Configurator | IRC Integration page change Transport to
  Socket, press the appeared Connection Settings... button and check that
  host and port configured there are equal to srchost and srcport in ac.ini.
  If you don't have AMIP Configurator, get it at http://amip.tools-for.net.
  
  AMIP Client _accepts_ AMIP plugin connections on srchost:srcport.
  
</IMPORTANT>

By default the Client will _send_ commands to AMIP running on host
127.0.0.1 and port 60333. This can be adjusted in ac.ini file
(host and port properties).

AMIP must be configured to accept connections on the same interface
and port. Please see AMIP Configurator | Remote/API page.

If you don't want the AMIP Client to print messages into the mIRC
Status window when starting your mIRC, set verbose to 0 in ac.ini.


Testing:
==========================
When changing song in your player AMIP will send the string configured
in the AMIP Preset to mIRC via ac.dll.

To change the format of the message please see AMIP Configurator | Presets.

The ac.dll provides the following functions:

mexec -- executes AMIP command
meval -- evaluates AMIP variable or command and returns the string result

command has the same format as /dde in AMIP help file.

Old DDE command:
/dde mplug announce

New DLL command:
/dll ac mexec announce

Basically, just replace "/dde mplug" with "/dll ac mexec".

Old $dde command:
//echo -s song title: $dde(mplug,var_name)

New $dll command:
//echo -s song title: $dll(ac,meval,var_name)

You may want to check the result returned by meval and mexec,
if something goes wrong, the result string may be:

S_INVALID       - no server running or previous calls failed
S_CONEXCEPTION  - connection exception
S_EXCEPTION     - some other exception
S_NOCLIENT      - client is NULL

Otherwise, for mexec the string is S_OK, for meval the string
will contain result of the evaluation.

There is also a special command to ping the server:
$dll(ac,mpingServer,host port timeout)
returns 1 if AMIP server is available, 0 otherwise.
Example: //echo -s ping: $dll(ac,mpingServer,127.0.0.1 60333 1000)


Configuring from mIRC:
==========================
Prefix the below commands with
/dll ac

msetDestPort N      - sets AMIP plugin port
msetDestHost host   - sets AMIP plugin host
msetTimeout N       - sets connection timeout

msetSrcPort N       - sets Client source port
msetSrcHost host    - sets Client bind address (0.0.0.0 for all interfaces)

After configuring AMIP Client be sure to call

mrehash             - reloads config and restarts services with new settings


Using Callbacks and Listeners
==========================
You can ask AMIP to notify you about different events via a function alias you
define in mIRC. It's the best way to configure everything to work automatically,
so that you don't have to go into AMIP settings and switch transport to sockets.

How it works:
1. You say AMIP that you want to get notifications about events or messages on 
   specified host and port using this function:
   
   maddEventListener host port timeout flags fail_count

   host       - the host of the server where you want to get events (srchost)
   port       - port number where client's server is running (srcport)
   timeout    - connection timeout
   flags      - sum of possible event codes that you want to receive from AMIP (decimal)
                Possible events and codes:
                  AC_EVT_PLAY          0x0001   - playback start
                  AC_EVT_PAUSE         0x0002   - playback pause
                  AC_EVT_STOP          0x0004   - playback stop
                  AC_EVT_START         0x0008   - player start
                  AC_EVT_EXIT          0x0010   - player exit
                  AC_EVT_TIMER         0x0020   - AMIP timer (default is 1000ms)
                  AC_EVT_MSG           0x0040   - get messages from AMIP!!!
                  AC_EVT_CHANGE        0x0080   - song change
                  AC_EVT_PLCHANGE      0x0100   - playlist change
                  AC_EVT_PLREADY       0x0200   - playlist sync complete

                Codes are given in hex, you must convert them to dec and sum up for
                multiple events. Example: you want to listen for playback start, playback
                stop and song change events, (0x0001 + 0x0004 + 0x0080) = 0x85 = 133.
                So for these 3 event types you pass 133 to this function as flags param.
                
   fail_count - AMIP will automatically remove your listener if it fails to connect
                more times than specified by this value. It's recommended to use
                1 for stable localhost connections, 5-50 for slow modem connections.
                It's also possible to set up infinite number, so that listener will
                never be removed, use with care and always remove such listener when
                you no longer need it (see below). For infinite value specify 4294967295.
                
   Example: /dll ac maddEventListener 127.0.0.1 60334 1000 159 1

   If you register listener for AC_EVT_MSG event, you get all the strings from AMIP, such as song
   information and some other messages as if mIRC integration was enabled in AMIP with automatic
   announcement. Read below how you can control and handle such notifications in your script.

   If you want to change event list you want to get, call the same function with different flags
   parameter, old listener will be removed and new one will be added. Listeners are identified by
   host:port.

   Don't worry if the user has already configured socket transport manually, MSG event is delivered only
   once per host:port, so there will be no duplicate messages if both transport and listener are set.
   However, if automatic announcement is enabled and transport is FileMapping or DDE, user can get
   duplicate messages if you don't catch them by your alias.
   Logic is as follows: message event is always delivered, message via socket transport is delivered
   only in case socket transport is enabled and there is no already event listener for the configured
   host and port. If transport is FileMapping or DDE, messages are also delivered via the specified 
   transport. Of course, it's not a problem if AMIP and mIRC are running on different hosts.

2. To receive notifications you must also define the name of alias which will get event codes as
   a parameter.

   msetEvtAlias alias

   Example: /dll ac msetEvtAlias /echo -s event code:
   this sets alias to /echo -s event code:
   and you can see in status AMIP event codes, like:

   event code: 2
   event code: 1
   event code: 128

   In your real alias you would do something useful depending on the event code.

3. If listener for AC_EVT_MSG event is registered, all the messages will be delivered and executed in
   mIRC. If you want to control them and display only when some option is set, or filter some messages,
   you can define alias which will get messages from AMIP:

   msetMsgAlias alias

   Example: /dll ac msetMsgAlias /echo -s message:
   this will just print all the raw AMIP messages to status.

4. When you no longer need the listener (when mIRC exists) it's highly recommended that you remove
   your listener:

   mremoveEventListener host port

   Example: /dll ac mremoveEventListener 127.0.0.1 60334
   removes listener set in example from section 1.

Please note that AMIP stores listeners even between restarts in its configuration file.


More functions
==========================
load    - just a stub you can use to make mIRC load the ac.dll in memory and init
          stuff, however, when called not from mIRC, but from another client which
          is compatible with mIRC dlls, this will initialize ac.dll server and client parts
          (useful for Klient). mIRC will call it automatically when any other function is being
          invoked, so you may need to use it only on mIRC start event. ac.irc script does it, so
          that ac.dll starts the server before AMIP sends anything to mIRC.

unload  - uninitializes ac.dll, for mIRC does almost the same as '/dll -u ac', for other clients
          (such as Klient), you need to call it on client exit (don't call it from mIRC, since mIRC
          does it automatically).
          
version - returns a string containing dll version, for example "1.0".

mserverstarted      - these functions evaluate to 1 when server started up fine and client
mclientinitialized    has been initialized correctly (respectively) and to 0 otherwise.

Parameters description (ac.ini):
==========================
port=60333
Port where AMIP Server is running

host=127.0.0.1
Host where AMIP Server is running

timeout=1000
Timeout for Client connections

srcport=60334
Port where Client Service accepting info from AMIP is running

srchost=127.0.0.1
Bind interface for Client Service, set to 0.0.0.0 to accept connetions
from AMIP running on the remote machine, otherwise only connections
from localhost will be accepted

disablesec=5
If client can't connect to AMIP, don't try to connect 5 seconds

disablecount=1
Disable connections if failed 1 or more times

verbose=1
Print information to mIRC regarding client state


Feedback:
==========================
E-Mail:   Serge Baranov <coder[at]tools-for[dot]net> *
IRC:      irc.freenode.net #amip (nick: [Serge])
ICQ:      12467890
AIM:      SergeJetBrains 
URL:      http://amip.tools-for.net 
Skype:    crazycoder
Jabber:   commando@jabber.ru
Yahoo:    sergecoder
MSN:      serge[at]jetbrains[dot]com *

* - replace [at] with @ and [dot] with .
