/*
 *  call-seq:
 *    play( options={:fade_in => 0, :repeats => 0, :start_at => 0} )  ->  self
 *
 *  Play the Music, optionally fading in, repeating a certain number
 *  of times (or forever), and/or starting at a certain position in
 *  the song.
 *
 *  See also #pause and #stop.
 *
 *  options::     Hash of options, listed below. (Hash, required)
 *
 *    :fade_in::     Fade in from silence over the given number of
 *                   seconds. Default: 0. (Numeric, optional)
 *    :repeats::     Repeat the music the given number of times, or
 *                   forever (or until stopped) if -1. Default: 0.
 *                   (Integer, optional)
 *    :start_at::    Start playing the music at the given time in the
 *                   song, in seconds. Default: 0. (Numeric, optional)
 *                   **NOTE**: Non-zero start times only work for
 *                   OGG and MP3 formats! Please refer to #jump.
 *
 *
 *  Returns::     The receiver (self).
 *  May raise::   SDLError, if the music file could not be played, or
 *                if you used :start_at with an unsupported format.
 *
 *      **NOTE**: Only one music can be playing at once. If any music is
 *  already playing (or paused), it will be stopped before playing the
 *  new music.
 *
 *  Example:
 *    # Fade in over 2 seconds, play 4 times (1 + 3 repeats),
 *    # starting at 60 seconds since the beginning of the song.
 *    music.play( :fade_in => 2, :repeats => 3, :start_at => 60 );
 *
 */
static VALUE rg_music_play( int argc, VALUE *argv, VALUE self )
{
  RG_Music *music;
  Data_Get_Struct(self,  RG_Music, music);

  VALUE options;
  rb_scan_args(argc, argv, "01", &options);

  int fade_in    =  0;
  int repeats    =  1;
  double start_at   =  0;

  /* If we got some options */
  if( RTEST(options) )
  {
    /* Make sure options is a Hash table */
    if( TYPE(options) != T_HASH )
    {
      rb_raise(rb_eTypeError, "wrong argument type %s (expected Hash)",
               rb_obj_classname(options));
    }

    VALUE temp;


    temp = rb_hash_aref(options, make_symbol("fade_in"));
    if( RTEST(temp) )
    {
      fade_in = (int)(1000 * NUM2DBL( temp ));

      if( fade_in < 0 )
      {
        rb_raise(rb_eArgError, ":fade_in cannot be negative (got %.2f)",
                 fade_in / 1000);
      }
      else if( fade_in < 50 )
      {
        /* Work-around for a bug with SDL_mixer not working with small non-zero fade-ins */
        fade_in = 0;
      }
    }


    temp = rb_hash_aref(options, make_symbol("repeats"));
    if( RTEST(temp) )
    {
      repeats = NUM2INT(temp);

      if( repeats > -1 )
      {
        /* Adjust so repeats means the same as it does for Sound */
        repeats += 1;
      }

      if( repeats < -1 )
      {
        rb_raise(rb_eArgError, ":repeats cannot be negative, except -1 (got %d)",
                 repeats);
      }
    }


    temp = rb_hash_aref(options, make_symbol("start_at"));
    if( RTEST(temp) )
    {
      start_at = (double)(NUM2DBL( temp ));

      if( start_at < 0 )
      {
        rb_raise(rb_eArgError, ":start_at cannot be negative (got %.2f)",
                 start_at);
      }
    }

  }

  int result = _rg_music_play( music, fade_in, repeats, start_at );

  if( result == -1 )
  {
    rb_raise(eSDLError, "Could not play Music: %s", Mix_GetError());
  }

  /* This music is now current. */
  _rg_music_set_current( self );

  return self;
}