Exemple #1
0
void noia_log_finalize(void)
{
    if (sLogFD > 1) {
        LOG_INFO1("Closing log file. Bye!");
        write(sLogFD, scLogGoodByeText, sizeof(scLogGoodByeText) - 1);
        close(sLogFD);
    } else {
        LOG_INFO1("Bye!");
        write(sLogFD, scLogGoodByeText, sizeof(scLogGoodByeText) - 1);
    }
    sLogFD = NOIA_DEFAULT_LOG_FD;
}
Exemple #2
0
void *ices_runner (void *arg)
{
    struct runner *run = arg;
    struct instance *current;

#ifdef HAVE_SCHED_GET_PRIORITY_MAX
    int policy;
    struct sched_param param;

    pthread_getschedparam (pthread_self(), &policy, &param);
    param . sched_priority = sched_get_priority_min (SCHED_OTHER);

    if (pthread_setschedparam (pthread_self(), SCHED_OTHER, &param))
    {
        LOG_ERROR1 ("failed to set priority: %s", strerror (errno));
    }
    else
        LOG_INFO0 ("set priority on runner");
#endif
    LOG_INFO1 ("Runner %d ready", run->id);

    while (1)
    {
        input_buffer *buffer;
        
        buffer = runner_wait_for_data (run);

        if (buffer == NULL)
            break;

        current = run->instances;

        while (current != NULL)
        {
            add_to_stream (current, buffer);
            current = current->next;
        }

        send_to_runner (run->next, buffer);
    }

    runner_close (run->next);
    LOG_DEBUG1 ("Runner thread %d cleaning up streams", run->id);
    current = run->instances;
    while (current)
    {
        struct instance *next;
        next = current->next;
        stream_cleanup (current);
        current = next;
    }
    close (run->fd[0]);
    run->fd[0] = -1;
    run->not_running = 1;
    LOG_DEBUG1 ("Runner thread %d finshed", run->id);
    
    return NULL;
}
Exemple #3
0
void* noia_wayland_engine_run(void* data)
{
    noia_environment_on_enter_new_thread(0, "noia:wayland");

    LOG_INFO1("Threads: Wayland thread started");
    NoiaWaylandEngine* engine = (NoiaWaylandEngine*) data;
    wl_display_run(engine->display);
    return NULL;
}
Exemple #4
0
void noia_log_initialize(const char* filename)
{
    if (filename and (strlen(filename) > 0)) {
        setbuf(stdout, NULL);
        sLogFD = noia_environment_open_file(filename, 0, RUNTIME_PATH);
        if (sLogFD == -1) {
            sLogFD = NOIA_DEFAULT_LOG_FD;
            LOG_ERROR("Log file could not be opened!");
        }
    }

    noia_debug_config()->print = noia_log_print;
    noia_debug_config()->print_backtrace = noia_log_backtrace;
    noia_debug_config()->print_failure = noia_log_failure;

    write(sLogFD, scLogWelcomeText, sizeof(scLogWelcomeText) - 1);
    LOG_INFO1("Build: " __TIME__ " " __DATE__ "; Version: " NOIA_VERSION);
}
Exemple #5
0
void *metadata_thread_stdin(void *arg)
{
    char buf[1024];
    input_module_t *mod = arg;

    if (ices_config->background)
    {
        LOG_INFO0("Metadata thread shutting down, tried to use "
                "stdin from background");
        return NULL;
    }
    while(1)
    {
        char **md = NULL;
        int comments = 0;
        int wait_for_data = 1;

        /* wait for data */
        while (wait_for_data)
        {
            struct timeval t;
            fd_set fds;
            FD_ZERO (&fds);
            FD_SET (0, &fds);
            t.tv_sec = 0;
            t.tv_usec = 150;

            switch (select (1, &fds, NULL, NULL, &t))
            {
            case 1:
                wait_for_data = 0;
            case 0:
                break;
            default:
                if (errno != EAGAIN)
                {
                    LOG_INFO1 ("shutting down thread (%d)", errno);
                    return NULL; /* problem get out quick */
                }
                break;
            }

            if (ices_config->shutdown)
            {
                LOG_INFO0 ("metadata thread shutting down");
                return NULL;
            }
        }
        while(fgets(buf, 1024, stdin))
        {
            if(buf[0] == '\n')
                break;
            else
            {
                if(buf[strlen(buf)-1] == '\n')
                    buf[strlen(buf)-1] = 0;
                md = realloc(md, (comments+2)*sizeof(char *));
                md[comments] = malloc(strlen(buf)+1);

                memcpy(md[comments], buf, strlen(buf)+1);
                comments++;
            }
        }

        if(md) /* Don't update if there's nothing there */
        {
            md[comments]=0;

            /* Now, let's actually use the new data */
            LOG_INFO0("Updating metadata");
            mod->handle_event(mod,EVENT_METADATAUPDATE,md);
        }

    }
}
Exemple #6
0
/* Core streaming function for this module
 * This is what actually produces the data which gets streamed.
 *
 * returns:  >0  Number of bytes read
 *            0  Non-fatal error.
 *           <0  Fatal error.
 */
static int playlist_read(void *self, ref_buffer *rb)
{
    playlist_state_t *pl = (playlist_state_t *)self;
    int bytes;
    unsigned char *buf;
    char *newfn;
    int result;
    ogg_page og;

    if (pl->errors > 5) 
    {
        LOG_WARN0("Too many consecutive errors - exiting");
        return -1;
    }

    if (!pl->current_file || pl->nexttrack) 
    {
        pl->nexttrack = 0;

        if (pl->current_file && strcmp (pl->filename, "-"))
        {
            fclose(pl->current_file);
            pl->current_file = NULL;
        }
	if (pl->file_ended)
	{
	    pl->file_ended(pl->data, pl->filename);
	}

        newfn = pl->get_filename(pl->data);
        if (!newfn)
        {
            LOG_INFO0("No more filenames available, end of playlist");
            return -1; /* No more files available */
        }

        if (strcmp (newfn, "-"))
        {
            if (!pl->allow_repeat && pl->filename && !strcmp(pl->filename, newfn))
            {
                LOG_ERROR0("Cannot play same file twice in a row, skipping");
                pl->errors++;
                pl->free_filename (pl->data, newfn);
                return 0;
            }
            pl->free_filename(pl->data, pl->filename);
            pl->filename = newfn;

            pl->current_file = fopen(pl->filename, "rb");
            if (!pl->current_file) 
            {
                LOG_WARN2("Error opening file \"%s\": %s",pl->filename, strerror(errno));
                pl->errors++;
                return 0;
            }
            LOG_INFO1("Currently playing \"%s\"", pl->filename);
        }
        else
        {
            LOG_INFO0("Currently playing from stdin");
            pl->current_file = stdin;
            pl->free_filename(pl->data, pl->filename);
            pl->filename = newfn;
        }

        /* Reinit sync, so that dead data from previous file is discarded */
        ogg_sync_clear(&pl->oy);
        ogg_sync_init(&pl->oy);
    }
    input_sleep ();

    while(1)
    {
        result = ogg_sync_pageout(&pl->oy, &og);
        if(result < 0)
            LOG_WARN1("Corrupt or missing data in file (%s)", pl->filename);
        else if(result > 0)
        {
            if (ogg_page_bos (&og))
            {
               if (ogg_page_serialno (&og) == pl->current_serial)
                   LOG_WARN1 ("detected duplicate serial number reading \"%s\"", pl->filename);

               pl->current_serial = ogg_page_serialno (&og);
            }
            if (input_calculate_ogg_sleep (&og) < 0)
            {
                pl->nexttrack = 1;
                return 0;
            }
            rb->len = og.header_len + og.body_len;
            rb->buf = malloc(rb->len);
            rb->aux_data = og.header_len;

            memcpy(rb->buf, og.header, og.header_len);
            memcpy(rb->buf+og.header_len, og.body, og.body_len);
            if(ogg_page_granulepos(&og)==0)
                rb->critical = 1;
            break;
        }

        /* If we got to here, we didn't have enough data. */
        buf = ogg_sync_buffer(&pl->oy, BUFSIZE);
        bytes = fread(buf,1, BUFSIZE, pl->current_file);
        if (bytes <= 0) 
        {
            if (feof(pl->current_file)) 
            {
                pl->nexttrack = 1;
                return playlist_read(pl,rb);
            } 
            else 
            {
                LOG_ERROR2("Read error from \"%s\": %s", pl->filename, strerror(errno));
                fclose(pl->current_file);
                pl->current_file=NULL;
                pl->errors++;
                return 0; 
            }
        }
        else
            ogg_sync_wrote(&pl->oy, bytes);
    }

    pl->errors=0;

    return rb->len;
}
Exemple #7
0
/* The main loop for each instance. Gets data passed to it from the stream
 * manager (which gets it from the input module), and streams it to the
 * specified server
 */
void *ices_instance_stream(void *arg)
{
	int ret, shouterr;
	ref_buffer *buffer;
	char *connip;
	stream_description *sdsc = arg;
	instance_t *stream = sdsc->stream;
	input_module_t *inmod = sdsc->input;
	int reencoding = (inmod->type == ICES_INPUT_VORBIS) && stream->encode;
	int encoding = (inmod->type == ICES_INPUT_PCM) && stream->encode;
    char *stream_name = NULL, *stream_genre = NULL, *stream_description = NULL;
    char *user = NULL;
	
	vorbis_comment_init(&sdsc->vc);

	sdsc->shout = shout_new();

	/* we only support the ice protocol and vorbis streams currently */
	shout_set_format(sdsc->shout, SHOUT_FORMAT_VORBIS);
	//shout_set_protocol(sdsc->shout, SHOUT_PROTOCOL_ICE);
	shout_set_protocol(sdsc->shout, SHOUT_PROTOCOL_HTTP);

    signal(SIGPIPE, signal_hup_handler);

	connip = malloc(16);
	if(!resolver_getip(stream->hostname, connip, 16))
	{
		LOG_ERROR1("Could not resolve hostname \"%s\"", stream->hostname);
		free(connip);
		stream->died = 1;
		return NULL;
	}

	if (!(shout_set_host(sdsc->shout, connip)) == SHOUTERR_SUCCESS) {
		LOG_ERROR1("libshout error: %s\n", shout_get_error(sdsc->shout));
		free(connip);
		stream->died = 1;
		return NULL;
	}

	shout_set_port(sdsc->shout, stream->port);
	if (!(shout_set_password(sdsc->shout, stream->password)) == SHOUTERR_SUCCESS) {
		LOG_ERROR1("libshout error: %s\n", shout_get_error(sdsc->shout));
		free(connip);
		stream->died = 1;
		return NULL;
	}
    if (stream->user)
        user = stream->user;
    else
        user = "******";

    if(shout_set_user(sdsc->shout, user) != SHOUTERR_SUCCESS) {
		LOG_ERROR1("libshout error: %s\n", shout_get_error(sdsc->shout));
		free(connip);
		stream->died = 1;
		return NULL;
    }

	if (!(shout_set_agent(sdsc->shout, VERSIONSTRING)) == SHOUTERR_SUCCESS) {
		LOG_ERROR1("libshout error: %s\n", shout_get_error(sdsc->shout));
		free(connip);
		stream->died = 1;
		return NULL;
	}

	if (!(shout_set_mount(sdsc->shout, stream->mount)) == SHOUTERR_SUCCESS) {
		LOG_ERROR1("libshout error: %s\n", shout_get_error(sdsc->shout));
		free(connip);
		stream->died = 1;
		return NULL;
	}

	/* set the metadata for the stream */
    if(stream->stream_name)
        stream_name = stream->stream_name;
    else if (ices_config->stream_name)
        stream_name = ices_config->stream_name;

    if(stream->stream_description)
        stream_description = stream->stream_description;
    else if (ices_config->stream_description)
        stream_description = ices_config->stream_description;

    if(stream->stream_genre)
        stream_genre = stream->stream_genre;
    else if (ices_config->stream_genre)
        stream_genre = ices_config->stream_genre;

    if(stream_name)
		if (!(shout_set_name(sdsc->shout, stream_name)) == SHOUTERR_SUCCESS) {
			LOG_ERROR1("libshout error: %s\n", shout_get_error(sdsc->shout));
			free(connip);
			stream->died = 1;
			return NULL;
		}
	if (stream_genre)
		if (!(shout_set_genre(sdsc->shout, stream_genre)) == SHOUTERR_SUCCESS) {
			LOG_ERROR1("libshout error: %s\n", shout_get_error(sdsc->shout));
			free(connip);
			stream->died = 1;
			return NULL;
		}
	if (stream_description)
		if (!(shout_set_description(sdsc->shout, stream_description)) == SHOUTERR_SUCCESS) {
			LOG_ERROR1("libshout error: %s\n", shout_get_error(sdsc->shout));
			free(connip);
			stream->died = 1;
			return NULL;
		}

    if(stream->downmix && encoding && stream->channels == 1) {
        stream->channels = 1;
        sdsc->downmix = downmix_initialise();
    }

    if(stream->resampleinrate && stream->resampleoutrate && encoding) {
        stream->samplerate = stream->resampleoutrate;
        sdsc->resamp = resample_initialise(stream->channels, 
                stream->resampleinrate, stream->resampleoutrate);
    }

	if(encoding)
	{
		if(inmod->metadata_update)
			inmod->metadata_update(inmod->internal, &sdsc->vc);
		sdsc->enc = encode_initialise(stream->channels, stream->samplerate,
				stream->managed, stream->min_br, stream->nom_br, stream->max_br,
                stream->quality, stream->serial++, &sdsc->vc);
        if(!sdsc->enc) {
            LOG_ERROR0("Failed to configure encoder");
		    stream->died = 1;
            return NULL; /* FIXME: probably leaking some memory here */
        }
	}
	else if(reencoding)
		sdsc->reenc = reencode_init(stream);

    if(stream->savefilename != NULL) 
    {
        stream->savefile = fopen(stream->savefilename, "wb");
        if(!stream->savefile)
            LOG_ERROR2("Failed to open stream save file %s: %s", 
                    stream->savefilename, strerror(errno));
        else
            LOG_INFO1("Saving stream to file %s", stream->savefilename);
    }

	if((shouterr = shout_open(sdsc->shout)) == SHOUTERR_SUCCESS)
	{
		LOG_INFO3("Connected to server: %s:%d%s", 
				shout_get_host(sdsc->shout), shout_get_port(sdsc->shout), shout_get_mount(sdsc->shout));

		while(1)
		{
			if(stream->buffer_failures > MAX_ERRORS)
			{
				LOG_WARN0("Too many errors, shutting down");
				break;
			}

			buffer = stream_wait_for_data(stream);

			/* buffer being NULL means that either a fatal error occured,
			 * or we've been told to shut down
			 */
			if(!buffer)
				break;

			/* If data is NULL or length is 0, we should just skip this one.
			 * Probably, we've been signalled to shut down, and that'll be
			 * caught next iteration. Add to the error count just in case,
			 * so that we eventually break out anyway 
			 */
			if(!buffer->buf || !buffer->len)
			{
				LOG_WARN0("Bad buffer dequeued!");
				stream->buffer_failures++;
				continue; 
			}

            if(stream->wait_for_critical)
            {
                LOG_INFO0("Trying restart on new substream");
                stream->wait_for_critical = 0;
            }

            ret = process_and_send_buffer(sdsc, buffer);

            /* No data produced, do nothing */
            if(ret == -1)
                ;
            /* Fatal error */
            else if(ret == -2)
            {
                LOG_ERROR0("Serious error, waiting to restart on "
                           "next substream. Stream temporarily suspended.");
                /* Set to wait until a critical buffer comes through (start of
                 * a new substream, typically), and flush existing queue.
                 */
                thread_mutex_lock(&ices_config->flush_lock);
                stream->wait_for_critical = 1;
                input_flush_queue(stream->queue, 0);
                thread_mutex_unlock(&ices_config->flush_lock);
            }
            /* Non-fatal shout error */
            else if(ret == 0)
			{
				LOG_ERROR2("Send error: %s (%s)", 
                        shout_get_error(sdsc->shout), strerror(errno));
				if(shout_get_errno(sdsc->shout) == SHOUTERR_SOCKET)
				{
					int i=0;

					/* While we're trying to reconnect, don't receive data
					 * to this instance, or we'll overflow once reconnect
					 * succeeds
					 */
					thread_mutex_lock(&ices_config->flush_lock);
					stream->skip = 1;

					/* Also, flush the current queue */
					input_flush_queue(stream->queue, 1);
					thread_mutex_unlock(&ices_config->flush_lock);
					
					while((i < stream->reconnect_attempts ||
							stream->reconnect_attempts==-1) && 
                            !ices_config->shutdown)
					{
						i++;
						LOG_WARN0("Trying reconnect after server socket error");
						shout_close(sdsc->shout);
						if((shouterr = shout_open(sdsc->shout)) == SHOUTERR_SUCCESS)
						{
							LOG_INFO3("Connected to server: %s:%d%s", 
                                    shout_get_host(sdsc->shout), shout_get_port(sdsc->shout), 
                                    shout_get_mount(sdsc->shout));
                            /* This stream can't restart until the next
                             * logical stream comes along, since the
                             * server won't have any cached headers for
                             * this source/connection. So, don't continue
                             * yet.
                             */
                            thread_mutex_lock(&ices_config->flush_lock);
                            stream->wait_for_critical = 1;
                            input_flush_queue(stream->queue, 0);
                            thread_mutex_unlock(&ices_config->flush_lock);
							break;
						}
						else
						{
							LOG_ERROR3("Failed to reconnect to %s:%d (%s)",
								shout_get_host(sdsc->shout),shout_get_port(sdsc->shout),
								shout_get_error(sdsc->shout));
							if(i==stream->reconnect_attempts)
							{
								LOG_ERROR0("Reconnect failed too many times, "
										  "giving up.");
                                /* We want to die now */
								stream->buffer_failures = MAX_ERRORS+1; 
							}
							else /* Don't try again too soon */
								sleep(stream->reconnect_delay); 
						}
					}
					stream->skip = 0;
				}
				stream->buffer_failures++;
			}
			stream_release_buffer(buffer);
		}
	}
	else
	{
		LOG_ERROR3("Failed initial connect to %s:%d (%s)", 
				shout_get_host(sdsc->shout),shout_get_port(sdsc->shout), shout_get_error(sdsc->shout));
	}
	
	shout_close(sdsc->shout);

    if(stream->savefile != NULL) 
        fclose(stream->savefile);

    shout_free(sdsc->shout);
	encode_clear(sdsc->enc);
	reencode_clear(sdsc->reenc);
    downmix_clear(sdsc->downmix);
    resample_clear(sdsc->resamp);
	vorbis_comment_clear(&sdsc->vc);

	stream->died = 1;
	return NULL;
}