diff --git a/mollom-captcha-player.swf b/mollom-captcha-player.swf
index 938e0135dd22f23843f45064a36aa589b398fffa..85143484a60d0d20f0532f443e13952641e64f77 100644
GIT binary patch
literal 5986
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
Qft9~HVt>x|zqqPWWJNn)NB{r;

literal 1378
zcmV-o1)cgsS5pZI2mk<hoTXH2Y!p=#K4%_#clOcFK3ldel(H@KK|4}FsR^`Q+R{>J
z)8!>eVW!<#c64`kot@TTLfk~7Au;hsjX{M({}>EEl)@hqlllW6m?ka;F(hJ0G{zVb
zY9fh5ll9I_0juH<z1iG*&z<jn=R4=@JsAi{fWH9v5OxOK0FYoRmC8cIOScHgXH{Ko
zd<38pp0p1#%lLaMA}lQ}RY3HgJ%vAv2b$p40(TzZ_~+j=!_POXE{P*c;66Ryw^Tx)
z#1#xfFJ8QOu@cyFc60rwSJ>0@-@Scz+u>e#(dA;O2kPn|b;ZE`SKoYM`2GE7UpstK
zMigI|zZ(1qg0Q%_Sh>8+1mG|ocncTNeLlJA<Hv7uUzEJw?vD1-_EESyeql@hhmBmh
z6p3{2OP2a6`4GLu!rrTQ=605x8Es`3K#WA^Puxm=d-wY7+3>HuD8Ad9a*ac9^>df%
zE0^E-et?D<shvCX6Wj6|&dnB<m2wYLdgI28|D{x?xA=#UJDM)ve&s)rZx_L-h857u
zXRd#82j@<dK7$2!6D4zjRcgBy9Lv&V0mpE*<>P5xXuu0D%V`Tsp|vNU|FMu&j`z=)
zW?qMd@G0K<pU@#fCorYb?*y1PUbn^vJ9>bd&1)%NI;#{jo$9Qrn?=u_{7g|Du=c*;
zu>r%#8@9piQ8eA}AX8e=@*(WW&uVHSs}(#CT>6q)u8>t7!#ia!N3GB7jFELEO+(X<
z@x}a%p7J_mIW?sze9}50(-}qA)vV995{|)Xx@LMUhD6`^zQnFRpK6KPrRb@wYPiOx
zo>ZsJWnpP8YpO=kGnCCgGidLtj;UrMqh(Y5$M-5Z)iat`QmQemr}LbV&zqj?ecMw|
z42rPsug#cdp{J`$N#&>1&gp!vt1sEzwMmk;c1_JtT1~%~GD}IZW<^$d?q?;u@;q5E
zG*gYQJlyH5P85l}Zqh8P#+sF&VV$Z{rcG^Db%1sMLQ?<dYWCQ*v%V|lbVfA<npZVV
zU8KlzuK2|0aALQpq*69?R4baa#~8d_dEO3?n^lY=JN48t!J*bw)3bkKbV7Z4MlG6L
z(aaaz!(&GWCML!vI7<j`J12$%sQ!xv{|dQ*zXccl=bX5l{6(S|Wuv6l#Y40@TEjyP
zx>rZn#9Xn)*xFcAY+WoKYmP;uolG^4Zo%W_eEzCxF%S%GB*+kkBMeW_MOZgMfv_IJ
zdkOC&=qG#?afyTv5Lb}!A;O0VA0Zeeq?X_+!o~>J5v(WJP=^H96Wl<sm0%meb|Q2T
zfzBIAxQn1f@DYNWh|o=h&4k%P*sX+pl(3HxcANc{?Sa4`ebjVf@11bGK;N~SVhFgc
zNdWKw?fgFQ15`mZy(1#90i<spkVlR~`s5J>4_lUKBSl1y*ISm#!!TJrRt@xsA*@%t
zgk|Yq+gFl`jiq1?ttFIWoP|B&E_VonVU)>B8Mlg)k#ahkt{IGAy4C_85md}#hcCS<
zBgjJIxwZh+*D4DgEf2PME=U^{y&Kwyag4j$;y4oGEgv#v%rXa1iHWTMvRh`-b+R~C
z&sg9%bYWb)4`yvJYlB6AvUEi{3~krir1l&(xS1i`@E%^khSlsEz#udN6N0tChJa-`
zuc%oOUb7=?vO>F(!*bdmqyp(OwvNu;K(no}Nft($&_b0beU`crA1Yq@U1rm9IY70Q
zsWI3Lir<m(r6uF*Wf|-c?%sE(VKviYwdD1{Gy#W<$Lkb;r{xsZmn9YCpd@dQ<W@;;
kljL?u?vP}j{tiKdGcp{7?+6LtbZ4u%LNDF?0mUgdYj+E)?EnA(

diff --git a/mollom.admin.inc b/mollom.admin.inc
index c9d052aa8a61f3a2f799dc1391a51fea40e14fd4..954c41e54766d260a153867b3fb2ded71f73345f 100644
--- a/mollom.admin.inc
+++ b/mollom.admin.inc
@@ -928,6 +928,7 @@ function mollom_admin_settings(&$form_state) {
     '#default_value' => variable_get('mollom_log_minimum_severity', WATCHDOG_WARNING),
   );
   $form['mollom_advanced']['mollom_audio_captcha_enabled'] = array(
+    '#type' => 'checkbox',
     '#title' => t('Enable audio CAPTCHAs.'),
     '#description' => t('Allows users to switch to an audio verification using the <a href="!faq-url">NATO alphabet</a>.  This may not be appropriate for non-English language sites.', array(
       '!faq-url' => 'https://mollom.com/faq/mollom-audible-captcha-language',
diff --git a/mollom.captcha.audio.tpl.php b/mollom.captcha.audio.tpl.php
new file mode 100644
index 0000000000000000000000000000000000000000..d492cd7eb15414a5d66ae9f458b5ec60b6078c17
--- /dev/null
+++ b/mollom.captcha.audio.tpl.php
@@ -0,0 +1,123 @@
+<?php
+/**
+ * @file
+ * Provide the HTML output for the audio CAPTCHA playback.
+ *
+ * Available variables:
+ * - $captcha_url:  The CAPTCHA audio to present.
+ * - $flash_fallback_player: The URL to the Flash plugin to use as a fallback
+ *   player when HTML5 audio is unsupported for MP3.
+ *
+ * Assumptions:
+ * - SWFObject is already included if it is available.
+ *
+ * @see http://www.html5rocks.com/en/tutorials/audio/quick/
+ */
+
+$flash_url = url($flash_fallback_player, array(
+  'query' => array('url' => $captcha_url),
+  'external' => TRUE,
+));
+$switch_verify = t('Switch to image verification');
+$instructions = t('Enter only the first letter of each word you hear.  If you are having trouble listening in your browser, you can <a href="@captcha-url" id="mollom_captcha_download" class="swfNext-mollom_captcha_verify">download the audio</a> to listen on your device.', array(
+  '@captcha-url' => $captcha_url,
+));
+$unsupported = t('Your system does not support our audio playback verification.  Please <a href="@captcha-url" id="mollom_captcha_download" class="swfNext-mollom_captcha_verify">download this verification</a> to listen on your device.', array(
+  '@captcha-url' => $captcha_url,
+));
+?>
+
+<script type="text/javascript">
+  function embedFallbackPlayer() {
+    var embedDiv = document.getElementById("mollom_captcha_fallback_player");
+    var audioDiv = document.getElementById("mollom_captcha_audio");
+    var unsupportedDiv = document.getElementById("mollom_captcha_unsupported");
+    var movie = '<?php print $flash_url; ?>';
+
+    function embedComplete(e) {
+      if (e.success) {
+        e.ref.focus();
+      } else {
+        jQuery(unsupportedDiv).show();
+      }
+    }
+
+    var flashvars = {},
+      params = {
+        wmode:  "opaque"
+      },
+      attributes = {
+        "class": "swfPrev-mollom_captcha_download swfNext-mollom_captcha_verify mollom_captcha_flash_player",
+      },
+      playerWidth = 110,
+      playerHeight = 50;
+    if (typeof swfobject !== 'undefined') {
+      swfobject.embedSWF(movie, embedDiv, playerWidth, playerHeight, "10.0", null, flashvars, params, attributes, embedComplete);
+    } else {
+      var embed = '<object id="mollom_captcha_fallback_player" name="mollom_captcha_fallback_player" ';
+      embed += 'classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" ';
+      embed += 'type="application/x-shockwave-flash" ';
+      embed += 'data="' + movie + '" '
+      for (var attr in attributes) {
+        embed += attr + '="' + attributes[attr] + '" ';
+      }
+      embed += 'width="' + playerWidth + 'px" height="' + playerHeight + 'px">';
+      embed += '<param name="movie" value="' + movie + '" />';
+      for (var param in params) {
+        embed += '<param name="' + param + '" value="' + params[param] + '" />';
+      }
+      var flashVarsArray = [];
+      for(var varname in flashvars) {
+        flashVarsArray.append(varname + '=' + encodeURI(flashvars[varname]));
+      }
+      flashVarsString = flashVarsArray.join('&');
+      if (flashVarsString.length > 0) {
+        embed += '<param name="flashVars" value="' + flashVarsString + '" />';
+      }
+      embed += '<embed src="' + movie + '" width="' + playerWidth + '" height="' + playerHeight + '" ';
+      for (var attr in attributes) {
+        embed += attr + '="' + attributes[attr] + '" ';
+      }
+      for (var param in params) {
+        embed += param + '="' + params[param] + '" ';
+      }
+      if (flashVarsString.length > 0) {
+        embed += 'flashVars="' + flashVarsString + '"';
+      }
+      embed += '/>';
+      embed += '</object>';
+      jQuery(embedDiv).replaceWith(embed);
+      jQuery("#mollom_captcha_fallback_player").focus();
+    }
+    jQuery(audioDiv).hide();
+  }
+</script>
+
+<div class="mollom-captcha-content mollom-audio-captcha">
+  <div class="mollom-audio-catcha-instructions"><?php print $instructions; ?></div>
+
+  <!--- HTML5 Audio playback -->
+  <audio id="mollom_captcha_audio" controls tabindex="0">
+    <source src="<?php print $captcha_url; ?>" type="audio/mpeg" />
+    <!-- Displays if HTML5 audio is unsupported and JavaScript player embed is unsupported -->
+    <p><?php print $unsupported; ?></p>
+  </audio>
+
+  <!-- Fallback for browsers not supporting HTML5 audio or not MP3 format -->
+  <div id="mollom_captcha_fallback">
+    <div id="mollom_captcha_fallback_player"></div>
+    <script>
+      var audioTest = document.createElement('audio');
+      if (!audioTest.canPlayType || !audioTest.canPlayType('audio/mpeg')) {
+        embedFallbackPlayer();
+      }
+    </script>
+  </div>
+
+  <!-- Text to show when neither HTML5 audio or SWFs are supported -->
+  <div id="mollom_captcha_unsupported" style="display:none;">
+    <p><?php print $unsupported; ?></p>
+  </div>
+
+  <div class="mollom-audio-captcha-switch"><a href="#" class="mollom-switch-captcha mollom-image-captcha swfPrev-mollom_captcha_download" id="mollom_captcha_verify"><?php print $switch_verify; ?></a>.</div>
+</div>
diff --git a/mollom.captcha.image.tpl.php b/mollom.captcha.image.tpl.php
new file mode 100644
index 0000000000000000000000000000000000000000..9ec62e91eadf7e85e0d8f4385305a247404008cd
--- /dev/null
+++ b/mollom.captcha.image.tpl.php
@@ -0,0 +1,21 @@
+<?php
+/**
+ * @file
+ * Provide the HTML output for the CAPTCHA image display.
+ *
+ * Available variables:
+ * - $captcha_url:  The CAPTCHA image to present based
+ * - $audio_enabled: boolean indicates if audio CAPTCHAs are enabled
+ *   for this site.
+ */
+
+$switch_verify = $audio_enabled ? t('Switch to audio verification') : '';
+$instructions = t("Type the characters you see in the picture; if you can't read them, submit the form and a new image will be generated. Not case sensitive.");
+$image_alt_text = t('Type the characters you see in this picture.');
+?>
+
+<?php
+$captcha_output = theme('image', $captcha_url, $image_alt_text, NULL, NULL, FALSE);
+?>
+<span class="mollom-captcha-content mollom-image-captcha"><?php print $captcha_output; ?></span>
+<div class="mollom-image-captcha-instructions"><?php print $instructions; ?><?php if ($audio_enabled) { ?>&nbsp;&nbsp;<a href="#" class="mollom-switch-captcha mollom-audio-captcha"><?php print $switch_verify; ?></a>.<?php } ?></div>
diff --git a/mollom.css b/mollom.css
index e1089b9db88a69d44e8c40422d90cd145ee8fff6..60723989532929f134eb89b2980b5db82c8b0c5c 100644
--- a/mollom.css
+++ b/mollom.css
@@ -15,3 +15,13 @@ img.mollom-fba {
   width: 1px;
   height: 1px;
 }
+
+/* Allow CAPTCHA rendering to take full form width. */
+.form-item-mollom-captcha label[for="edit-mollom-captcha"] {
+    float: none;
+}
+
+/* Accessibilty focus helper for audio CAPTCHA. */
+.mollom_captcha_flash_player:focus{
+    border: yellow 2px solid;
+}
diff --git a/mollom.js b/mollom.js
index 54c0dfa1e1caac256c66f0f17b1c10115df73df5..cec999288977269325c7e4845ed260915267a49f 100644
--- a/mollom.js
+++ b/mollom.js
@@ -52,7 +52,15 @@ function getMollomCaptcha() {
       // Add an onclick-event handler for the new link.
       Drupal.attachBehaviors(context);
       // Focus on the CAPTCHA input.
-      $('input[name="mollom[captcha]"]', context).focus();
+      if (newCaptchaType == 'image') {
+          $('input[name="mollom[captcha]"]', context).focus();
+      } else {
+        // Focus on audio player.
+        // Fallback player code is responsible for setting focus upon embed.
+        if ($('#mollom_captcha_audio').is(":visible")) {
+            $('#mollom_captcha_audio').focus();
+        }
+      }
     }
   });
   return false;
diff --git a/mollom.module b/mollom.module
index 3b8fff70cc8ae9491cb8f654642491ac24bcb16a..22c7c2af8073e5c990590a82edf20c4538928722 100644
--- a/mollom.module
+++ b/mollom.module
@@ -1702,6 +1702,7 @@ function mollom_elements() {
  * Implements hook_theme().
  */
 function mollom_theme() {
+  $base_path = base_path() . drupal_get_path('module', 'mollom');
   return array(
     'mollom' => array(
       'arguments' => array('element' => NULL),
@@ -1710,6 +1711,21 @@ function mollom_theme() {
       'arguments' => array('form' => NULL),
       'file' => 'mollom.admin.inc',
     ),
+    'mollom_captcha_audio' => array(
+      'arguments' => array(
+        'captcha_url' => NULL,
+        'flash_fallback_player' => $base_path . '/mollom-captcha-player.swf',
+      ),
+      'template' => 'mollom.captcha.audio',
+    ),
+    'mollom_captcha_image' => array(
+      'arguments' => array(
+        'captcha_url' => NULL,
+        'audio_enabled' => TRUE,
+      ),
+      'template' => 'mollom.captcha.image',
+    ),
+
   );
 }
 
@@ -1858,10 +1874,9 @@ function mollom_process_mollom($element, $input, &$form_state, &$complete_form)
   // assigned as Boolean #solved = TRUE element property when solved correctly.
   $element['captcha'] = array(
     '#type' => 'textfield',
-    '#title' => t('Word verification'),
+    '#title' => t('verification'),
     '#size' => 10,
     '#default_value' => '',
-    '#description' => t("Type the characters you see in the picture above; if you can't read them, submit the form and a new image will be generated. Not case sensitive."),
   );
   // Disable browser autocompletion, unless testing mode is enabled, in which
   // case autocompletion for 'correct' and 'incorrect' is handy.
@@ -2044,6 +2059,8 @@ function mollom_form_add_captcha(&$element, &$form_state) {
   if (!empty($captcha)) {
     $element['captcha']['#access'] = TRUE;
     $element['captcha']['#field_prefix'] = $captcha;
+    $element['captcha']['#attributes'] = array('title' => t('Enter the characters from the verification above.'));
+    _mollom_attach_captcha_script($element['captcha']);
 
     // Ensure that the latest CAPTCHA ID is output as value.
     $element['captchaId']['#value'] = $form_state['mollom']['response']['captcha']['id'];
@@ -2060,6 +2077,78 @@ function mollom_form_add_captcha(&$element, &$form_state) {
 }
 
 /**
+ * Attach SWFObject script to render element when available.
+ *
+ * @param $element
+ *   A render element to attach the script to.
+ *
+ * @return bool
+ *   True if the library can be found, false otherwise.
+ */
+function _mollom_attach_captcha_script(&$element = NULL) {
+  static $libraries;
+  if (empty($libraries['swfobject'])) {
+    $lib = array(
+      'found' => FALSE,
+    );
+
+    // Try to load via libraries module if enabled.
+    if (module_exists('libraries')) {
+      if (($library = libraries_detect('swfoject')) && !empty($library['installed'])) {
+        $lib = array(
+          'found' => TRUE,
+          'libraries' => TRUE,
+        );
+      }
+    }
+    if (!$lib['found']) {
+      // Check for SWFObject in standard library locations.
+      global $profile;
+      if (!isset($profile)) {
+        $profile = variable_get('install_profile', 'default');
+      }
+      $config = conf_path();
+      $search = array();
+      $search[] = 'libraries';
+      if (file_exists("profiles/$profile/libraries")) {
+        $search[] = "profiles/$profile/libraries";
+      }
+      $search[] = 'site/all/libraries';
+      if (file_exists("$config/libraries")) {
+        $search[] = "$config/libraries";
+      }
+      foreach ($search as $dir) {
+        if (is_dir($dir) && (
+            file_exists("$dir/swfobject.js") || file_exists("$dir/swfobject/swfobject.js")
+          )) {
+          $lib = array(
+            'found' => TRUE,
+            'libraries' => FALSE,
+            'path' => file_exists("$dir/swfobject.js") ? "$dir/swfobject.js" : "$dir/swfobject/swfobject.js",
+          );
+          break;
+        }
+      }
+    }
+    $libraries['swfobject'] = $lib;
+  }
+  if ($libraries['swfobject']['found']) {
+    if (isset($element)) {
+      if ($libraries['swfobject']['libraries']) {
+        $element['#attached']['libraries_load'][] = array('swfobject');
+      }
+      else {
+        $element['#attached'] = array(
+          'js' => array($libraries['swfobject']['path']),
+        );
+      }
+    }
+    return TRUE;
+  }
+  return FALSE;
+}
+
+/**
  * Form validation handler to perform textual analysis on submitted form values.
  */
 function mollom_validate_analysis($form_copy, &$form_state) {
@@ -2937,37 +3026,14 @@ function mollom_get_captcha(&$form_state) {
     return '';
   }
 
-  // @todo Convert these to actual theme functions?
-  $output = '';
-  switch ($form_state['mollom']['captcha_type']) {
-    case 'audio':
-      $source = url(base_path() . drupal_get_path('module', 'mollom') . '/mollom-captcha-player.swf', array(
-        'query' => array('url' => $url),
-        'external' => TRUE,
-      ));
-      $output = '<object classid="clsid:d27cdb6e-ae6d-11cf-96b8-444553540000" codebase="//download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=9,0,0,0" width="110" height="50">';
-      $output .= '<param name="allowFullScreen" value="false" />';
-      $output .= '<param name="movie" value="' . $source . '" />';
-      $output .= '<param name="loop" value="false" />';
-      $output .= '<param name="menu" value="false" />';
-      $output .= '<param name="quality" value="high" />';
-      $output .= '<param name="wmode" value="transparent" />';
-      $output .= '<param name="bgcolor" value="#ffffff" />';
-      $output .= '<embed src="' . $source . '" loop="false" menu="false" quality="high" wmode="transparent" bgcolor="#ffffff" width="110" height="50" align="baseline" allowScriptAccess="sameDomain" allowFullScreen="false" type="application/x-shockwave-flash" pluginspage="http://www.adobe.com/go/getflashplayer_de" />';
-      $output .= '</object>';
-
-      $output = '<span class="mollom-captcha-content mollom-audio-captcha">' . $output . '</span>';
-      $output .= ' (<a href="#" class="mollom-switch-captcha mollom-image-captcha">' . t('verify using image') . '</a>)';
-      break;
-
-    case 'image':
-      $captcha = theme('image', $url, t('Type the characters you see in this picture.'), '', NULL, FALSE);
-      $output = '<span class="mollom-captcha-content mollom-image-captcha">' . $captcha . '</span>';
-      $output .= ' (<a href="#" class="mollom-switch-captcha mollom-audio-captcha">' . t('verify using audio') . '</a>)';
-      break;
+  // Theme CAPTCHA output and return.
+  $audio_enabled = variable_get('mollom_audio_captcha_enabled', 1);
+  if ($audio_enabled && $form_state['mollom']['captcha_type'] == 'audio') {
+    return theme('mollom_captcha_audio', $url);
+  }
+  else {
+    return theme('mollom_captcha_image', $url, $audio_enabled);
   }
-
-  return $output;
 }
 
 /**
diff --git a/tests/mollom.test b/tests/mollom.test
index 8ef3a8d55202ee41c9cf736fd3d272ff75b506b6..328d6756f8f02ed8bda51d9e7e06618244d2eb7b 100644
--- a/tests/mollom.test
+++ b/tests/mollom.test
@@ -4739,6 +4739,20 @@ class MollomCaptchaTestCase extends MollomWebTestCase {
     // D6 can encode, but not decode its own JSON, so only check for captchaId.
     $this->assertText('captchaId');
   }
+
+  /**
+   * Tests the CAPTCHA audio enable/disable functionality.
+   */
+  function subTestCAPTCHAAudioEnable() {
+    // Default should be enabled audio.
+    $this->drupalGet('mollom-test/form');
+    $this->assertLink(t('Switch to audio verification'));
+
+    // Verify that CAPTCHA cannot be switched when audio is disabled.
+    variable_set('mollom_audio_captcha_enabled', 0);
+    $this->drupalGet('mollom-test/form');
+    $this->assertNoLink(t('Switch to audio verification'));
+  }
 }
 
 /**
