diff --git a/includes/scald.admin.inc b/includes/scald.admin.inc
index 1639e9d..2abcedf 100644
--- a/includes/scald.admin.inc
+++ b/includes/scald.admin.inc
@@ -131,6 +131,18 @@ function scald_admin_type_form($form, $form_state, $type) {
     '#maxlength'      => 255,
     '#required'       => TRUE,
   );
+  $options = array(
+    'managed_file' => t('Managed file'),
+  );
+  if (module_exists('plupload')) {
+    $options['plupload'] = t('Plupload');
+  }
+  $form['defaults']['type_' . $type_name . '_utype'] = array(
+    '#type'           => 'select',
+    '#title'          => t('Upload type'),
+    '#default_value'  => $default->upload_type,
+    '#options' => $options
+  );
   // Create checkboxes for the defined actions.
   $actions = scald_actions();
   $options = array();
@@ -193,6 +205,10 @@ function scald_admin_type_form_submit($form, &$form_state) {
           $scald_atom_defaults[$type]->description = $value;
           break;
 
+        case '_utype':
+          $scald_atom_defaults[$type]->upload_type = $value;
+          break;
+
         case '_actin':
           $actions = scald_actions();
           $bitmask = 0;
diff --git a/includes/scald.pages.inc b/includes/scald.pages.inc
index 0a40f32..0576244 100644
--- a/includes/scald.pages.inc
+++ b/includes/scald.pages.inc
@@ -134,7 +134,7 @@ function scald_atom_add_page($js, $type, $step = NULL, $atom_id = NULL) {
   }
   else {
     if ($output === FALSE || !empty($form_state['complete'])) {
-      $atom = $form_state['scald']['atom'];
+      $atom = $form_state['scald']['atoms'][0];
       drupal_goto('atom/' . $atom->sid . '/view');
     }
     elseif (!empty($form_state['cancel'])) {
@@ -200,48 +200,79 @@ function scald_atom_add_form_add($form, &$form_state) {
  */
 function scald_atom_add_form_add_submit(&$form, &$form_state) {
   $scald = $form_state['scald'];
-  $atom = new ScaldAtom($scald['type']->type, $scald['source']);
 
-  // Allow the source provider to alter it, filling in defaults value.
-  $function = $atom->provider . '_scald_add_form_fill';
+  $count = 1;
+  $atom_count_implemented = FALSE;
+  // Allow the source provider to define how many atoms to create
+  // and handle differences between upload modules
+  $function = $scald['source'] . '_scald_add_atom_count';
   if (function_exists($function)) {
-    $function($atom, $form, $form_state);
+    $count = $function($form, $form_state);
+    $atom_count_implemented = TRUE;
+  }
+
+  for ($delta = 0; $delta < $count; $delta++) {
+    $atoms[$delta] = new ScaldAtom($scald['type']->type, $scald['source']);
   }
 
+  // Allow the source provider to alter it, filling in defaults value.
+  $function = $scald['source'] . '_scald_add_form_fill';
+  if (function_exists($function)) {
+    if ($atom_count_implemented) {
+      $function($atoms, $form, $form_state);
+    }
+    else {
+      $function($atoms[0], $form, $form_state);
+    }
+  }
   // And put it in the form_state
-  $form_state['scald']['atom'] = $atom;
+  $form_state['scald']['atoms'] = $atoms;
 }
 
 /**
  * Options form.
  */
 function scald_atom_add_form_options($form, &$form_state) {
-  $atom = $form_state['scald']['atom'];
-
-  $form['title'] = array(
-    '#type' => 'textfield',
-    '#title' => t('Title'),
-    '#required' => TRUE,
-    '#default_value' => $atom->title,
-  );
+  $atoms = $form_state['scald']['atoms'];
 
   $actions = scald_actions();
-  $options = array();
-  $options_default = array();
-  foreach ($actions as $name => $action) {
-    $options[$name] = $action['title'];
-    $options_default[$name] = $atom->actions & $action['bitmask'] ? $name : '';
-  }
-  $form['scald_actions'] = array(
-    '#type' => 'checkboxes',
-    '#title' => 'Openly available actions',
-    '#group' => 'additional_settings',
-    '#options' => $options,
-    '#default_value' => $options_default,
-    '#access' => user_access('administer scald atoms'),
-  );
 
-  field_attach_form('scald_atom', $atom, $form, $form_state);
+  foreach ($atoms as $delta => $atom) {
+    $form['atom' . $delta] = array(
+      '#prefix' => '<div class="atom-wrapper">',
+      '#suffix' => '</div>',
+      '#parents' => array('atom' . $delta),
+    );
+    $form['atom' . $delta]['title'] = array(
+      '#type' => 'textfield',
+      '#title' => t('Title'),
+      '#required' => TRUE,
+      '#default_value' => $atom->title,
+      '#parents' => array('atom' . $delta, 'title'),
+      '#weight' => -10,
+    );
+    field_attach_form('scald_atom', $atom, $form['atom' . $delta], $form_state);
+    $instances = field_info_instances('scald_atom', $atom->type);
+    foreach ($instances as $instance) {
+      $field_name = $instance['field_name'];
+      $form['atom' . $delta][$field_name]['#parents'] = array('atom' . $delta, $field_name);
+    }
+    $options = array();
+    $options_default = array();
+    foreach ($actions as $name => $action) {
+      $options[$name] = $action['title'];
+      $options_default[$name] = $atom->actions & $action['bitmask'] ? $name : '';
+    }
+    $form['atom' . $delta]['scald_actions'] = array(
+      '#type' => 'checkboxes',
+      '#title' => 'Openly available actions',
+      '#group' => 'additional_settings',
+      '#options' => $options,
+      '#default_value' => $options_default,
+      '#parents' => array('atom' . $delta, 'scald_actions'),
+      '#access' => user_access('administer scald atoms'),
+    );
+  }
 
   $form['actions']['submit']['#value'] = t('Save');
 
@@ -252,40 +283,44 @@ function scald_atom_add_form_options($form, &$form_state) {
  * Handles the final atom creation step form submission.
  */
 function scald_atom_add_form_options_submit(&$form, &$form_state) {
-  $atom = $form_state['scald']['atom'];
-
-  if (is_array($form_state['values']['scald_actions'])) {
-    $bitstream = 0;
-    $actions = scald_actions();
-    foreach ($actions as $name => $action) {
-      if (!empty($form_state['values']['scald_actions'][$name])) {
-        $bitstream |= $action['bitmask'];
+  $atoms = $form_state['scald']['atoms'];
+
+  foreach ($atoms as $delta => $atom) {
+    if (is_array($form_state['values']['atom' . $delta]['scald_actions'])) {
+      $bitstream = 0;
+      $actions = scald_actions();
+      foreach ($actions as $name => $action) {
+        if (!empty($form_state['values']['atom' . $delta]['scald_actions'][$name])) {
+          $bitstream |= $action['bitmask'];
+        }
       }
+      $form_state['values']['atom' . $delta]['actions'] = $bitstream;
     }
-    $form_state['values']['actions'] = $bitstream;
-  }
-
-  $op = empty($atom->sid) ? t('created') : t('updated');
 
-  // Let entity add its properties to the atom.
-  entity_form_submit_build_entity('scald_atom', $atom, $form, $form_state);
+    $op = empty($atom->sid) ? t('created') : t('updated');
 
-  // Then save it...
-  scald_atom_save($atom);
-
-  // Add a message confirming the creation.
-  drupal_set_message(t('Atom %title, of type %type has been %op', array(
-    '%title' => $atom->title,
-    '%type' => $atom->type,
-    '%op' => $op,
-  )));
+    // Let entity add its properties to the atom.
+    entity_form_submit_build_entity('scald_atom', $atom, $form['atom' . $delta], $form_state);
+    $atom->title = $form_state['values']['atom' . $delta]['title'];
+    $atom->actions = $form_state['values']['atom' . $delta]['actions'];
+    // Then save it...
+    scald_atom_save($atom);
+  }
+  if (count($atoms) == 1) {
+    // Add a message confirming the creation.
+    drupal_set_message(t('Atom %title, of type %type has been %op', array(
+      '%title' => $atoms[0]->title,
+      '%type' => $atoms[0]->type,
+      '%op' => $op,
+    )));
+  }
 }
 
 /**
  * Handle the 'next' click on the add/edit pane form wizard.
  */
 function scald_atom_add_wizard_next(&$form_state) {
-  $cache_id = isset($form_state['scald']['atom']->sid) ? 'edit:' . $form_state['scald']['atom']->sid : 'add';
+  $cache_id = isset($form_state['scald']['atoms'][0]->sid) ? 'edit:' . $form_state['scald']['atoms'][0]->sid : 'add';
   ctools_object_cache_set('scald_atom', $cache_id, $form_state['scald']);
 }
 
@@ -318,7 +353,7 @@ function scald_atom_edit_page($js, $atom) {
   // We prepare data for this step then send back to the add page. The only
   // useful information at this step is the atom itself.
   $scald = array(
-    'atom' => $atom,
+    'atoms' => array($atom),
   );
   $types = scald_types();
   ctools_include('object-cache');
diff --git a/modules/library/dnd/dnd.module b/modules/library/dnd/dnd.module
index 5920f87..fccb235 100644
--- a/modules/library/dnd/dnd.module
+++ b/modules/library/dnd/dnd.module
@@ -102,7 +102,8 @@ function dnd_library() {
     'js' => array(
       // Drag and drop
       $path . '/js/dnd-library.js' => array(),
-
+      // javascript workaround for the continue button
+      $path . '/js/dnd-modal.js' => array(),
       // Settings for the library url
       array(
         'type' => 'setting',
diff --git a/modules/library/dnd/js/dnd-modal.js b/modules/library/dnd/js/dnd-modal.js
new file mode 100644
index 0000000..8fe6e4a
--- /dev/null
+++ b/modules/library/dnd/js/dnd-modal.js
@@ -0,0 +1,26 @@
+(function ($) {
+  Drupal.behaviors.dndModal= {
+    attach: function (context, settings) {
+      $('#edit-next', context).click(function(e) {
+        var form = $('#scald-atom-add-form-add');
+        if (form.find('.plupload-element').length > 0) {
+          var uploader = form.find('.plupload-element').first().pluploadQueue();
+          if ((uploader.total.uploaded + uploader.total.failed) != uploader.files.length || uploader.files.length == 0) {
+            uploader.start();
+            uploader.bind('UploadComplete', function() {
+              setTimeout(function(){$('#edit-next', context).click();},500);
+            });
+            return false;
+          }
+        }
+        else if (form.find('.form-managed-file')) {
+          var file = form.find('.form-managed-file').first();
+          var name = file.attr('id').substr(5).replace('-', '_');
+          if (file.find("[name='" + name + "[fid]']").val() == 0) {
+            return false;
+          }
+        }
+      });
+    }
+  };
+})(jQuery);
diff --git a/modules/providers/scald_audio/scald_audio.module b/modules/providers/scald_audio/scald_audio.module
index 8e944c0..42339d9 100644
--- a/modules/providers/scald_audio/scald_audio.module
+++ b/modules/providers/scald_audio/scald_audio.module
@@ -22,71 +22,89 @@ function scald_audio_scald_atom_providers() {
  * Implements hook_scald_add_form().
  */
 function scald_audio_scald_add_form(&$form, &$form_state) {
+  $defaults = scald_atom_defaults('audio');
   $form['file'] = array(
-    '#type' => 'managed_file',
+    '#type' => $defaults->upload_type,
     '#title' => 'Audio',
     '#upload_location' => 'public://atoms/audio/',
     '#upload_validators' => array('file_validate_extensions' => array('wav ogg mp3')),
   );
 }
 
+/**
+ * Implements hook_scald_add_atom_count().
+ */
+function scald_audio_scald_add_atom_count(&$form, &$form_state) {
+  if (is_array($form_state['values']['file'])) {
+    return max(count($form_state['values']['file']), 1);
+  }
+  return 1;
+}
 
 /**
  * Implements hook_scald_add_form_fill().
  */
-function scald_audio_scald_add_form_fill(&$atom, $form, $form_state) {
+function scald_audio_scald_add_form_fill(&$atoms, $form, $form_state) {
   $dir_audio_thumb = 'public://atoms/audio/thumb';
-  $file = file_load($form_state['values']['file']);
-  $atom->base_id = $file->fid;
-  $atom->file_source = $file->uri;
-  $atom->data['audio_file'] = $file->uri;
-  $atom->data['audio_id'] = $file->fid;
-  $atom->title = $file->filename;
-
-  if (file_prepare_directory($dir_audio_thumb, FILE_CREATE_DIRECTORY)) {
-    if (module_exists('waudio_getid3') && $getid3 = _waudio_getid3_load()) {
-      $filepath = drupal_realpath($file->uri);
-      // get all id3 infos
-      $ret = waudio_getid3_ret_infos($filepath, $getid3);
-      $atom->title = isset($ret['tags']['title'])?$ret['tags']['title']:$file->filename;
-
-      // Prefill the author
-      $atom->scald_authors[LANGUAGE_NONE][0] = array(
-        'tid' => 0,
-        'taxonomy_term' => (object)(array('name' => isset($ret['tags']['artist'])?$ret['tags']['artist']:t('Unknown')))
-      );
-
-      // Prefill tags
-      $atom->scald_tags[LANGUAGE_NONE][0] = array(
-        'tid' => 0,  // Beware, this is not a real tid, it's just an index
-        'taxonomy_term' => (object)(array('name' => isset($ret['tags']['genre'])?$ret['tags']['genre']:t('Unknown')))
-      );
-
-      $atom->data['artist'] = isset($ret['tags']['artist'])?$ret['tags']['artist']:'';
-      $atom->data['title'] = isset($ret['tags']['title'])?$ret['tags']['title']:'';
-      $atom->data['album'] = isset($ret['tags']['album'])?$ret['tags']['album']:'';
-      $atom->data['track'] = isset($ret['tags']['track'])?$ret['tags']['track']:isset($ret['tags']['track_number'])?$ret['tags']['track_number']:'';
-      $atom->data['year'] = isset($ret['tags']['year'])?$ret['tags']['year']:'';
-      $atom->data['genre'] = isset($ret['tags']['genre'])?$ret['tags']['genre']:'';
-
-      // If the MP3 includes a cover art, use it as the default thumbnail.
-      if (isset($ret['images'][0]['data']) && $ret['images'][0]['data'] != '') {
-        $extension = '.jpg';
-        if ($ret['images'][0]['image_mime'] == 'image/png') {
-          $extension = '.png';
-        }
-        elseif ($ret['images'][0]['image_mime'] == 'image/gif') {
-          $extension = '.gif';
+  foreach ($atoms as $delta => $atom) {
+    if (is_array($form_state['values']['file']) && module_exists('plupload')) {
+      $file = scald_plupload_save_file($form_state['values']['file'][$delta]['tmppath'],
+        $form['file']['#upload_location'] . $form_state['values']['file'][$delta]['name']);
+    }
+    else {
+      $file = file_load($form_state['values']['file']);
+    }
+    $atom->base_id = $file->fid;
+    $atom->file_source = $file->uri;
+    $atom->data['audio_file'] = $file->uri;
+    $atom->data['audio_id'] = $file->fid;
+    $atom->title = $file->filename;
+
+    if (file_prepare_directory($dir_audio_thumb, FILE_CREATE_DIRECTORY)) {
+      if (module_exists('waudio_getid3') && $getid3 = _waudio_getid3_load()) {
+        $filepath = drupal_realpath($file->uri);
+        // get all id3 infos
+        $ret = waudio_getid3_ret_infos($filepath, $getid3);
+        $atom->title = isset($ret['tags']['title'])?$ret['tags']['title']:$file->filename;
+
+        // Prefill the author
+        $atom->scald_authors[LANGUAGE_NONE][0] = array(
+          'tid' => 0,
+          'taxonomy_term' => (object)(array('name' => isset($ret['tags']['artist'])?$ret['tags']['artist']:t('Unknown')))
+        );
+
+        // Prefill tags
+        $atom->scald_tags[LANGUAGE_NONE][0] = array(
+          'tid' => 0,  // Beware, this is not a real tid, it's just an index
+          'taxonomy_term' => (object)(array('name' => isset($ret['tags']['genre'])?$ret['tags']['genre']:t('Unknown')))
+        );
+
+        $atom->data['artist'] = isset($ret['tags']['artist'])?$ret['tags']['artist']:'';
+        $atom->data['title'] = isset($ret['tags']['title'])?$ret['tags']['title']:'';
+        $atom->data['album'] = isset($ret['tags']['album'])?$ret['tags']['album']:'';
+        $atom->data['track'] = isset($ret['tags']['track'])?$ret['tags']['track']:isset($ret['tags']['track_number'])?$ret['tags']['track_number']:'';
+        $atom->data['year'] = isset($ret['tags']['year'])?$ret['tags']['year']:'';
+        $atom->data['genre'] = isset($ret['tags']['genre'])?$ret['tags']['genre']:'';
+
+        // If the MP3 includes a cover art, use it as the default thumbnail.
+        if (isset($ret['images'][0]['data']) && $ret['images'][0]['data'] != '') {
+          $extension = '.jpg';
+          if ($ret['images'][0]['image_mime'] == 'image/png') {
+            $extension = '.png';
+          }
+          elseif ($ret['images'][0]['image_mime'] == 'image/gif') {
+            $extension = '.gif';
+          }
+          $dest = $dir_audio_thumb . '/' . $file->filename . $extension;
+          $thumbnail = file_save_data($ret['images'][0]['data'], $dest);
+          // Set the file status to temporary (image thumb)
+          db_update('file_managed')
+            ->condition('fid', $thumbnail->fid)
+            ->fields(array('status' => 0))
+            ->execute();
+
+          $atom->scald_thumbnail[LANGUAGE_NONE][0] = (array)$thumbnail;
         }
-        $dest = $dir_audio_thumb . '/' . $file->filename . $extension;
-        $thumbnail = file_save_data($ret['images'][0]['data'], $dest);
-        // Set the file status to temporary (image thumb)
-        db_update('file_managed')
-          ->condition('fid', $thumbnail->fid)
-          ->fields(array('status' => 0))
-          ->execute();
-
-        $atom->scald_thumbnail[LANGUAGE_NONE][0] = (array)$thumbnail;
       }
     }
   }
diff --git a/modules/providers/scald_flash/scald_flash.module b/modules/providers/scald_flash/scald_flash.module
index 7f69080..7fcfac3 100644
--- a/modules/providers/scald_flash/scald_flash.module
+++ b/modules/providers/scald_flash/scald_flash.module
@@ -17,8 +17,9 @@ function scald_flash_scald_atom_providers() {
 
 
 function scald_flash_scald_add_form(&$form, &$form_state) {
+  $defaults = scald_atom_defaults('flash');
   $form['file_swf'] = array(
-    '#type' => 'managed_file',
+    '#type' => $defaults->upload_type,
     '#title' => t('SWF File'),
     '#upload_location' => 'public://atoms/swf/',
     '#upload_validators' => array('file_validate_extensions' => array('swf')),
@@ -26,17 +27,36 @@ function scald_flash_scald_add_form(&$form, &$form_state) {
 }
 
 /**
+ * Implements hook_scald_add_atom_count().
+ */
+function scald_flash_scald_add_atom_count(&$form, &$form_state) {
+  if (is_array($form_state['values']['file_swf'])) {
+    return max(count($form_state['values']['file_swf']), 1);
+  }
+  return 1;
+}
+
+
+/**
  * Implements hook_scald_add_form_fill.
  */
-function scald_flash_scald_add_form_fill(&$atom, $form, $form_state) {
-  $file = file_load($form_state['values']['file_swf']);
-  $atom->title = $file->filename;
-  $atom->base_id = $file->fid;
-  $size_infos = getimagesize($file->uri);
-  $atom->data['flash_width'] = $size_infos[0];
-  $atom->data['flash_height'] = $size_infos[1];
-  $atom->scald_width[LANGUAGE_NONE][0]['value'] = $size_infos[0];
-  $atom->scald_height[LANGUAGE_NONE][0]['value'] = $size_infos[1];
+function scald_flash_scald_add_form_fill(&$atoms, $form, $form_state) {
+  foreach ($atoms as $delta => $atom) {
+    if (is_array($form_state['values']['file_swf']) && module_exists('plupload')) {
+      $file = scald_plupload_save_file($form_state['values']['file_swf'][$delta]['tmppath'],
+        $form['file_swf']['#upload_location'] . $form_state['values']['file_swf'][$delta]['name']);
+    }
+    else {
+      $file = file_load($form_state['values']['file_swf']);
+    }
+    $atom->title = $file->filename;
+    $atom->base_id = $file->fid;
+    $size_infos = getimagesize($file->uri);
+    $atom->data['flash_width'] = $size_infos[0];
+    $atom->data['flash_height'] = $size_infos[1];
+    $atom->scald_width[LANGUAGE_NONE][0]['value'] = $size_infos[0];
+    $atom->scald_height[LANGUAGE_NONE][0]['value'] = $size_infos[1];
+  }
 }
 
 /**
diff --git a/modules/providers/scald_image/scald_image.module b/modules/providers/scald_image/scald_image.module
index ea2f025..4561eff 100644
--- a/modules/providers/scald_image/scald_image.module
+++ b/modules/providers/scald_image/scald_image.module
@@ -25,8 +25,9 @@ function scald_image_scald_atom_providers() {
  * Implements hook_scald_add_form().
  */
 function scald_image_scald_add_form(&$form, &$form_state) {
+  $defaults = scald_atom_defaults('image');
   $form['file'] = array(
-    '#type' => 'managed_file',
+    '#type' => $defaults->upload_type,
     '#title' => t('Image'),
     '#upload_location' => 'public://atoms/images/',
     '#upload_validators' => array('file_validate_extensions' => array('jpg jpeg png gif')),
@@ -34,13 +35,31 @@ function scald_image_scald_add_form(&$form, &$form_state) {
 }
 
 /**
+ * Implements hook_scald_add_atom_count().
+ */
+function scald_image_scald_add_atom_count(&$form, &$form_state) {
+  if (is_array($form_state['values']['file'])) {
+    return max(count($form_state['values']['file']), 1);
+  }
+  return 1;
+}
+
+/**
  * Implements hook_scald_add_form_fill().
  */
-function scald_image_scald_add_form_fill(&$atom, $form, $form_state) {
-  $file = file_load($form_state['values']['file']);
-  $atom->title = $file->filename;
-  $atom->base_id = $file->fid;
-  $atom->scald_thumbnail[LANGUAGE_NONE][0] = (array)$file;
+function scald_image_scald_add_form_fill(&$atoms, $form, $form_state) {
+  foreach ($atoms as $delta => $atom) {
+    if (is_array($form_state['values']['file']) && module_exists('plupload')) {
+      $file = scald_plupload_save_file($form_state['values']['file'][$delta]['tmppath'],
+        $form['file']['#upload_location'] . $form_state['values']['file'][$delta]['name']);
+    }
+    else {
+      $file = file_load($form_state['values']['file']);
+    }
+    $atom->title = $file->filename;
+    $atom->base_id = $file->fid;
+    $atom->scald_thumbnail[LANGUAGE_NONE][0] = (array)$file;
+  }
 }
 
 /**
diff --git a/scald.module b/scald.module
index fd829c8..99bc955 100644
--- a/scald.module
+++ b/scald.module
@@ -391,6 +391,7 @@ function scald_atom_defaults($type) {
     $actions = scald_actions();
     $default = new stdClass();
     $default->actions = $actions['view']['bitmask'] + $actions['fetch']['bitmask'];
+    $default->upload_type = 'managed_file';
     $default->description = '';
 
     $thumbnail = in_array($type, array('image', 'audio', 'video')) ? $type . '.png' : 'thumbnail_default.png';
@@ -2384,3 +2385,14 @@ function scald_atom_user_build_actions_links($atom, $query = NULL) {
 
   return $links;
 }
+
+/*
+ * Creates a file object at the proper place when uploading with plupload
+ */
+function scald_plupload_save_file($tmppath, $target) {
+  $tmp = plupload_file_uri_to_object($tmppath);
+  // changing file mime to the proper one
+  $tmp->filemime = file_get_mimetype($target);
+  $tmp->status = 0;
+  return file_move($tmp, $target, FILE_EXISTS_RENAME);
+}
\ No newline at end of file
