Ejemplo n.º 1
0
static void *dae_play_loop(void *arg)
{
	char *buffer = g_malloc(CD_FRAMESIZE_RAW * CDDA_DAE_FRAMES);
	int pos = LBA(cdda_playing.cd_toc.track[cdda_playing.track]);
	int end, frames;

	if (cdda_playing.track == cdda_playing.cd_toc.last_track)
		end = LBA(cdda_playing.cd_toc.leadout);
	else
		end = LBA(cdda_playing.cd_toc.track[cdda_playing.track + 1]);

	while (cdda_playing.playing)
	{
		int left;
		char *data;

		if (dae_data.seek != -1)
		{
			cdda_ip.output->flush(dae_data.seek * 1000);
			pos = LBA(cdda_playing.cd_toc.track[cdda_playing.track])
				+ dae_data.seek * 75;
			dae_data.seek = -1;
			dae_data.eof = FALSE;
		}
		frames = MIN(CDDA_DAE_FRAMES, end - pos);
		if (frames == 0)
			dae_data.eof = TRUE;

		if (dae_data.eof)
		{
			xmms_usleep(30000);
			continue;
		}

		frames = read_audio_data(cdda_playing.fd, pos,
					 frames, buffer);
		if (frames <= 0)
		{
			int err = -frames;
			if (err == EOPNOTSUPP)
				dae_data.eof = TRUE;
			else
			{
				/*
				 * If the read failed, skip ahead to
				 * avoid getting stuck on scratches
				 * and such.
				 */
				g_message("read_audio_data() failed:  %s (%d)",
					  strerror(err), err);
				pos += MIN(CDDA_DAE_FRAMES, end - pos);
			}
			continue;
		}
		left = frames * CD_FRAMESIZE_RAW;
		data = buffer;
		while (cdda_playing.playing && left > 0 && dae_data.seek == -1)
		{
			int cur = MIN(512 * 2 * 2, left);
			cdda_ip.add_vis_pcm(cdda_ip.output->written_time(),
					    FMT_S16_LE, 2, cur, data);
			while (cdda_ip.output->buffer_free() < cur &&
			       cdda_playing.playing && dae_data.seek == -1)
				xmms_usleep(30000);
			if (cdda_playing.playing && dae_data.seek == -1)
				cdda_ip.output->write_audio(data, cur);
			left -= cur;
			data += cur;
		}
		pos += frames;
	}

	cdda_ip.output->buffer_free();
	cdda_ip.output->buffer_free();
	g_free(buffer);

	return NULL;
}
Ejemplo n.º 2
0
static void *playlist_get_info_func(void *arg)
{
    GList *node;
    gboolean update_playlistwin = FALSE, update_mainwin = FALSE;
    PlaylistEntry *entry;

    while (playlist_get_info_going)
    {
        if (cfg.get_info_on_load && playlist_get_info_scan_active)
        {
            PL_LOCK();
            for (node = get_playlist(); node; node = g_list_next(node))
            {
                entry = node->data;
                if (entry->title || entry->length != -1)
                    continue;
                if (!playlist_get_info_entry(entry))
                {
                    if (g_list_index(get_playlist(), entry) == -1)
                        /* Entry disapeared while we
                           looked it up.  Restart. */
                        node = get_playlist();
                }
                else if (entry->title || entry->length != -1)
                {
                    update_playlistwin = TRUE;
                    if (entry == playlist_position)
                        update_mainwin = TRUE;
                    break;
                }
            }
            PL_UNLOCK();

            if (!node)
                playlist_get_info_scan_active = FALSE;
        }
        else if (!cfg.get_info_on_load && cfg.get_info_on_demand &&
                 cfg.playlist_visible && !cfg.playlist_shaded)
        {
            gboolean found = FALSE;

            PL_LOCK();
            if (!get_playlist())
            {
                PL_UNLOCK();
                xmms_usleep(1000000);
                continue;
            }

            for (node = g_list_nth(get_playlist(), playlistwin_get_toprow());
                    node && playlistwin_item_visible(g_list_position(get_playlist(), node));
                    node = g_list_next(node))
            {
                entry = node->data;
                if (entry->title || entry->length != -1)
                    continue;

                if (!playlist_get_info_entry(entry))
                {
                    if (g_list_index(get_playlist(), entry) == -1)
                        /* Entry disapeared while we
                           looked it up.  Restart. */
                        node = g_list_nth(get_playlist(), playlistwin_get_toprow());
                }
                else if (entry->title || entry->length != -1)
                {
                    update_playlistwin = TRUE;
                    if (entry == playlist_position)
                        update_mainwin = TRUE;
                    found = TRUE;
                    break;
                }
            }
            PL_UNLOCK();
            if (!found)
            {
                xmms_usleep(500000);
                continue;
            }
        }
        else
            xmms_usleep(500000);

        if (update_playlistwin)
        {
            playlistwin_update_list();
            update_playlistwin = FALSE;
        }
        if (update_mainwin)
        {
            mainwin_set_info_text();
            update_mainwin = FALSE;
        }
    }
    pthread_exit(NULL);
}
Ejemplo n.º 3
0
static void *play_loop(void *arg)
{
  enum uade_control_state controlstate = UADE_S_STATE;
  int ret;
  int left = 0;
  uint8_t space[UADE_MAX_MESSAGE_SIZE];
  struct uade_msg *um = (struct uade_msg *) space;
  int subsong_end = 0;
  uint16_t *sm;
  int i;
  unsigned int play_bytes, tailbytes = 0;
  uint64_t subsong_bytes = 0;
  char *reason;
  uint32_t *u32ptr;
  int writeoffs;
  int framesize = UADE_CHANNELS * UADE_BYTES_PER_SAMPLE;
  int song_end_trigger = 0;
  int64_t skip_bytes = 0;

  uade_lock();
  record_playtime = 1;
  uade_unlock();

  while (1) {
    if (controlstate == UADE_S_STATE) {

      assert(left == 0);

      if (abort_playing) {
    uade_lock();
    record_playtime = 0;
    uade_unlock();
    break;
      }

      uade_lock();
      if (uade_seek_forward) {
    skip_bytes += uade_seek_forward * UADE_BYTES_PER_FRAME * state.config.frequency;
    uade_ip.output->flush(uade_ip.output->written_time() + uade_seek_forward * 1000);
    uade_seek_forward = 0;
      }
      if (uade_select_sub != -1) {
    state.song->cur_subsong = uade_select_sub;

    uade_change_subsong(&state);

    uade_ip.output->flush(0);
    uade_select_sub = -1;
    subsong_end = 0;
    subsong_bytes = 0;

    /* we do this to avoid timeout, and to not record playtime */
    state.song->out_bytes = 0;
    record_playtime = 0;

    uade_info_string();
      }

      if (subsong_end && song_end_trigger == 0) {

    if (state.song->cur_subsong == -1 || state.song->max_subsong == -1) {
      song_end_trigger = 1;

    } else {

      state.song->cur_subsong++;

      if (state.song->cur_subsong > state.song->max_subsong) {
        song_end_trigger = 1;
      } else {
        int x = 0;

        uade_change_subsong(&state);

        while (uade_ip.output->buffer_playing()) {
          /* Sleep at most 5 secs */
          if (x >= 500) {
        __android_log_print(ANDROID_LOG_VERBOSE, "UADE", "UADE: blocking work-around activated.\n");
        break;
          }
          x++;
          xmms_usleep(10000);
        }
        uade_ip.output->flush(0);
        subsong_end = 0;
        subsong_bytes = 0;

        uade_gui_subsong_changed(state.song->cur_subsong);

        uade_info_string();
      }
    }
      }
      uade_unlock();

      if (song_end_trigger) {
    /* We must drain the audio fast if abort_playing happens (e.g.
       the user changes song when we are here waiting the sound device) */
    while (uade_ip.output->buffer_playing() && abort_playing == 0)

      xmms_usleep(10000);
    break;
      }

      left = uade_read_request(&state.ipc);

      if (uade_send_short_message(UADE_COMMAND_TOKEN, &state.ipc)) {
    __android_log_print(ANDROID_LOG_VERBOSE, "UADE", "Can not send token.\n");
    return NULL;
      }
      controlstate = UADE_R_STATE;

    } else {

      if (uade_receive_message(um, sizeof(space), &state.ipc) <= 0) {
    __android_log_print(ANDROID_LOG_VERBOSE, "UADE", "Can not receive events from uade\n");
    exit(1);
      }

      switch (um->msgtype) {

      case UADE_COMMAND_TOKEN:
    controlstate = UADE_S_STATE;
    break;

      case UADE_REPLY_DATA:
    sm = (uint16_t *) um->data;
    for (i = 0; i < um->size; i += 2) {
      *sm = ntohs(*sm);
      sm++;
    }

    if (subsong_end) {
      play_bytes = tailbytes;
      tailbytes = 0;
    } else {
      play_bytes = um->size;
    }

    if (subsong_end == 0 && song_end_trigger == 0 &&
        uade_test_silence(um->data, play_bytes, &state)) {
      subsong_end = 1;
    }

    subsong_bytes += play_bytes;
    uade_lock();
    state.song->out_bytes += play_bytes;
    uade_unlock();

    if (skip_bytes > 0) {
      if (play_bytes <= skip_bytes) {
        skip_bytes -= play_bytes;
        play_bytes = 0;
      } else {
        play_bytes -= skip_bytes;
        skip_bytes = 0;
      }
    }

    uade_effect_run(&state.effects, (int16_t *) um->data, play_bytes / framesize);
    uade_ip.add_vis_pcm(uade_ip.output->written_time(), sample_format, UADE_CHANNELS, play_bytes, um->data);

    writeoffs = 0;
    while (writeoffs < play_bytes) {
      int writable;
      while ((writable = uade_ip.output->buffer_free()) <= 0) {
        if (abort_playing)
          goto nowrite;
        xmms_usleep(10000);
      }

      if (writable > (play_bytes - writeoffs))
        writable = play_bytes - writeoffs;

      uade_ip.output->write_audio(&um->data[writeoffs], writable);

      writeoffs += writable;
    }


      nowrite:

    if (state.config.timeout != -1 && state.config.use_timeouts) {
      if (song_end_trigger == 0) {
        uade_lock();
        if (state.song->out_bytes / (UADE_BYTES_PER_FRAME * state.config.frequency) >= state.config.timeout) {
          song_end_trigger = 1;
          record_playtime = 0;
        }
        uade_unlock();
      }
    }

    if (state.config.subsong_timeout != -1 && state.config.use_timeouts) {
      if (subsong_end == 0 && song_end_trigger == 0) {
        if (subsong_bytes / (UADE_BYTES_PER_FRAME * state.config.frequency) >= state.config.subsong_timeout) {
          subsong_end = 1;
          record_playtime = 0;
        }
      }
    }

    assert (left >= um->size);
    left -= um->size;
    break;

      case UADE_REPLY_FORMATNAME:
    uade_check_fix_string(um, 128);
    strlcpy(gui_formatname, (char *) um->data, sizeof gui_formatname);
    strlcpy(state.song->formatname, (char *) um->data, sizeof state.song->formatname);
    break;

      case UADE_REPLY_MODULENAME:
    uade_check_fix_string(um, 128);
    strlcpy(gui_modulename, (char *) um->data, sizeof gui_modulename);
    strlcpy(state.song->modulename, (char *) um->data, sizeof state.song->modulename);
    break;

      case UADE_REPLY_MSG:
    uade_check_fix_string(um, 128);
    plugindebug("Message: %s\n", (char *) um->data);
    break;

      case UADE_REPLY_PLAYERNAME:
    uade_check_fix_string(um, 128);
    strlcpy(gui_playername, (char *) um->data, sizeof gui_playername);
    strlcpy(state.song->playername, (char *) um->data, sizeof state.song->playername);
    break;

      case UADE_REPLY_SONG_END:
    if (um->size < 9) {
      __android_log_print(ANDROID_LOG_VERBOSE, "UADE", "Invalid song end reply\n");
      exit(1);
    }
    tailbytes = ntohl(((uint32_t *) um->data)[0]);
    /* next ntohl() is only there for a principle. it is not useful */
    if (ntohl(((uint32_t *) um->data)[1]) == 0) {
      /* normal happy song end. go to next subsong if any */
      subsong_end = 1;
    } else {
      /* unhappy song end (error in the 68k side). skip to next song
         ignoring possible subsongs */
      song_end_trigger = 1;
    }
    i = 0;
    reason = (char *) &um->data[8];
    while (reason[i] && i < (um->size - 8))
      i++;
    if (reason[i] != 0 || (i != (um->size - 9))) {
      __android_log_print(ANDROID_LOG_VERBOSE, "UADE", "Broken reason string with song end notice\n");
      exit(1);
    }
    break;

      case UADE_REPLY_SUBSONG_INFO:
    if (um->size != 12) {
      __android_log_print(ANDROID_LOG_VERBOSE, "UADE", "subsong info: too short a message\n");
      exit(1);
    }
    u32ptr = (uint32_t *) um->data;
    uade_lock();
    state.song->min_subsong = ntohl(u32ptr[0]);
    state.song->max_subsong = ntohl(u32ptr[1]);
    state.song->cur_subsong = ntohl(u32ptr[2]);

    if (!(-1 <= state.song->min_subsong && state.song->min_subsong <= state.song->cur_subsong && state.song->cur_subsong <= state.song->max_subsong)) {
      int tempmin = state.song->min_subsong, tempmax = state.song->max_subsong;
      __android_log_print(ANDROID_LOG_VERBOSE, "UADE", "uade: The player is broken. Subsong info does not match with %s.\n", gui_filename);
      state.song->min_subsong = tempmin <= tempmax ? tempmin : tempmax;
      state.song->max_subsong = tempmax >= tempmin ? tempmax : tempmin;
      if (state.song->cur_subsong > state.song->max_subsong)
        state.song->max_subsong = state.song->cur_subsong;
      else if (state.song->cur_subsong < state.song->min_subsong)
        state.song->min_subsong = state.song->cur_subsong;
    }
    uade_unlock();
    break;

      default:
    __android_log_print(ANDROID_LOG_VERBOSE, "UADE", "Expected sound data. got %d.\n", um->msgtype);
    plugin_disabled = 1;
    return NULL;
      }
    }
  }

  last_beat_played = 1;

  if (uade_send_short_message(UADE_COMMAND_REBOOT, &state.ipc)) {
    __android_log_print(ANDROID_LOG_VERBOSE, "UADE", "Can not send reboot.\n");
    return NULL;
  }

  if (uade_send_short_message(UADE_COMMAND_TOKEN, &state.ipc)) {
    __android_log_print(ANDROID_LOG_VERBOSE, "UADE", "Can not send token.\n");
    return NULL;
  }

  do {
    ret = uade_receive_message(um, sizeof(space), &state.ipc);
    if (ret < 0) {
      __android_log_print(ANDROID_LOG_VERBOSE, "UADE", "Can not receive events from uade.\n");
      return NULL;
    }
    if (ret == 0) {
      __android_log_print(ANDROID_LOG_VERBOSE, "UADE", "End of input after reboot.\n");
      return NULL;
    }
  } while (um->msgtype != UADE_COMMAND_TOKEN);

  return NULL;
}
Ejemplo n.º 4
0
void *play_loop_(void *arg)
{
	unsigned written_time_last = 0, bh_index_last_w = 0, bh_index_last_o = BITRATE_HIST_SIZE, blocksize = 1;
	FLAC__uint64 decode_position_last = 0, decode_position_frame_last = 0, decode_position_frame = 0;

	(void)arg;

	while(stream_data_.is_playing) {
		if(!stream_data_.eof) {
			while(sample_buffer_last_ - sample_buffer_first_ < SAMPLES_PER_WRITE) {
				unsigned s;

				s = sample_buffer_last_ - sample_buffer_first_;
				if(FLAC__stream_decoder_get_state(decoder_) == FLAC__STREAM_DECODER_END_OF_STREAM) {
					stream_data_.eof = true;
					break;
				}
				else if(!FLAC__stream_decoder_process_single(decoder_)) {
					/*@@@ this should probably be a dialog */
					fprintf(stderr, "libxmms-flac: READ ERROR processing frame\n");
					stream_data_.eof = true;
					break;
				}
				blocksize = sample_buffer_last_ - sample_buffer_first_ - s;
				decode_position_frame_last = decode_position_frame;
				if(stream_data_.is_http_source || !FLAC__stream_decoder_get_decode_position(decoder_, &decode_position_frame))
					decode_position_frame = 0;
			}
			if(sample_buffer_last_ - sample_buffer_first_ > 0) {
				const unsigned n = min(sample_buffer_last_ - sample_buffer_first_, SAMPLES_PER_WRITE);
				int bytes = n * stream_data_.channels * stream_data_.sample_format_bytes_per_sample;
				FLAC__byte *sample_buffer_start = sample_buffer_ + sample_buffer_first_ * stream_data_.channels * stream_data_.sample_format_bytes_per_sample;
				unsigned written_time, bh_index_w;
				FLAC__uint64 decode_position;

				sample_buffer_first_ += n;
				flac_ip.add_vis_pcm(flac_ip.output->written_time(), stream_data_.sample_format, stream_data_.channels, bytes, sample_buffer_start);
				while(flac_ip.output->buffer_free() < (int)bytes && stream_data_.is_playing && stream_data_.seek_to_in_sec == -1)
					xmms_usleep(10000);
				if(stream_data_.is_playing && stream_data_.seek_to_in_sec == -1)
					flac_ip.output->write_audio(sample_buffer_start, bytes);

				/* compute current bitrate */

				written_time = flac_ip.output->written_time();
				bh_index_w = written_time / BITRATE_HIST_SEGMENT_MSEC % BITRATE_HIST_SIZE;
				if(bh_index_w != bh_index_last_w) {
					bh_index_last_w = bh_index_w;
					decode_position = decode_position_frame - (double)(sample_buffer_last_ - sample_buffer_first_) * (double)(decode_position_frame - decode_position_frame_last) / (double)blocksize;
					bitrate_history_[(bh_index_w + BITRATE_HIST_SIZE - 1) % BITRATE_HIST_SIZE] =
						decode_position > decode_position_last && written_time > written_time_last ?
							8000 * (decode_position - decode_position_last) / (written_time - written_time_last) :
							stream_data_.sample_rate * stream_data_.channels * stream_data_.bits_per_sample;
					decode_position_last = decode_position;
					written_time_last = written_time;
				}
			}
			else {
				stream_data_.eof = true;
				xmms_usleep(10000);
			}
		}
		else
			xmms_usleep(10000);
		if(!stream_data_.is_http_source && stream_data_.seek_to_in_sec != -1) {
			const double distance = (double)stream_data_.seek_to_in_sec * 1000.0 / (double)stream_data_.length_in_msec;
			FLAC__uint64 target_sample = (FLAC__uint64)(distance * (double)stream_data_.total_samples);
			if(stream_data_.total_samples > 0 && target_sample >= stream_data_.total_samples)
				target_sample = stream_data_.total_samples - 1;
			if(FLAC__stream_decoder_seek_absolute(decoder_, target_sample)) {
				flac_ip.output->flush(stream_data_.seek_to_in_sec * 1000);
				bh_index_last_w = bh_index_last_o = flac_ip.output->output_time() / BITRATE_HIST_SEGMENT_MSEC % BITRATE_HIST_SIZE;
				if(!FLAC__stream_decoder_get_decode_position(decoder_, &decode_position_frame))
					decode_position_frame = 0;
				stream_data_.eof = false;
				sample_buffer_first_ = sample_buffer_last_ = 0;
			}
			else if(FLAC__stream_decoder_get_state(decoder_) == FLAC__STREAM_DECODER_SEEK_ERROR) {
				/*@@@ this should probably be a dialog */
				fprintf(stderr, "libxmms-flac: SEEK ERROR\n");
				FLAC__stream_decoder_flush(decoder_);
				stream_data_.eof = false;
				sample_buffer_first_ = sample_buffer_last_ = 0;
			}
			stream_data_.seek_to_in_sec = -1;
		}
		else {
			/* display the right bitrate from history */
			unsigned bh_index_o = flac_ip.output->output_time() / BITRATE_HIST_SEGMENT_MSEC % BITRATE_HIST_SIZE;
			if(bh_index_o != bh_index_last_o && bh_index_o != bh_index_last_w && bh_index_o != (bh_index_last_w + 1) % BITRATE_HIST_SIZE) {
				bh_index_last_o = bh_index_o;
				flac_ip.set_info(stream_data_.title, stream_data_.length_in_msec, bitrate_history_[bh_index_o], stream_data_.sample_rate, stream_data_.channels);
			}
		}
	}

	safe_decoder_finish_(decoder_);

	/* are these two calls necessary? */
	flac_ip.output->buffer_free();
	flac_ip.output->buffer_free();

	g_free(stream_data_.title);

	pthread_exit(NULL);
	return 0; /* to silence the compiler warning about not returning a value */
}
Ejemplo n.º 5
0
void *oss_loop(void *arg)
{
	gint length, cnt;
	fd_set set;
	struct timeval tv;

	while (going)
	{
		if (oss_used() > prebuffer_size)
			prebuffer = FALSE;
		if (oss_used() > 0 && !paused && !prebuffer)
		{
			tv.tv_sec = 0;
			tv.tv_usec = 10000;
			FD_ZERO(&set);
			FD_SET(fd, &set);
			if(!select_works || (select(fd + 1, NULL, &set, NULL, &tv) > 0))
			{
				length = MIN(blk_size, oss_used());
				while (length > 0)
				{
					cnt = MIN(length,buffer_size-rd_index);
					oss_write_audio(buffer + rd_index, cnt);
					rd_index=(rd_index+cnt)%buffer_size;
					length-=cnt;				
				}
				if (!oss_used())
					ioctl(fd, SNDCTL_DSP_POST, 0);
			}
		}
		else
			xmms_usleep(10000);
		oss_calc_device_buffer_used();
		if (do_pause && !paused)
		{
			do_pause = FALSE;
			paused = TRUE;
			/*
			 * We lose some data here that is sent to the
			 * soundcard, but not yet played.  I don't
			 * think this is worth fixing.
			 */
			ioctl(fd, SNDCTL_DSP_RESET, 0);
		}
		else if (unpause && paused)
		{
			unpause = FALSE;
			close(fd);
			fd = open(device_name, O_WRONLY);
			oss_set_audio_params();
			paused = FALSE;
		}

		if (flush != -1)
		{
			/*
			 * This close and open is a work around of a
			 * bug that exists in some drivers which cause
			 * the driver to get f****d up by a reset
			 */

			ioctl(fd, SNDCTL_DSP_RESET, 0);
			close(fd);
			fd = open(device_name, O_WRONLY);
			oss_set_audio_params();
			output_time_offset = flush;
			written = ((guint64)flush * input.bps) / 1000;
			rd_index = wr_index = output_bytes = 0;
			flush = -1;
			prebuffer = TRUE;
		}

	}

	ioctl(fd, SNDCTL_DSP_RESET, 0);
	close(fd);
	g_free(buffer);
	pthread_exit(NULL);
}