Beispiel #1
0
/* Key/value functions */
int
keyval_add_size(struct keyval *kv, const char *name, const char *value, size_t size)
{
  struct onekeyval *okv;
  const char *val;

  /* Check for duplicate key names */
  val = keyval_get(kv, name);
  if (val)
    {
      /* Same value, fine */
      if (strcmp(val, value) == 0)
        return 0;
      else /* Different value, bad */
        return -1;
    }

  okv = (struct onekeyval *)malloc(sizeof(struct onekeyval));
  if (!okv)
    {
      DPRINTF(E_LOG, L_MISC, "Out of memory for new keyval\n");

      return -1;
    }

  okv->name = strdup(name);
  if (!okv->name)
    {
      DPRINTF(E_LOG, L_MISC, "Out of memory for new keyval name\n");

      free(okv);
      return -1;
    }

  okv->value = (char *)malloc(size + 1);
  if (!okv->value)
    {
      DPRINTF(E_LOG, L_MISC, "Out of memory for new keyval value\n");

      free(okv->name);
      free(okv);
      return -1;
    }

  memcpy(okv->value, value, size);
  okv->value[size] = '\0';

  okv->next = NULL;

  if (!kv->head)
    kv->head = okv;

  if (kv->tail)
    kv->tail->next = okv;

  kv->tail = okv;

  return 0;
}
Beispiel #2
0
static int
scrobble(int id)
{
  struct media_file_info *mfi;
  struct keyval *kv;
  char duration[4];
  char trackNumber[4];
  char timestamp[16];
  int ret;

  mfi = db_file_fetch_byid(id);
  if (!mfi)
    {
      DPRINTF(E_LOG, L_LASTFM, "Scrobble failed, track id %d is unknown\n", id);
      return -1;
    }

  // Don't scrobble songs which are shorter than 30 sec
  if (mfi->song_length < 30000)
    goto noscrobble;

  // Don't scrobble non-music and radio stations
  if ((mfi->media_kind != MEDIA_KIND_MUSIC) || (mfi->data_kind == DATA_KIND_URL))
    goto noscrobble;

  // Don't scrobble songs with unknown artist
  if (strcmp(mfi->artist, "Unknown artist") == 0)
    goto noscrobble;

  kv = keyval_alloc();
  if (!kv)
    goto noscrobble;

  snprintf(duration, sizeof(duration), "%" PRIu32, mfi->song_length);
  snprintf(trackNumber, sizeof(trackNumber), "%" PRIu32, mfi->track);
  snprintf(timestamp, sizeof(timestamp), "%" PRIi64, (int64_t)time(NULL));

  ret = ( (keyval_add(kv, "api_key", lastfm_api_key) == 0) &&
          (keyval_add(kv, "sk", lastfm_session_key) == 0) &&
          (keyval_add(kv, "artist", mfi->artist) == 0) &&
          (keyval_add(kv, "track", mfi->title) == 0) &&
          (keyval_add(kv, "album", mfi->album) == 0) &&
          (keyval_add(kv, "albumArtist", mfi->album_artist) == 0) &&
          (keyval_add(kv, "duration", duration) == 0) &&
          (keyval_add(kv, "trackNumber", trackNumber) == 0) &&
          (keyval_add(kv, "timestamp", timestamp) == 0)
        );

  free_mfi(mfi, 0);

  if (!ret)
    {
      keyval_clear(kv);
      free(kv);
      return -1;
    }

  DPRINTF(E_INFO, L_LASTFM, "Scrobbling '%s' by '%s'\n", keyval_get(kv, "track"), keyval_get(kv, "artist"));

  ret = request_post("track.scrobble", kv, 0);

  keyval_clear(kv);
  free(kv);

  return ret;

 noscrobble:
  free_mfi(mfi, 0);

  return -1;
}
Beispiel #3
0
/* Thread: main (mdns) */
static void
touch_remote_cb(const char *name, const char *type, const char *domain, const char *hostname, int family, const char *address, int port, struct keyval *txt)
{
  const char *p;
  char *devname;
  char *paircode;
  int ret;

  if (port < 0)
    {
      /* If Remote stops advertising itself, the pairing either succeeded or
       * failed; any subsequent attempt will need a new pairing pin, so
       * we can just forget everything we know about the remote.
       */
      pthread_mutex_lock(&remote_lck);

      remove_remote_address_byid(name, family);

      pthread_mutex_unlock(&remote_lck);
    }
  else
    {
      /* Get device name (DvNm field in TXT record) */
      p = keyval_get(txt, "DvNm");
      if (!p)
	{
	  DPRINTF(E_LOG, L_REMOTE, "Remote %s: no DvNm in TXT record!\n", name);

	  return;
	}

      if (*p == '\0')
	{
	  DPRINTF(E_LOG, L_REMOTE, "Remote %s: DvNm has no value\n", name);

	  return;
	}

      devname = strdup(p);
      if (!devname)
	{
	  DPRINTF(E_LOG, L_REMOTE, "Out of memory for device name\n");

	  return;
	}

      /* Get pairing code (Pair field in TXT record) */
      p = keyval_get(txt, "Pair");
      if (!p)
	{
	  DPRINTF(E_LOG, L_REMOTE, "Remote %s: no Pair in TXT record!\n", name);

	  free(devname);
	  return;
	}

      if (*p == '\0')
	{
	  DPRINTF(E_LOG, L_REMOTE, "Remote %s: Pair has no value\n", name);

	  free(devname);
	  return;
	}

      paircode = strdup(p);
      if (!paircode)
	{
	  DPRINTF(E_LOG, L_REMOTE, "Out of memory for paircode\n");

	  free(devname);
	  return;
	}

      DPRINTF(E_LOG, L_REMOTE, "Discovered remote %s (id %s) at [%s]:%d, paircode %s\n", devname, name, address, port, paircode);

      /* Add the data to the list, adding the remote to the list if needed */
      pthread_mutex_lock(&remote_lck);

      ret = add_remote_mdns_data(name, family, address, port, devname, paircode);

      if (ret < 0)
	{
	  DPRINTF(E_WARN, L_REMOTE, "Could not add Remote mDNS data, id %s\n", name);

	  free(devname);
	  free(paircode);
	}
      else if (ret == 1)
	kickoff_pairing();

      pthread_mutex_unlock(&remote_lck);
    }
}
Beispiel #4
0
/* Earlier versions of ffmpeg/libav do not seem to allow access to the http
 * headers, so we must instead open the stream ourselves to get the metadata.
 * Sorry about the extra connections, you radio streaming people!
 *
 * It is not possible to get the packet metadata with these versions of ffmpeg
 */
struct http_icy_metadata *
http_icy_metadata_get(AVFormatContext *fmtctx, int packet_only)
{
  struct http_icy_metadata *metadata;
  struct http_client_ctx ctx;
  struct keyval *kv;
  const char *value;
  int got_header;
  int ret;

  /* Can only get header metadata */
  if (packet_only)
    return NULL;

  kv = keyval_alloc();
  if (!kv)
    return NULL;

  memset(&ctx, 0, sizeof(struct http_client_ctx));
  ctx.url = fmtctx->filename;
  ctx.headers = kv;
  ctx.headers_only = 1;
  ctx.body = NULL;

  ret = http_client_request(&ctx);
  if (ret < 0)
    {
      DPRINTF(E_LOG, L_HTTP, "Error fetching %s\n", fmtctx->filename);

      free(kv);
      return NULL;
    }

  metadata = malloc(sizeof(struct http_icy_metadata));
  if (!metadata)
    return NULL;
  memset(metadata, 0, sizeof(struct http_icy_metadata));

  got_header = 0;
  if ( (value = keyval_get(ctx.headers, "icy-name")) )
    {
      metadata->name = strdup(value);
      got_header = 1;
    }
  if ( (value = keyval_get(ctx.headers, "icy-description")) )
    {
      metadata->description = strdup(value);
      got_header = 1;
    }
  if ( (value = keyval_get(ctx.headers, "icy-genre")) )
    {
      metadata->genre = strdup(value);
      got_header = 1;
    }

  keyval_clear(kv);
  free(kv);

  if (!got_header)
   {
     free(metadata);
     return NULL;
   }

/*  DPRINTF(E_DBG, L_HTTP, "Found ICY: N %s, D %s, G %s, T %s, A %s, U %s, I %" PRIu32 "\n",
	metadata->name,
	metadata->description,
	metadata->genre,
	metadata->title,
	metadata->artist,
	metadata->artwork_url,
	metadata->hash
	);*/

  return metadata;
}