//===========================================================================//
//
//  $Workfile: flixpub_main.js$
//  $Revision: 8$
//  $DateUTC: 2007-07-02 19:40:30Z$
//
//===========================================================================//


if (typeof(fp) == 'undefined') {
    fp = new Object;
}

if (typeof(fp.util) == 'undefined') {
    fp.util = new Object;
}

fp.util.fms_settings = 
function
(
    bool_enable,
    str_server, 
    str_application, 
    str_stream, 
    bool_ignore_error, 
    bool_write_file, 
    num_auth_mode,
    str_username,
    str_password,
    num_cap_latency,
    num_aud_buf_ms,
    num_fms_buf_ms
)
{
    if (bool_enable == null|| str_server == null || str_application == null || str_stream == null)
        throw("fms_settings: server, application, and stream are required parameters.");
        
    this.enable = bool_enable;
    this.server = str_server;
    this.app = str_application;
    this.stream = str_stream;
    
    // optional params
    this.ignore_error = bool_ignore_error == null ? bool_ignore_error : false;
    this.write_output_file = bool_write_file == null ? bool_write_file : true;
    this.auth_mode = num_auth_mode ? num_auth_mode : 0;
    this.username = str_username;
    this.password = str_password;
    this.max_capture_latency = num_cap_latency == null ? -1 : num_cap_latency;
    this.audio_capture_buffer_time = num_aud_buf_ms == null ? -1 : num_aud_buf_ms;
    this.fms_buffer_time = num_fms_buf_ms == null ? -1 : num_fms_buf_ms;
}

fp.util.volume = function() { this.volume = 50; }

fp.util.volume.prototype = {
    decrease: function(pub, step) {

        try {
            this.volume = pub.AudioCaptureVolume;
        } catch(e) {
            debug_str("fp.util.volume::decrease: volume read failed e=" + e);
        }

        this.volume -= step;

        if (this.volume < 0) this.volume = 0;

        try {
            pub.AudioCaptureVolume = this.volume;
        } catch (e) {
            debug_str("fp.util.volume::decrease: volume write failed e=" + e);
        }

        return this.volume;
    },
    
    increase: function(pub, step) {

        try {
            this.volume = pub.AudioCaptureVolume;
        } catch(e) {
            debug_str("fp.util.volume::increase: volume read failed e=" + e);
        }

        this.volume += step;

        if (this.volume > 100) this.volume = 100;

        try {
            pub.AudioCaptureVolume = this.volume;
        } catch (e) {
            debug_str("fp.util.volume::increase: volume write failed e=" + e);
        }

        return this.volume;
    }
};

var fp_volume = new fp.util.volume;


//===========================================================================//
// Script Globals
// Browser Detection Globals:
var isIE  = (navigator.appVersion.indexOf("MSIE") != -1) ? true : false;
var isWin = (navigator.appVersion.toLowerCase().indexOf("win") != -1) ? true : false;
var isOpera = (navigator.userAgent.indexOf("Opera") != -1) ? true : false;
var isMac = (navigator.userAgent.indexOf("Mac") != -1) ? true : false;
var isFirefox = (navigator.userAgent.toLowerCase().indexOf("firefox") != -1) ? true : false;
var isSafari = (navigator.userAgent.indexOf("Safari") != -1) ? true : false;
var firefox_needs_update = false;
var isMacSafari = isMac && isSafari;
var isMacFirefox = isMac && isFirefox;

// make sure firefox is >= 1.5:
if (isWin && isFirefox) {
    var rvs = "1.5.0.0";
    var rv = fp_version_to_float(rvs);
    var temp = navigator.userAgent.split("Firefox/");
    var ver = fp_version_to_float(temp[1]);
    if (ver < rv) firefox_needs_update = true;
}


// var for holding publisher object
var on2pub;

// setTimeout is used in functions handling UI status, timeout_delay
// is passed to all setTimeout calls:
var timeout_delay = 100;

//===========================================================================//
// function fp_init()
//  If firefox/mozilla compat:
//     - do plug-in detection: if the plug-in not present or needs update,
//       false is returned and caller should trigger plug-in install
//  Calls fp_load() to retrieve the plug-in interface object.
function fp_init() {

    if (!isIE && isWin) {
        if (!fp_check_for_netscape_plugin()) {
            // plugin not present, install it:
            fp_install_xpi_plugin(xpi_name, xpi_source);
            return false;
        }       
    } else if (isMacSafari) {
        // check for the Safari Mac plug-in
    	if (!fp_check_for_mac_safari_plugin()) {
    	    alert('The plugIn is out of date or not installed, please click OK '
                  + 'and follow the instructions on the page.');
    	}
    }

    try {
        fp_load();
    } catch(e) {
        return false;
    }
	
    return true;
}

//===========================================================================//
function fp_check_for_mac_safari_plugin()
{
    var found = false;

    if (fp_mac_browser_plugins_detected())
    	found = fp_mac_safari_plugin_detected(macsafari_plugin_name); 

    return found;
}

//===========================================================================//
function fp_mac_browser_plugins_detected() 
{
    var browser_has_plugins = false;

    if(navigator.plugins && navigator.plugins.length > 0)
        browser_has_plugins = true;

    return browser_has_plugins;
}

//===========================================================================//
function fp_mac_safari_plugin_detected(plugin_name) 
{
    var pluginFound = false;
    
	var pluginsArrayLength = navigator.plugins.length;
    var i;

	// for each plugin in Safari's plugIn array...
	for (i = 0; i < pluginsArrayLength; i++) 
	{
        var found = false;
        var this_plugin = navigator.plugins[i];

        if (this_plugin.name.indexOf(plugin_name) != -1) {
            found = true;
        }
        
        if (found == true) {
            // check the version 
            var installed_version = fp_get_plugin_version_string(this_plugin);

            if (installed_version.length > 1) {
                pluginFound = !Boolean(fp_ver_compare(macsafari_version.split('.'), 
                                       installed_version.split('.')));
            }

            break;
        }
    }

    return pluginFound;
}

//===========================================================================//
// function fp_load()
//  assigns plug-in interface object to on2pub global
function fp_load() {
    if (isIE && isWin && !isOpera)
        on2pub = document.flixe;
    else if (isWin && !isOpera) {
        on2pub = get_ns_plugin();
    }
    else if (isMacSafari) {
        on2pub = document.embeds["flixe"];
    }	
}


//===========================================================================//
// look up mimetype_str in the navigator.mimetypes array
function fp_find_plugin(mimetype_str) {
    var plugin = navigator.mimeTypes[mimetype_str];
    return plugin;
}


//===========================================================================//
// return the version string from the description of the plugin passed in
function fp_get_plugin_version_string(plugin) {
    if (plugin) 
        return plugin.description.substring(plugin.description.lastIndexOf("v")+1);
    else
        return "0.0.0.1";
}


//===========================================================================//
function fp_check_for_netscape_plugin() {
    // make sure the mime type is usable:
    if (np_mime_type == "" || np_mime_type.indexOf("application/x-") == -1)
        return false;

    // get the handler
    var mimetype_handler = fp_find_plugin(np_mime_type);

    // get the plugin
    var plugin;

    try {
    plugin = mimetype_handler.enabledPlugin;
    } catch (e) {
        return false;
    }

    var installed_version = "0.0.0.0";

    if (plugin) {
        try {
            installed_version = fp_get_plugin_version_string(plugin);
        } catch (e) {};
    }

    var array_installed_version = installed_version.split(".");
    var array_required_version = xpi_version.split(".");

    var fp_needs_update = fp_ver_compare(array_required_version, array_installed_version);

    if (fp_needs_update)
        return false;

    return true;
}


//===========================================================================//
function fp_install_xpi_plugin(name, url)
{
    var xpi = new Object();
    xpi[name] = url;
    site_authorized = InstallTrigger.install(xpi);
    
    if (!site_authorized) {
        // show an image instructing users how to authorize installation of 
        // add-ons for the current site
        document.getElementById('div_plugin_holder').innerHTML = flixpub_firefox_auth_markup;
    }
}

//===========================================================================//
// returns true if "new" version is greater than "old" version
function fp_ver_compare(ver_array_new, ver_array_old) {
    if (ver_array_new.length < 3 || ver_array_old.length < 3)
        return true;

    var i;
    for (i = 0; i < 4; i++) {
        // Ensure version component at array index is a number
        // A compare of "9" > "10" returns true if you leave the components
        // as type string.
        // A compare of Number("9") > Number("10") returns false 
        ver_array_old[i] = Number(ver_array_old[i]);
        ver_array_new[i] = Number(ver_array_new[i]);

        // Compare version component 
        if (ver_array_new[i] > ver_array_old[i]) {
            // version contained within new array is higher
            return true;
        } else if (ver_array_old[i] > ver_array_new[i]) {
            // version contained within old array is higher
            return false;
        }
        // fall through if version components are equal
    }

    return false;
}


//===========================================================================//
// function fp_version_to_float()
// Convert a dotted version string to a floating point number:
// 1.1          => 101.0000
// 1.2.0.0      => 102.0000
// 1.2.0.1      => 102.0001
// 1.2.0.2      => 102.0002
// 1.2.0.3      => 102.0003
// 1.2.0.4      => 102.0004
// 1.2.0.5      => 102.0005
// 1.3.0.0      => 103.0000
// 2.0.0.0      => 200.0000
// 2.0.0.1      => 200.0001
// 2.0.0.2      => 200.0002
// 2.0.0.3      => 200.0003
// 2.0.0.4      => 200.0004
// 2.0.1.0      => 200.0100
// 2.0.1.1      => 200.0101
// 2.0.1.2      => 200.0102
function fp_version_to_float(string) {
    var vf = 0.0;

    try {
        var temp = string.split(".");
        var s_chief = temp[0];

        var s_major;

        try {
            s_major = temp[1];
        } catch (e) {
            s_major = "0";
        }

        var s_minor;

        try {
            s_minor = temp[2];
        } catch (e) {
            s_minor = "0";
        }

        var s_patch;
        try {
            s_patch = temp[3];
        } catch (e) {
            s_patch = "0";
        }

        var vf_str = s_chief
            + ((s_major >= 10) ? s_major : "0" + s_major)
            + "."
            + ((s_minor >= 10) ? s_minor : "0" + s_minor)
            + ((s_patch >= 10) ? s_patch : "0" + s_patch);

        vf = parseFloat(vf_str);
    } catch (e) {};

    return vf;
}


//===========================================================================//
// function fp_state_to_str()
//  Converts the current publisher state value to its corresponding string
//  representation, and returns it.
function fp_state_to_str(pub)
{
    switch(pub.State)
    {
    case  /* FS_PLAY_I */ 1:
    case  /* FS_PLAY_O */ 3:
        return "Playing";

    case  /* FS_PAUSE_I */ 2:
    case  /* FS_PAUSE_O */ 4:
    case  /* FS_PAUSE_C */ 6:
    case  /* FS_PAUSE_E */ 10:
        return "Paused";

    case  /* FS_CAPTURE */ 5:
        return "Capturing";

    case  /* FS_ENCODE */ 7:
        return "Encoding";

    case  /* FS_UPLOAD */ 8:
        return "Uploading";

    case  /* FS_PREVIEW */ 9:
        return "Previewing";

    case  /* FS_STOP */ 0:
    default:
        return "Ready";
    }
}

//===========================================================================//
// function fp_show_error(pub, error)
//  Converts error value to a readable error message and displays it to
//  the user via a call to pub_alert().
function fp_show_error(pub, error) {
    switch(error) {
        case FE_DIRECTSHOW:
            pub_alert("Your computer is missing a codec, or direct show "
                + "is not present on your computer.");
            break;
        case FE_ENCODER_V:
            pub_alert("An error occurred while setting up the video "
                + "encoder.");
            break;
        case FE_MUX:
            pub_alert("An error occurred while setting up the FLV writing "
                + "filter.");
            break;
        case FE_CAPTURE_V:
            pub_alert("An error occurred while setting up video capture.");
            break;
        case FE_CAPTURE_A:
            pub_alert("An error occurred while setting up audio capture.");
            break;
        case FE_RESAMPLE:
            pub_alert("An error occurred while setting up resampling of "
                + "the audio or video input.");
            break;
        case FE_ENCODER_A:
            pub_alert("An error occurred while setting up the audio encoder.");
            break;
        case FE_CAPTURE_DV:
            pub_alert("An error occurred while setting up DV A/V capture. "
                + "There is no DV capture \n device installed on your computer, "
                + "or the DV device is not installed and working\n properly.");
            break;
        case FE_RENDER:
            pub_alert("An error occurred while setting up video display.");
            break;
        case FE_QT:
            pub_alert("An error occurred while the publisher plug-in was "
                + "working with your QuickTime file.");
            break;
        case FE_FILE:
            pub_alert("An error occurred while the publisher plug-in was "
                + "working with your file.\n"
                + "Is it a media file? Are the necessary codecs installed?");
            break;
        case FE_RESIZE:
            pub_alert("A video resizing error occurred..");
            break;
        case FE_ASF:
            pub_alert("An error occurred while the publisher plug-in was "
                + "working with your Windows Media file.");
            break;
        case FE_SEEK:
            pub_alert("An error occurred in the publisher plug-in while "
                + "a seek operation was in progress.");
            break;
        case FE_LOGIN:
            pub_alert("The publisher plug-in could not log in to the "
                + "upload site.");
            break;
        case FE_TRANSFER_FAILED:
            pub_alert("File upload failed.");
            break;
        case FE_NO_CAPTURE_DEVICE:
            pub_alert("Capture setup failed because no devices were found.");
            break;
        case FE_IN_USE:
            pub_alert("Cannot change capture device while capture is in progress.");
            break;
        case FE_FILE_CANNOT_SEEK:
            pub_alert("The current file does not allow seeking.");
            break;
        case FE_METER_A:
            pub_alert("There was an error while setting up the audio meter.");
            break;
        case FE_UNAVAILABLE:
            pub_alert("The page you are viewing attempted to use an unavailable "
                + "publisher plug-in feature.");
            break;
        case FE_FMS_CONNECTION:
            pub_alert("The publisher plug-in is experiencing problems connecting to "
                + "the Flash Media Server.");
            break;
        case FE_RUN_FAILED:
            pub_alert("A problem was encountered by the publisher plug-in.  It is "
                + "unable to start the last requested operation.");
            break;
        case FE_WRONG_STATE:
            pub_alert("The page you are viewing experienced attempted to use a "
                + "publisher plug-in feature that is not valid given the current "
                + "context.");
            break;
        case FE_PROTECTED:
            pub_alert("The publisher plug-in does not support playback or "
                + "transcode of DRM protected files.");
        case FE_FMS_AUTH_FAILED:
            pub_alert("The publisher plug-in could not authentication the "
                + "connection to FMS.");
        case FE_TRANSFER_ABORTED:
            pub_alert("The publisher plug-in aborted the upload.");
        case FE_READ_FAILED:
            pub_alert("The publisher plug-in couldn't read the file.");
        case FE_FMS_MONITOR_FAIL:
            pub_alert("The publisher plug-in couldn't start the FMS "
             + " connection monitor.");
            break;
    }
}


//===========================================================================//
// function pub_alert( msg )
//  Errors are displayed through this function, making it easy to display them
//  using something more friendly than throwing up an alert box, if desired.
function pub_alert( msg )
{
    alert(msg);
}


//===========================================================================//
function fp_get_date_as_str() {
    var t = new Date();

    var month = (1 + t.getMonth());
    var date = t.getDate();
    var hour = t.getHours();
    var minute = t.getMinutes();
    var second = t.getSeconds();

    var year_str = t.getFullYear().toString();
    var month_str = month > 9 ? month.toString() : "0" + month.toString();
    var date_str = date > 9 ? date.toString() : "0" + date.toString();
    var hour_str = hour > 9 ? hour.toString() : "0" + hour.toString();
    var minute_str = minute > 9 ? minute.toString() : "0" + minute.toString();
    var second_str = second > 9 ? second.toString() : "0" + second.toString();

    var file_date_str
        = year_str
        + "-"
        + month_str
        + "-"
        + date_str
        + "_"
        + hour_str
        + minute_str
        + "-"
        + second_str;

    return file_date_str;
}


//===========================================================================//
function fp_time_to_str(milliseconds) {
    var minutes = Math.floor(milliseconds / 60000);
    var seconds = Math.floor( (milliseconds - (60000 * minutes)) / 1000)
    if (seconds < 10) {
        seconds = '0'+seconds;
    }
    var returnStr = String(minutes) + ':' + String(seconds);
    return returnStr;
}


//===========================================================================//
function fp_time_to_minutes(milliseconds) {
    var minutes = Math.floor(milliseconds / 60000);
    return String(minutes);
}


var kUNUSED = -1;
var encode_timeout_id = kUNUSED;
var play_timeout_id = kUNUSED;
var upload_timeout_id = kUNUSED;

//===========================================================================//
// function fp_clear_timeout(tid)
//  Brief:
//   clears a timeout id returned by setTimeout
//  Returns:
//   success - true
//   failure - false
//  Args:
//   tid - time out id to clear
//  Notes:
//   returns success when asked to clear a tid == kUNUSED
//===========================================================================//
function fp_clear_timeout(tid) {
    try {
        if (tid != kUNUSED) clearTimeout(tid);
    } catch (e) {
        return false;
    }

    return true;
}


//===========================================================================//
// publisher plug-in control functions
//===========================================================================//
//===========================================================================//
// function fp_load_input_file()
//  Brief:
//   checks input file, used in the handler for the publisher's filesDropped
//   event
//  Returns:
//   success - true
//   failure - false
//  Args:
//   none
//  Notes:
//   none
//===========================================================================//
function fp_load_input_file() {
    var result = FE_SUCCESS;
    // validate the file
    try {
        on2pub.checkInputFile();
        result = on2pub.LastError;
    } catch (e) {
        // the publisher wasn't able to handle the input file
        result = FE_FILE;
    }
    return result;
}


//===========================================================================//
// function fp_set_bg_img(img_name)
//  Brief:
//   sets publisher plug-in background image to img_name
//  Args:
//   img_name - image file name
//  Notes:
//   Uses image_location from required_param.js with img_name to generate
//   complete URL.
//===========================================================================//
function fp_set_bg_img(img_name) {
    var result = false;
    try {
        img_url = image_location + img_name;
        on2pub.BGImageURL = img_url;
        result = true;
    } catch (e) {};

    return result;
}


//===========================================================================//
// function fp_start_preview()
//  Brief:
//   starts capture preview of currently selected devices
//  Args:
//   none
//  Returns:
//   success - true
//   failure - false
//  Notes:
//   - calls fp_stop()
//   - Desired devices must be set first.
//===========================================================================//
function fp_start_preview() {
    try {
        on2pub.startCapturePreview();
    } catch (e) {
        return false;
    }
    return true;
}


//===========================================================================//
// function fp_stop_preview()
//  Brief:
//   stops capture preview
//  Args:
//   none
//  Returns:
//   success - true
//   failure - false
//  Notes:
//   none
//===========================================================================//
function fp_stop_preview() {
    try {
        on2pub.stopCapturePreview();
    } catch (e) {
        return false;
    }
    return true;
}


//===========================================================================//
// function fp_start_capture()
//  Brief:
//   starts capture using currently selected devices
//  Args:
//   none
//  Returns:
//   success - true
//   failure - false
//  Notes:
//   - calls fp_stop()
//   - Desired devices must be set first.
//===========================================================================//
function fp_start_capture() {
    try {
        on2pub.startCapture();
    } catch (e) {
        return false;
    }
    return true;
}


//===========================================================================//
// function fp_stop_preview()
//  Brief:
//   stops capture
//  Args:
//   none
//  Returns:
//   success - true
//   failure - false
//  Notes:
//   none
//===========================================================================//
function fp_stop_capture() {
    try {
        on2pub.stopCapture();
    } catch (e) {
        return false;
    }
    return true;
}


//===========================================================================//
// function fp_start_transcode()
//  Brief:
//   starts transcoding the input file
//  Args:
//   none
//  Returns:
//   success - true
//   failure - false
//===========================================================================//
function fp_start_transcode() {
    try {
        on2pub.startFileEncode();
    } catch (e) {
        return false;
    }
    return true;
}


//===========================================================================//
// function fp_stop_transcode()
//  Brief:
//   stops transcoding
//  Args:
//   none
//  Returns:
//   success - true
//   failure - false
//  Notes:
//   none
//===========================================================================//
function fp_stop_transcode() {
    try {
        on2pub.stopFileEncode();
    } catch (e) {
        return false;
    }

    return true;
}


//===========================================================================//
// function fp_play_file(b_input)
//  Brief:
//   Plays the selected file.
//  Args:
//   b_input - true if playback of input file is desired, false otherwise
//  Returns:
//   success - true
//   failure - false
//  Notes:
//   none
//===========================================================================//
function fp_play_file(b_input) {
    try {
        if (b_input)
            on2pub.selectInputFileForPlayback();
        else
            on2pub.selectOutputFileForPlayback();

        on2pub.startPlayback();
    } catch (e) {
        return false;
    }
    return true;
}


//===========================================================================//
// function fp_stop()
//  Brief:
//   Stops plug-in activity, if any
//  Args:
//   none
//  Returns:
//   success - true
//   failure - false
//  Notes:
//   Uses publisher state to determine what to stop.
//===========================================================================//
function fp_stop() {
    try {
        var state = on2pub.State;
        if (state == FS_UPLOAD)
            on2pub.publishAbort();
        else if (is_transcoding())
            on2pub.stopFileEncode();
        else if (state == FS_PREVIEW)
            on2pub.stopCapturePreview();
        else if (is_capturing())
            on2pub.stopCapture();
        else if (is_playing())
            on2pub.stopPlayback();
    } catch (e) {
        return false;
    }

    return true;
}


//===========================================================================//
// function fp_start_upload()
//  Brief:
//   Starts uploading the output file.
//  Args:
//   none
//  Returns:
//   success - true
//   failure - false
//  Notes:
//   - calls fp_stop()
//   - calls fp_set_upload_settings()
//===========================================================================//
function fp_start_upload() {
    try {
        fp_set_upload_settings(on2pub);
        on2pub.uploadFile(on2pub.OutputFileName, upload_mode);
    } catch (e) {
        return false;
    }
    return true;
}


//===========================================================================//
// function fp_stop_upload()
//  Brief:
//   Stops upload.
//  Args:
//   none
//  Returns:
//   success - true
//   failure - false
//  Notes:
//   none
//===========================================================================//
function fp_stop_upload() {
    try {
        on2pub.publishAbort();
    } catch (e) {
        return false;
    }
    return true;
}


//===========================================================================//
function fp_show_audio_settings() {
    on2pub.show_audio_capture_settings();
}


//===========================================================================//
function fp_show_video_settings() {
    on2pub.show_video_capture_settings();
}

//===========================================================================//
function fp_set_fms_settings_obj(pub, fms_set) {
    try {
        pub.FmsEnable = fms_set.enable;
        pub.FmsServer = fms_set.server;
        pub.FmsPath = fms_set.app;
        pub.FmsName = fms_set.stream;
        
        pub.OutputFileWriteEnable = fms_set.write_output_file;
        

        if (fms_set.auth_mode > 0 && fms_set.auth_mode < 3) {
            pub.FmsAuthenticationMode = fms_set.auth_mode;
            pub.FmsUsername = fms_set.username;
            pub.FmsPassword = fms_set.password;
        }
        
        if (fms_set.max_capture_latency != -1) {
            pub.MaximumCaptureLatency = fms_set.max_capture_latency;
        }
        
        if (fms_set.audio_capture_buffer_time != -1) {
            pub.AudioCaptureBufferTime = fms_set.audio_capture_buffer_time;
        }
        
        if (fms_set.fms_buffer_time != -1) {
            pub.FmsBufferTime = fms_set.fms_buffer_time;
        }
    } catch(e) {
        throw("fp_set_fms_settings_obj(): caught e=[" + e + "]");
    }
    
    // set conf file settings
    try {
        fp_set_fms_fpconf_settings(pub);
    } catch(e) {
        throw("fp_set_fms_settings_obj(): fp_set_fms_fpconf_settings threw e=[" 
            + e + "]");
    }
}

//===========================================================================//
function fp_set_fms_settings(pub, enable, server, path, name, ignore_errs) {
    try {
        pub.FmsEnable = enable;

        if (enable) {
            pub.FmsServer = server;
            pub.FmsPath = path;
            pub.FmsName = name;
            pub.FmsIgnoreFail = ignore_errs;
        }

        fp_set_fms_fpconf_settings(pub);

    } catch (e) {
        return false;
    }
    return true;
}


//===========================================================================//
function fp_set_fms_fpconf_settings(pub)
{
    try {
        pub.FmsAuthenticationMode = flixpub_fms_auth_mode;
        
        if (flixpub_fms_auth_arg_functions.length > 0) {
            pub.resetFmsAuthArgs();
            var i;
            
            // loop through the holder array
            for (i = 0; i < flixpub_fms_auth_arg_functions.length; i++) {
                // add each function and its args
                var func = flixpub_fms_auth_arg_functions[i].get_func();

                if (func.length) {
                    // get the function's arg array 
                    var args_array = flixpub_fms_auth_arg_functions[i].get_args();
                    
                    if (args_array.length) {
                        // arg array is non-empty, send the args into the plug-in
                        var j;
                        for (j = 0; j < args_array.length; j++) {
                            pub.addFmsAuthArg(func, args_array[j]);
                        }
                    } else {
                        // empty arg array, just set the function to call
                        pub.addFmsAuthArg(func, "");
                    }
                } 
            }
        }
    } catch (e) {
        debug_str("failed setting auth params (" + e + ").");
    }

    if (flixpub_fmsmon_enable) {
        try {
        
            pub.FmsPollEnable = flixpub_fmsmon_enable;
            pub.FmsPollDelay = flixpub_fmsmon_poll_delay;
            pub.FmsPollTimeout = flixpub_fmsmon_poll_timeout;
        
            pub.setFmsPollFunction(flixpub_fmsmon_poll_func);
            pub.resetFmsPollArgs();
            
            var i;
            for (i=0; i < flixpub_fmsmon_poll_args.length; i++) {
                pub.addFmsPollArg(flixpub_fmsmon_poll_args[i]);
            }
        } catch (e) {
            debug_str("failed setting poll params (" + e + ").");
        };
    }
}

//===========================================================================//
function fp_set_fms_uid(pub, username, password) 
{
    try {
        pub.FmsUsername = username;
        pub.FmsPassword = password;
    } catch (e) {
        debug_str("failed setting fms uid");
    }
}

//===========================================================================//
// helper functions for sending settings to the publisher
//===========================================================================//
//===========================================================================//
function fp_set_audio_settings(pub, c, br) {
    try {
    	
        if (!isMacSafari) {
            if (c != -1 && fp_is_numeric(c) && c >= 0 && c <= 1) {
                pub.AudioCodecID = parseInt(c);
            } else {
                pub.AudioCodecID = flixpub_flv_audio_codec;
            }
        }

        if (br != -1 && fp_is_numeric(br) && br > 0) {
    	    if(isMacSafari)
    	    {
                if (br == 1)
        		{
        		    pub.AudioBitrate = parseInt(flixpub_flv_audio_bitrate);
        		}
        		else
        		{
        		    pub.AudioBitrate = parseInt(br);
        		}
            } 
    	    else
    	    {
                    pub.AudioBitrate = parseInt(br);
    	    }
        } else {
            pub.AudioBitrate = flixpub_flv_audio_bitrate;
        }
    } catch (e) {
        return false;
    }
    return true;
}


//===========================================================================//
// function fp_set_video_settings(pub, b_cap, br, w, h, fps, rcm, kfm, kff, cm)
//  Returns:
//   true  - Success
//   false - Failure
//  Args:
//   pub    - publisher plug-in object
//   b_cap  - true if settings are for a capture
//   w      - width, in pixels
//   h      - height, in pixels
//   fps    - frames per second
//   rcm    - rate control mode
//   kfm    - key frame mode
//   kff    - key frame frequency
//   cm     - compress mode
//===========================================================================//
function fp_set_video_settings(pub, b_cap, br, w, h, fps, rcm, kfm, kff, cm) {
    try {
        if (br != -1 && fp_is_numeric(br)) {
            var nbr = parseInt(br);
            pub.VideoBitrate = nbr;
        } else {
            pub.VideoBitrate = flixpub_flv_video_bitrate;
        }
        if (w != -1 && fp_is_numeric(w)) {
            var nw = parseInt(w);
            pub.OutputFileWidth = nw;
        } else {
            var nw;

            if (b_cap == true)
                nw = flixpub_flv_width_capture;
            else
                nw = flixpub_flv_width;

            pub.OutputFileWidth = nw;
        }
        if (h != -1 && fp_is_numeric(h)) {
            var nh = parseInt(h);
            pub.OutputFileHeight = nh;
        } else {
            var nh;

            if (b_cap == true)
                nh = flixpub_flv_height_capture;
            else
                nh = flixpub_flv_height;

            pub.OutputFileHeight = nh;
        }
        if (fps != -1 && fp_is_numeric(fps)) {
            var nf = parseFloat(fps);
            pub.OutputFileFrameRate = nf;
        } else {
            var nf;

            if (b_cap == true)
                nf = flixpub_flv_fps_capture;
            else
                nf = flixpub_flv_fps;

            pub.OutputFileFrameRate = nf;
        }

        if(!isMacSafari)
        {
            if (rcm != -1 && fp_is_numeric(rcm) && rcm >= 0 && rcm <= 1) {
                var nrcm = parseInt(rcm);
                pub.VideoBitrateControlMode = nrcm;
            } else {
                pub.VideoBitrateControlMode = flixpub_flv_video_rate_control_mode;
            }
            if (kfm != -1 && fp_is_numeric(kfm) && kfm >= 0 && kfm <= 1) {
                var nkfm = parseInt(kfm);
                pub.VideoKeyFrameMode = nkfm;
            } else {
                pub.VideoKeyFrameMode = flixpub_flv_video_keyframe_mode;
            }
            if (kff != -1 && fp_is_numeric(kff)) {
                var nkff = parseInt(kff);
                pub.VideoKeyFrameFrequency = nkff;
            } else {
                pub.VideoKeyFrameFrequency = flixpub_flv_video_keyframe_rate;
            }
            if (cm != -1 && fp_is_numeric(cm) && cm >= 0 && cm <= 2) {
                var ncm = parseInt(cm);
                pub.VideoCompressMode = ncm;
            } else {
                pub.VideoCompressMode = flixpub_flv_video_compression_mode;
            }
        }
    } catch (e) {
        return false;
    }

    return true;
}


// calculate output file dimensions
//===========================================================================//
// function fp_get_video_dimensions(b_mar, b_cap, i_w, i_h, d_w, d_h)
//  Returns:
//   Success - Array containing desired width and height
//   Failure - Array containing default width and height
//  Args:
//   pub    - publisher plug-in object
//   b_mar  - true if input aspect ratio should be preserved
//   b_cap  - true if settings are for a capture
//   i_w    - input width, in pixels
//   i_h    - input height, in pixels
//   d_w    - desired width, in pixels
//   d_h    - desired height, in pixels
//===========================================================================//
function fp_get_video_dimensions(pub, b_cap, b_mar, i_w, i_h, d_w, d_h) {
    var w = d_w, h = d_h;

    if (b_cap) {
        if (b_mar) {
            // assume 4:3
            if (w >= h) {
                var ar = 3/4;
                h = Math.round(w * ar);
            } else {
                var ar = 4/3;
                w = Math.round(h * ar);
            }
        }
    } else {
        if (b_mar) {
            if (i_h >= i_w) {
                var ar = i_w/i_h;
                w = Math.round(h * ar);
            } else {
                var ar = i_h/i_w;
                h = Math.round(w * ar);
            }
        }
    }

    return new Array(w, h);
}


//===========================================================================//
// function fp_set_upload_settings(pub)
//  Returns:
//   none
//  Args:
//   pub        - publisher plug-in object
//  Notes:
//
//===========================================================================//
function fp_set_upload_settings(pub) {
    var t = new Date();
    var upload_file_name = upload_username
        + "_"
        + String(t.getFullYear())
        + String(1+t.getMonth())
        + String(t.getDate())+String(t.getHours())
        + String(t.getMinutes())
        + String(t.getSeconds())
        + ".flv";
    t = 0;

    pub.PublishMethod = upload_mode;

    if (upload_mode == kUploadModeFtp) 
	{
        // FTP upload
        pub.FtpSubDomain       = upload_sub_domain;
        pub.FtpMode            = "P";
        pub.FtpDestinationFile = upload_path_ftp + upload_file_name;
        pub.FtpUser            = upload_username;
        pub.FtpPassword        = upload_password_ftp;
    } 
	else 
	{
        if (isMacSafari) 
		{
        
            // the Mac Publisher plug-in only implements publisher v2:
            // HTTP POST upload
            pub.HttpSubDomain      = upload_sub_domain;
            pub.HttpPath           = upload_path_http;
            pub.HttpFile           = upload_file_name;

            try {
				 fp_set_http_maps(pub, upload_mode);               
            } catch (e) {};
            
            // the username and filename vars are set here for example purposes
            // only, you can see how they're used in samples/php/upload.php
            pub.setHttpVar('username', upload_username);
            pub.setHttpVar('filename', upload_file_name);
			
        } else {
        
            // HTTP POST upload, v3 publisher
            // set the variables/headers from the conf file
            try {
                fp_set_http_maps(pub, upload_mode);
            } catch (e) {};
            
            try {
                fp_set_md5_checksum(pub, upload_mode, upload_file_name);
            } catch (e) {};
        
            try {
                // backwards compatibility: this was done prior to v3.0.1.3
                //  some implementations of the publisher rely upon this behavior...
                if (pub.getHttpFormVar("username") == "") {
                    pub.setHttpFormVar("username", upload_username);
                }
                if (pub.getHttpFormVar("filename") == "") {
                    pub.setHttpFormVar("filename", upload_file_name);
                }
            } catch (e) {};

            pub.HttpSubDomain = upload_sub_domain;
            
            if (upload_http_target_is_file == true) 
                pub.HttpPath = upload_file_name;
            else 
                pub.HttpPath = upload_path_http;
        }
    }
}


//===========================================================================//
/*
function fp_set_http_map(p, n, v, w) {
    if (n.length != v.length) return;
    var i = 0;
    var len = n.length;
    if (w == kUploadModeHttpBinPost) {
        p.resetHttpRequestHeaders();
        for (; i < len; i++) {
            p.setHttpRequestHeader(n[i],v[i]);
        }
    } else if (w == kUploadModeHttpFormPost) {
        p.resetHttpFormVars();
        for (; i < len; i++) {
            p.setHttpFormVar(n[i],v[i]);
        }
    }
}
*/

function fp_set_http_form_vars(p, n, v)
{
	if (n.length != v.length) return;
	var i = 0;
	
	if (isMacSafari)  // Mac Safari plugin only supports V2 interface
	{
		try
		{
			debug_str("calling resetHttpVars()");
			debug_str("typeof(p) = [" + typeof(p) + "]");
			//p.resetHttpVars();
			for (i=0; i < n.length; i++) 
			{
				debug_str("calling setHttpVar( '" + n[i] + "', '" + v[i] + ")");
				p.setHttpVar(n[i],v[i]);
			}
		}
		catch (e)
		{
			debug_str("fp_set_http_form_vars : exception encountered = [" + e + "]");
		}
	}
	else
	{
		debug_str("calling resetHttpFormVars()");
		p.resetHttpFormVars();
		for (i=0; i < n.length; i++) 
		{
			debug_str("calling setHttpFormVar( '" + n[i] + "', '" + v[i] + ")");
			p.setHttpFormVar(n[i],v[i]);
		}
	}
}

function fp_set_http_request_headers(p, n, v)
{
	if (n.length != v.length) return;
	var i = 0;
	debug_str("calling resetHttpRequestHeaders()");
	p.resetHttpRequestHeaders();
	for (i=0; i < n.length; i++) 
	{
		debug_str("calling setHttpRequestHeader( '" + n[i] + "', '" + v[i] + ")");
		p.setHttpRequestHeader(n[i],v[i]);
	}
}

//===========================================================================//
function fp_set_http_maps(pub, mode) {
    if (mode == kUploadModeHttpFormPost) 
	{
        fp_set_http_form_vars(pub, upload_form_var_names, upload_form_var_values);		
    }
	fp_set_http_request_headers(pub, upload_req_hdr_names, upload_req_hdr_values);	   
}


//===========================================================================//
function fp_set_md5_checksum(pub, mode) {
    if (mode == kUploadModeFtp || upload_md5_enable == false) return;
    
    var cs;
    try {
      cs = pub.getMd5Checksum(pub.OutputFileName);
    } catch (e) {};
    
    if (cs.length) {
        if (mode == kUploadModeHttpFormPost && upload_md5_form_var == true) {
            pub.setHttpFormVar(upload_md5_name, cs);
        } else {
            pub.setHttpRequestHeader(upload_md5_name, cs);
        }
    }
}

//===========================================================================//
// Flix Publisher Plug-in API wrapper
function fp_fms_enabled(pub) {
    if (isMacSafari)
        return false;
    
    return pub.FmsEnable;
}

//===========================================================================//
// Flix Publisher Plug-in API wrapper
function fp_input_file_selected(pub) {
    if (isMacSafari)
        return true;
    
    return pub.InputFileSelected;
}

//===========================================================================//
// Flix Publisher Plug-in API wrapper
function fp_output_file_selected(pub) {
    if (isMacSafari)
        return false;
    
    return pub.OutputFileSelected;
}

//===========================================================================//
// Flix Publisher Plug-in API wrapper
function fp_set_play_position(pub, pos) {
    // the Mac safari plug-in ignores the attribute write if the
    // type is incorrect.  Force pos to be of type number.
    pos = Number(pos);
    pub.PlayPosition = pos;
}

//===========================================================================//
// Flix Publisher Plug-in API wrapper
function fp_show_file_chooser(pub) {
    var failed = false;

    try {
        pub.addFile("");        
    } catch (e) {
        failed = true;
    }
    
    debug_str('fp_show_file_chooser(): pub.InputFileName='+pub.InputFileName);
    
    // temporary work around for addFile misbehavior on the Mac:
    var fname = pub.InputFileName;
    failed = (typeof(fname) == "undefined");
    
    debug_str('fp_show_file_chooser(): failed='+failed);
    
    return (failed || pub.LastError != FE_SUCCESS) ? false : true;
}

//===========================================================================//
// handler functions for updating status during encoding/playback/upload
//===========================================================================//
//===========================================================================//
// function handle_encode(b_capture)
//  Returns:
//   none
//  Notes:
//   if encode is active, calls itself via setTimeout w/timeout_delay ms
//===========================================================================//
function handle_encode() {
    // clear any previous timeout on this function:
    fp_clear_timeout(encode_timeout_id);
    encode_timeout_id = kUNUSED;

    var active = (is_encoding());
    var capture = (is_capturing());

    if (active) {
        var now = on2pub.EncodedDuration;
        var max = on2pub.MaximumDuration;

        if (capture == false)
            max = on2pub.EncodeTimeEnd - on2pub.EncodeTimeStart;

        update_encode_status(now, max);

        encode_timeout_id = setTimeout(handle_encode,timeout_delay);
    }
}


//===========================================================================//
// function handle_playback(b_input)
//  Returns:
//   none
//  Args:
//   b_input - true if playing an input file
//  Notes:
//   if playback is in progress, calls itself via setTimeout w/timeout_delay ms
//===========================================================================//
function handle_playback() {
    // clear any previous timeout on this function:
    fp_clear_timeout(play_timeout_id);
    play_timeout_id = kUNUSED;

    if (is_playing()) {    
        var now = on2pub.PlayPosition;

        var dur = fp_input_file_selected(on2pub) 
            ? on2pub.InputFileDuration : on2pub.OutputFileDuration;

        update_playback_status(now, dur);
        play_timeout_id = setTimeout(handle_playback, timeout_delay);
    }
}


//===========================================================================//
// function handle_upload(b_ftp)
//  Returns:
//   none
//  Args:
//   b_ftp - true if uploading via ftp
//  Notes:
//   if upload is in progress, calls itself via setTimeout w/timeout_delay ms
//===========================================================================//
function handle_upload() {
    // clear any previous timeout on this function:
    fp_clear_timeout(upload_timeout_id);
    upload_timeout_id = kUNUSED;

    if (on2pub.State == FS_UPLOAD) {
        var current = on2pub.UploadedBytes;
        var total = on2pub.UploadFileSize;
        update_upload_status(current, total);
    if (on2pub.UploadFileSize == 0 || on2pub.UploadedBytes < on2pub.UploadFileSize)
        setTimeout(handle_upload, timeout_delay);
    }
}




//===========================================================================//
// helper functions for determining the state of the publisher plug-in
//===========================================================================//
//===========================================================================//
// function is_capturing()
//  returns true if the publisher is capturing
function is_capturing() {
    var capturing = false;
    var state = on2pub.State;

    if (state == FS_CAPTURE ||
        state == FS_PAUSE_C)
    {
        capturing = true;
    }

    return capturing;
}
//===========================================================================//
// function is_encoding()
//  returns true if the publisher capturing or transcoding
function is_encoding() {
    var encoding = (is_capturing() || is_transcoding());
    return encoding;
}
//===========================================================================//
// function is_transcoding()
//  returns true if the publisher is transcoding a file
function is_transcoding() {
    var encoding = false;
    var state = on2pub.State;

    if (state == FS_ENCODE ||
        state == FS_PAUSE_E)
    {
        encoding = true;
    }

    return encoding;
}
//===========================================================================//
// function is_playing()
//  returns true if the publisher is in a playback state
function is_playing() {
    var playing = false;
    var state = on2pub.State;

    if (state == FS_PLAY_I ||
        state == FS_PAUSE_I ||
        state == FS_PLAY_O ||
        state == FS_PAUSE_O)
    {
        playing = true;
    }

    return playing;
}
//===========================================================================//
// function is_paused()
//  returns true if the publisher is in a pause state
function is_paused() {
    var paused = false;
    var state = on2pub.State;

    if (state == FS_PAUSE_I ||
        state == FS_PAUSE_O ||
        state == FS_PAUSE_C ||
        state == FS_PAUSE_E)
    {
        paused = true;
    }

    return paused;
}




//===========================================================================//
// functon fp_re_isInteger(str)
//  returns true if str is an integer.
function fp_re_isInteger(str) {
    var re_int = /^\d+$/;
    return re_int.test(str);
}
//===========================================================================//
// function fp_re_isFloat(str)
//  returns true if str is a floating point number (integers pass too)
function fp_re_isFloat(str) {
    var re_float = /^((\d+(\.\d*)?)|((\d*\.)?\d+))$/;
    return re_float.test(str);
}
//===========================================================================//
// function fp_re_isAlphaNumeric(str)
//
function fp_re_isAlphaNumeric(str) {
    var re_alnum = /[^a-zA-Z0-9]/g;
    return !re_alnum.test(str);
}
//===========================================================================//
// function fp_re_isWhiteSpace(str)
//
function fp_re_isWhiteSpace(str) {
    var re_ws = /[\S]/g;
    return re_ws.test(str);
}

//===========================================================================//
function fp_is_numeric(str) {
    if (fp_re_isInteger(str) || fp_re_isFloat(str)) {
        return true;
    }
    return false;
}
//===========================================================================//
// function fp_filter_nonnumeric(e)
//  returns false if e.keyCode is not a number
function fp_filter_nonnumeric(e) {
    var code = e.keyCode;

    // check code against allowed vals
    if (   (code != 32 && code < 48) 	// disallow spaces
        || (code > 111 && code < 186)	// ignore Fkeys + numlock + scrollLock
        || (code >= 48 && code <= 57)  // allow numbers from top keyboard row
        || (code >= 96 && code <= 105) // allow numbers from num pad
        )
    {
        // allow the keystroke
        return true;
    }
    // filter out the keystroke
    return false;
}



