Exemplo n.º 1
0
void sess_connect()
{
  assert(g_session.username && g_session.password);

  sess_disconnect();

  if (!(g_session.dsfy = despotify_init_client(sess_callback, NULL, true, true)))
    panic("despotify_init_client(...) failed");

  play_state = PAUSE;
  pthread_create(&thread, NULL, &thread_loop, g_session.dsfy);

  // Login with credentials set by sess_username/sess_password.
  if (!despotify_authenticate(g_session.dsfy, g_session.username, g_session.password)) {
    g_session.state = SESS_ERROR;
    log_append(despotify_get_error(g_session.dsfy));
    despotify_exit(g_session.dsfy);
    // Switch to log view.
    ui_show(UI_SET_LOG);
  }
  else {
    g_session.state = SESS_ONLINE;
    log_append("Logged in as %s@%s:%d (%s)",
        g_session.dsfy->user_info->username,
        g_session.dsfy->user_info->server_host,
        g_session.dsfy->user_info->server_port,
        g_session.dsfy->user_info->country);
    // Switch to browser view.
    ui_show(UI_SET_BROWSER);
  }

  // Redraw status info.
  ui_dirty(UI_FOOTER);
}
Exemplo n.º 2
0
void sess_cleanup()
{
  sess_disconnect();
  audio_exit(audio_device);
  log_append("Destroyed audio output");

  // Free search results.
  for (sess_search_t *s = g_session.search; s;) {
    despotify_free_search(s->res);
    sess_search_t *p = s;
    s = s->next;
    free(p);
  }

  if (!despotify_cleanup())
    panic("despotify_cleanup() failed");

  free(g_session.username);
  g_session.username = 0;
  free(g_session.password);
  g_session.password = 0;
}
Exemplo n.º 3
0
/*
 * Main loop
 */
int sess_main(struct irc_session *sess)
{
    /* Jump into mainloop */
    while (!sess->kill) {
        time_t lastidle = time(NULL);
        time_t last_sign_of_life = time(NULL);

        if (sess_connect(sess) < 0)
            break;

        sess->session_start = time(NULL);
        sess_login(sess);

        /* Inner loop, receive and handle data */
        while (!sess->kill) {
            /*
             * Since both idle and flood protection are based on second
             * precision, this is an optimal timeout
             */
            struct timeval timeout = { .tv_sec = 1, .tv_usec = 0 };

            int res = sess_handle_data(sess, &timeout);

            if (res < 0) {
                break;
            } else if (res > 0) {
                last_sign_of_life = time(NULL);
            } else {
                if ((time(NULL) - last_sign_of_life) >= TIMEOUT) {
                    struct tm *tm = TIME_GETTIME(&last_sign_of_life);

                    char buffer[TIMEBUF_MAX] = {0};
                    strftime(buffer, sizeof(buffer), STRFTIME_FORMAT, tm);

                    log_info("Last sign of life was %d seconds "
                             "ago (%s). Pinging server...",
                                time(NULL) - last_sign_of_life, buffer);

                    struct irc_message ping;
                    irc_mkmessage(&ping, CMD_PING, NULL, 0, "%s",
                        sess->hostname);

                    if (sess_sendmsg_real(sess, &ping) <= 0)
                        break;
                }
            }

            /* Try to send messages in outbuffer */
            while (sess->buffer_out_start != sess->buffer_out_end) {
                struct irc_message *next =
                    &(sess->buffer_out[sess->buffer_out_start]);

                unsigned len = irc_message_size(next);
                len = MAX(len, FLOODPROT_MIN);

                if (tokenbucket_consume(&sess->quota, len)) {
                    sess_sendmsg_real(sess, next);

                    sess->buffer_out_start =
                        (sess->buffer_out_start + 1) % FLOODPROT_BUFFER;
                } else {
                    break;
                }
            }

            /* Check if we have to emit an idle event */
            if ((time(NULL) - lastidle) >= IDLE_INTERVAL) {
                if (sess->cb.on_idle)
                    sess->cb.on_idle(sess->cb.arg, lastidle);

                lastidle = time(NULL);
            }

            /* And regenerate some tokens */
            tokenbucket_generate(&sess->quota);
        }

        if (sess->cb.on_disconnect)
            sess->cb.on_disconnect(sess->cb.arg);

        /* Session is finished, free resources and start again unless killed */
        hashtable_clear(sess->channels);
        hashtable_clear(sess->capabilities);

        sess_disconnect(sess);
    }

    return 0;
}

int sess_login(struct irc_session *sess)
{
    struct irc_message nick;
    struct irc_message user;

    irc_mkmessage(&nick, CMD_NICK, (const char *[]){ sess->nick }, 1, NULL);
    irc_mkmessage(&user, CMD_USER,
            (const char *[]){ sess->user, "*", "*" }, 3, "%s", sess->real);
Exemplo n.º 4
0
void cmd_cb_disconnect()
{
  sess_disconnect();
}
Exemplo n.º 5
0
void sess_init(struct event_base *evbase)
{
  g_session.evbase  = evbase;
  g_session.spot_ev = evtimer_new(evbase, sess_event_cb, &g_session);
  g_session.stop_ev = evtimer_new(evbase, sess_stop_cb, &g_session);
  g_session.exiting = false;
  g_session.current_track = NULL;

  sp_session_config config = {
    .api_version          = SPOTIFY_API_VERSION,
    .cache_location       = "tmp",
    .settings_location    = "tmp",
    .application_key      = g_appkey,
    .application_key_size = g_appkey_size,
    .user_agent           = POLSPOT_USER_AGENT,
    .callbacks            = &g_callbacks,
    .userdata             = &g_session
  };

  sp_error err = sp_session_init(&config, &g_session.spotify);

  if (err != SP_ERROR_OK)
    panic("sp_session_init() failed: %s", sp_error_message(err));
}

void sess_cleanup()
{
  // If user is logged in then initiate logout. This will change the session
  // state to SESS_DISCONNECTING. Another call to this function will thus exit
  // the main loop without waiting for the logout process to finish, allowing
  // users to avoid waiting for timeouts by issuing the quit commant twice.
  if (g_session.state == SESS_ONLINE) {
    sess_disconnect();
    g_session.exiting = true;
  }
  else {
    free(g_session.username);
    g_session.username = 0;
    free(g_session.password);
    g_session.password = 0;

    // Free search results.
    for (sess_search_t *s = g_session.search; s;) {
      sp_search_release(s->res);
      sess_search_t *p = s;
      s = s->next;
      free(p);
    }

    g_session.current_track = NULL;
    event_free(g_session.spot_ev);

    // Exit main event loop.
    event_base_loopbreak(g_session.evbase);
  }
}

void sess_connect()
{
  assert(g_session.username && g_session.password);

  sess_disconnect();

  // Login with credentials set by sess_username/sess_password.
  sp_error err = sp_session_login(g_session.spotify, g_session.username, g_session.password);

  if (err != SP_ERROR_OK)
    panic("sp_session_login() failed: %s", sp_error_message(err));

  log_append("Connecting...");

  // Redraw status info.
  g_session.state = SESS_CONNECTING;
  ui_dirty(UI_FOOTER);
  ui_update_post(0);
}