コード例 #1
0
ファイル: tipdecode.c プロジェクト: bodop/tip-toi-reveng
static void print_playlistlist(FILE* out,const char* prefix,
                               const char* indent,
                               const struct gme_playlistlist* pll,
                               struct gme* gme)
{
  if (!pll || pll->len==0) return;
  if (prefix) fputs(prefix,out);
  fprintf(out,"{\n");
  uint16_t i;
  for (i=0; i<le16toh(pll->len); i++) {
    const struct gme_playlist* pl=gme_playlistlist_get(gme,pll,i);
    fputs("  ",out);
    print_playlist(out,indent,pl);
  }
  if (indent) fputs(indent,out);
  fputs("}\n",out);
}
コード例 #2
0
ファイル: term.c プロジェクト: BenWBrown/cs453_final_project
static void term_handle_key(mpg123_handle *fr, out123_handle *ao, char val)
{
	debug1("term_handle_key: %c", val);
	switch(tolower(val))
	{
	case MPG123_BACK_KEY:
		out123_pause(ao);
		out123_drop(ao);
		if(paused) pause_cycle=(int)(LOOP_CYCLES/mpg123_tpf(fr));

		if(mpg123_seek_frame(fr, 0, SEEK_SET) < 0)
		error1("Seek to begin failed: %s", mpg123_strerror(fr));

		framenum=0;
	break;
	case MPG123_NEXT_KEY:
		out123_pause(ao);
		out123_drop(ao);
		next_track();
	break;
	case MPG123_NEXT_DIR_KEY:
		out123_pause(ao);
		out123_drop(ao);
		next_dir();
	break;
	case MPG123_QUIT_KEY:
		debug("QUIT");
		if(stopped)
		{
			stopped = 0;
			out123_pause(ao); /* no chance for annoying underrun warnings */
			out123_drop(ao);
		}
		set_intflag();
		offset = 0;
	break;
	case MPG123_PAUSE_KEY:
		paused=1-paused;
		out123_pause(ao); /* underrun awareness */
		out123_drop(ao);
		if(paused)
		{
			/* Not really sure if that is what is wanted
				 This jumps in audio output, but has direct reaction to pausing loop. */
			out123_param_float(ao, OUT123_PRELOAD, 0.);
			pause_recycle(fr);
		}
		else
			out123_param_float(ao, OUT123_PRELOAD, param.preload);
		if(stopped)
			stopped=0;
		if(param.verbose)
			print_stat(fr, 0, ao);
		else
			fprintf(stderr, "%s", (paused) ? MPG123_PAUSED_STRING : MPG123_EMPTY_STRING);
	break;
	case MPG123_STOP_KEY:
	case ' ':
		/* TODO: Verify/ensure that there is no "chirp from the past" when
		   seeking while stopped. */
		stopped=1-stopped;
		if(paused) {
			paused=0;
			offset -= pause_cycle;
		}
		if(stopped)
			out123_pause(ao);
		else
		{
			if(offset) /* If position changed, old is outdated. */
				out123_drop(ao);
			/* No out123_continue(), that's triggered by out123_play(). */
		}
		if(param.verbose)
			print_stat(fr, 0, ao);
		else
			fprintf(stderr, "%s", (stopped) ? MPG123_STOPPED_STRING : MPG123_EMPTY_STRING);
	break;
	case MPG123_FINE_REWIND_KEY:
		seekmode(fr, ao);
		offset--;
	break;
	case MPG123_FINE_FORWARD_KEY:
		seekmode(fr, ao);
		offset++;
	break;
	case MPG123_REWIND_KEY:
		seekmode(fr, ao);
		  offset-=10;
	break;
	case MPG123_FORWARD_KEY:
		seekmode(fr, ao);
		offset+=10;
	break;
	case MPG123_FAST_REWIND_KEY:
		seekmode(fr, ao);
		offset-=50;
	break;
	case MPG123_FAST_FORWARD_KEY:
		seekmode(fr, ao);
		offset+=50;
	break;
	case MPG123_VOL_UP_KEY:
		mpg123_volume_change(fr, 0.02);
	break;
	case MPG123_VOL_DOWN_KEY:
		mpg123_volume_change(fr, -0.02);
	break;
	case MPG123_PITCH_UP_KEY:
	case MPG123_PITCH_BUP_KEY:
	case MPG123_PITCH_DOWN_KEY:
	case MPG123_PITCH_BDOWN_KEY:
	case MPG123_PITCH_ZERO_KEY:
	{
		double new_pitch = param.pitch;
		switch(val) /* Not tolower here! */
		{
			case MPG123_PITCH_UP_KEY:    new_pitch += MPG123_PITCH_VAL;  break;
			case MPG123_PITCH_BUP_KEY:   new_pitch += MPG123_PITCH_BVAL; break;
			case MPG123_PITCH_DOWN_KEY:  new_pitch -= MPG123_PITCH_VAL;  break;
			case MPG123_PITCH_BDOWN_KEY: new_pitch -= MPG123_PITCH_BVAL; break;
			case MPG123_PITCH_ZERO_KEY:  new_pitch = 0.0; break;
		}
		set_pitch(fr, ao, new_pitch);
		fprintf(stderr, "New pitch: %f\n", param.pitch);
	}
	break;
	case MPG123_VERBOSE_KEY:
		param.verbose++;
		if(param.verbose > VERBOSE_MAX)
		{
			param.verbose = 0;
			clear_stat();
		}
		mpg123_param(fr, MPG123_VERBOSE, param.verbose, 0);
	break;
	case MPG123_RVA_KEY:
		if(++param.rva > MPG123_RVA_MAX) param.rva = 0;
		if(param.verbose)
			fprintf(stderr, "\n");
		mpg123_param(fr, MPG123_RVA, param.rva, 0);
		mpg123_volume_change(fr, 0.);
	break;
	case MPG123_PREV_KEY:
		out123_pause(ao);
		out123_drop(ao);

		prev_track();
	break;
	case MPG123_PREV_DIR_KEY:
		out123_pause(ao);
		out123_drop(ao);
		prev_dir();
	break;
	case MPG123_PLAYLIST_KEY:
		fprintf(stderr, "%s\nPlaylist (\">\" indicates current track):\n", param.verbose ? "\n" : "");
		print_playlist(stderr, 1);
		fprintf(stderr, "\n");
	break;
	case MPG123_TAG_KEY:
		fprintf(stderr, "%s\n", param.verbose ? "\n" : "");
		print_id3_tag(fr, param.long_id3, stderr);
		fprintf(stderr, "\n");
	break;
	case MPG123_MPEG_KEY:
		if(param.verbose) print_stat(fr,0,ao); /* Make sure that we are talking about the correct frame. */
		fprintf(stderr, "\n");
		if(param.verbose > 1)
			print_header(fr);
		else
			print_header_compact(fr);
		fprintf(stderr, "\n");
	break;
	case MPG123_HELP_KEY:
	{ /* This is more than the one-liner before, but it's less spaghetti. */
		int i;
		fprintf(stderr,"\n\n -= terminal control keys =-\n");
		for(i=0; i<(sizeof(term_help)/sizeof(struct keydef)); ++i)
		{
			if(term_help[i].key2) fprintf(stderr, "[%c] or [%c]", term_help[i].key, term_help[i].key2);
			else fprintf(stderr, "[%c]", term_help[i].key);

			fprintf(stderr, "\t%s\n", term_help[i].desc);
		}
		fprintf(stderr, "\nAlso, the number row (starting at 1, ending at 0) gives you jump points into the current track at 10%% intervals.\n");
		fprintf(stderr, "\n");
	}
	break;
	case MPG123_FRAME_INDEX_KEY:
	case MPG123_VARIOUS_INFO_KEY:
		if(param.verbose) fprintf(stderr, "\n");
		switch(val) /* because of tolower() ... */
		{
			case MPG123_FRAME_INDEX_KEY:
			print_index(fr);
			{
				long accurate;
				if(mpg123_getstate(fr, MPG123_ACCURATE, &accurate, NULL) == MPG123_OK)
				fprintf(stderr, "Accurate position: %s\n", (accurate == 0 ? "no" : "yes"));
				else
				error1("Unable to get state: %s", mpg123_strerror(fr));
			}
			break;
			case MPG123_VARIOUS_INFO_KEY:
			{
				const char* curdec = mpg123_current_decoder(fr);
				if(curdec == NULL) fprintf(stderr, "Cannot get decoder info!\n");
				else fprintf(stderr, "Active decoder: %s\n", curdec);
			}
		}
	break;
	case '0':
	case '1':
	case '2':
	case '3':
	case '4':
	case '5':
	case '6':
	case '7':
	case '8':
	case '9':
	{
		off_t len;
		int num;
		num = val == '0' ? 10 : val - '0';
		--num; /* from 0 to 9 */

		/* Do not swith to seekmode() here, as we are jumping once to a
		   specific position. Dropping buffer contents is enough and there
		   is no race filling the buffer or waiting for more incremental
		   seek orders. */
		len = mpg123_length(fr);
		out123_pause(ao);
		out123_drop(ao);
		if(len > 0)
			mpg123_seek(fr, (off_t)( (num/10.)*len ), SEEK_SET);
	}
	break;
	case MPG123_BOOKMARK_KEY:
		continue_msg("BOOKMARK");
	break;
	default:
		;
	}
}
コード例 #3
0
ファイル: term.c プロジェクト: BacioiuC/love-native-android
static void term_handle_input(mpg123_handle *fr, audio_output_t *ao, int do_delay)
{
  int n = 1;
  /* long offset = 0; */
  
  while(n > 0) {
    fd_set r;
    struct timeval t;
    char val;

    t.tv_sec=0;
    t.tv_usec=(do_delay) ? 10*1000 : 0;
    
    FD_ZERO(&r);
    FD_SET(0,&r);
    n = select(1,&r,NULL,NULL,&t);
    if(n > 0 && FD_ISSET(0,&r)) {
      if(read(0,&val,1) <= 0)
        break;

      switch(tolower(val)) {
	case MPG123_BACK_KEY:
        if(!param.usebuffer) ao->flush(ao);
				else buffer_resync();
		if(paused) pause_cycle=(int)(LOOP_CYCLES/mpg123_tpf(fr));

		if(mpg123_seek_frame(fr, 0, SEEK_SET) < 0)
		error1("Seek to begin failed: %s", mpg123_strerror(fr));

		framenum=0;
		break;
	case MPG123_NEXT_KEY:
		if(!param.usebuffer) ao->flush(ao);
		else buffer_resync(); /* was: plain_buffer_resync */
	  next_track();
	  break;
	case MPG123_QUIT_KEY:
		debug("QUIT");
		if(stopped)
		{
			stopped = 0;
			if(param.usebuffer)
			{
				buffer_resync();
				buffer_start();
			}
		}
		set_intflag();
		offset = 0;
	  break;
	case MPG123_PAUSE_KEY:
  	  paused=1-paused;
	  if(paused) {
			/* Not really sure if that is what is wanted
			   This jumps in audio output, but has direct reaction to pausing loop. */
			if(param.usebuffer) buffer_resync();

			pause_recycle(fr);
	  }
		if(stopped)
		{
			stopped=0;
			if(param.usebuffer) buffer_start();
		}
	  fprintf(stderr, "%s", (paused) ? MPG123_PAUSED_STRING : MPG123_EMPTY_STRING);
	  break;
	case MPG123_STOP_KEY:
	case ' ':
		/* when seeking while stopped and then resuming, I want to prevent the chirp from the past */
		if(!param.usebuffer) ao->flush(ao);
	  stopped=1-stopped;
	  if(paused) {
		  paused=0;
		  offset -= pause_cycle;
	  }
		if(param.usebuffer)
		{
			if(stopped) buffer_stop();
			else
			{
				/* When we stopped buffer for seeking, we must resync. */
				if(offset) buffer_resync();

				buffer_start();
			}
		}
	  fprintf(stderr, "%s", (stopped) ? MPG123_STOPPED_STRING : MPG123_EMPTY_STRING);
	  break;
	case MPG123_FINE_REWIND_KEY:
	  if(param.usebuffer) seekmode();
	  offset--;
	  break;
	case MPG123_FINE_FORWARD_KEY:
	  seekmode();
	  offset++;
	  break;
	case MPG123_REWIND_KEY:
	  seekmode();
  	  offset-=10;
	  break;
	case MPG123_FORWARD_KEY:
	  seekmode();
	  offset+=10;
	  break;
	case MPG123_FAST_REWIND_KEY:
	  seekmode();
	  offset-=50;
	  break;
	case MPG123_FAST_FORWARD_KEY:
	  seekmode();
	  offset+=50;
	  break;
	case MPG123_VOL_UP_KEY:
		mpg123_volume_change(fr, 0.02);
	break;
	case MPG123_VOL_DOWN_KEY:
		mpg123_volume_change(fr, -0.02);
	break;
	case MPG123_PITCH_UP_KEY:
	case MPG123_PITCH_BUP_KEY:
	case MPG123_PITCH_DOWN_KEY:
	case MPG123_PITCH_BDOWN_KEY:
	case MPG123_PITCH_ZERO_KEY:
	{
		double new_pitch = param.pitch;
		switch(val) /* Not tolower here! */
		{
			case MPG123_PITCH_UP_KEY:    new_pitch += MPG123_PITCH_VAL;  break;
			case MPG123_PITCH_BUP_KEY:   new_pitch += MPG123_PITCH_BVAL; break;
			case MPG123_PITCH_DOWN_KEY:  new_pitch -= MPG123_PITCH_VAL;  break;
			case MPG123_PITCH_BDOWN_KEY: new_pitch -= MPG123_PITCH_BVAL; break;
			case MPG123_PITCH_ZERO_KEY:  new_pitch = 0.0; break;
		}
		set_pitch(fr, ao, new_pitch);
		fprintf(stderr, "New pitch: %f\n", param.pitch);
	}
	break;
	case MPG123_VERBOSE_KEY:
		param.verbose++;
		if(param.verbose > VERBOSE_MAX)
		{
			param.verbose = 0;
			clear_stat();
		}
		mpg123_param(fr, MPG123_VERBOSE, param.verbose, 0);
	break;
	case MPG123_RVA_KEY:
		if(++param.rva > MPG123_RVA_MAX) param.rva = 0;
		mpg123_param(fr, MPG123_RVA, param.rva, 0);
		mpg123_volume_change(fr, 0.);
	break;
	case MPG123_PREV_KEY:
		if(!param.usebuffer) ao->flush(ao);
		else buffer_resync(); /* was: plain_buffer_resync */

		prev_track();
	break;
	case MPG123_PLAYLIST_KEY:
		fprintf(stderr, "%s\nPlaylist (\">\" indicates current track):\n", param.verbose ? "\n" : "");
		print_playlist(stderr, 1);
		fprintf(stderr, "\n");
	break;
	case MPG123_TAG_KEY:
		fprintf(stderr, "%s\n", param.verbose ? "\n" : "");
		print_id3_tag(fr, param.long_id3, stderr);
		fprintf(stderr, "\n");
	break;
	case MPG123_MPEG_KEY:
		if(param.verbose) print_stat(fr,0,0); /* Make sure that we are talking about the correct frame. */
		fprintf(stderr, "\n");
		print_header(fr);
		fprintf(stderr, "\n");
	break;
	case MPG123_HELP_KEY:
	{ /* This is more than the one-liner before, but it's less spaghetti. */
		int i;
		fprintf(stderr,"\n\n -= terminal control keys =-\n");
		for(i=0; i<(sizeof(term_help)/sizeof(struct keydef)); ++i)
		{
			if(term_help[i].key2) fprintf(stderr, "[%c] or [%c]", term_help[i].key, term_help[i].key2);
			else fprintf(stderr, "[%c]", term_help[i].key);

			fprintf(stderr, "\t%s\n", term_help[i].desc);
		}
		fprintf(stderr, "\n");
	}
	break;
	case MPG123_FRAME_INDEX_KEY:
	case MPG123_VARIOUS_INFO_KEY:
		if(param.verbose) fprintf(stderr, "\n");
		switch(val) /* because of tolower() ... */
		{
			case MPG123_FRAME_INDEX_KEY:
			print_index(fr);
			{
				long accurate;
				if(mpg123_getstate(fr, MPG123_ACCURATE, &accurate, NULL) == MPG123_OK)
				fprintf(stderr, "Accurate position: %s\n", (accurate == 0 ? "no" : "yes"));
				else
				error1("Unable to get state: %s", mpg123_strerror(fr));
			}
			break;
			case MPG123_VARIOUS_INFO_KEY:
			{
				const char* curdec = mpg123_current_decoder(fr);
				if(curdec == NULL) fprintf(stderr, "Cannot get decoder info!\n");
				else fprintf(stderr, "Active decoder: %s\n", curdec);
			}
		}
	break;
	default:
	  ;
      }
    }
  }
}
コード例 #4
0
ファイル: simple.c プロジェクト: estock/spot
void command_loop(struct despotify_session* ds)
{
    bool loop = true;
    char buf[80];
    struct playlist* rootlist = NULL;
    struct playlist* searchlist = NULL;
    struct search_result *search = NULL;
    struct album_browse* playalbum = NULL;

    print_help();

    do {
        wprintf(L"\n> ");
        fflush(stdout);
        bzero(buf, sizeof buf);
        fgets(buf, sizeof buf -1, stdin);
        buf[strlen(buf) - 1] = 0; /* remove newline */

        /* list */
        if (!strncmp(buf, "list", 4)) {
            int num = atoi(buf + 5);
            if (num) {
                struct playlist* p = get_playlist(rootlist, num);

                if (p) {
                    print_tracks(p->tracks);
                    lastlist = p;
                }
            }
            else {
                if (!rootlist)
                    rootlist = despotify_get_stored_playlists(ds);
                print_list_of_lists(rootlist);
            }
        }

        /* rename */
        else if (!strncmp(buf, "rename", 6)) {
            int num = 0;
            char *name = 0;
            if (strlen(buf) > 9) {
                num = atoi(buf + 7);
                name = strchr(buf + 7, ' ') + 1;
            }

            if (num && name && name[0]) {
                struct playlist* p = get_playlist(rootlist, num);

                if (p) {
                    if (despotify_rename_playlist(ds, p, name))
                        wprintf(L"Renamed playlist %d to \"%s\".\n", num, name);
                    else
                        wprintf(L"Rename failed: %s\n", despotify_get_error(ds));
                }
            }
            else
                wprintf(L"Usage: rename [num] [string]\n");
        }

        /* collab */
        else if (!strncmp(buf, "collab", 6)) {
            int num = 0;
            if (strlen(buf) > 7)
                num = atoi(buf + 7);

            if (num) {
                struct playlist* p = get_playlist(rootlist, num);

                if (p) {
                    if (despotify_set_playlist_collaboration(ds, p, !p->is_collaborative))
                        wprintf(L"Changed playlist %d collaboration to %s.\n",
                                num, p->is_collaborative ? "ON" : "OFF");
                    else
                        wprintf(L"Setting playlist collaboration state failed: %s\n",
                                despotify_get_error(ds));
                }
            }
            else
                wprintf(L"Usage: collab [num]\n");
        }

        /* search */
        else if (!strncmp(buf, "search", 6)) {
            if (buf[7]) {
                if (search)
                    despotify_free_search(search);

                despotify_stop(ds); /* since we replace the list */
                search = despotify_search(ds, buf + 7, MAX_SEARCH_RESULTS);
                if (!search) {
                    wprintf(L"Search failed: %s\n", despotify_get_error(ds));
                    continue;
                }
                searchlist = search->playlist;
            }
            else if (searchlist && (searchlist->num_tracks < search->total_tracks))
                if (!despotify_search_more(ds, search, searchlist->num_tracks, MAX_SEARCH_RESULTS)) {
                    wprintf(L"Search failed: %s\n", despotify_get_error(ds));
                    continue;
                }

            if (searchlist) {
                print_search(search);


                lastlist = searchlist;
            }
            else
                wprintf(L"No previous search\n");
        }

        /* artist */
        else if (!strncmp(buf, "artist", 6)) {
            int num = atoi(buf + 7);
            if (!num) {
                wprintf(L"usage: artist [num]\n");
                continue;
            }
            if (!lastlist) {
                wprintf(L"No playlist\n");
                continue;
            }

            /* find the requested track */
            struct track* t = lastlist->tracks;
            for (int i=1; i<num; i++)
                t = t->next;

            for (struct artist* aptr = t->artist; aptr; aptr = aptr->next) {
                struct artist_browse* a = despotify_get_artist(ds, aptr->id);
                print_artist(a);
                despotify_free_artist_browse(a);
            }
        }

        /* album */
        else if (!strncmp(buf, "album", 5)) {
            int num = atoi(buf + 6);
            if (!num) {
                wprintf(L"usage: album [num]\n");
                continue;
            }
            if (!lastlist) {
                wprintf(L"No playlist\n");
                continue;
            }

            /* find the requested track */
            struct track* t = lastlist->tracks;
            for (int i=1; i<num; i++)
                t = t->next;

            if (t) {
                struct album_browse* a = despotify_get_album(ds, t->album_id);
                if (a) {
                    print_album(a);
                    despotify_free_album_browse(a);
                }
                else
                    wprintf(L"Got no album for id %s\n", t->album_id);
            }
        }

        /* playalbum */
        else if (!strncmp(buf, "playalbum", 9)) {
            int num = atoi(buf + 10);
            if (!num) {
                wprintf(L"usage: playalbum [num]\n");
                continue;
            }
            if (!lastlist) {
                wprintf(L"No playlist\n");
                continue;
            }

            /* find the requested track */
            struct track* t = lastlist->tracks;
            for (int i=1; i<num; i++)
                t = t->next;


            if (t) {
                if (playalbum)
                    despotify_free_album_browse(playalbum);

                despotify_stop(ds);
                playalbum = despotify_get_album(ds, t->album_id);

                if (playalbum)
                    despotify_play(ds, playalbum->tracks, true);
                else
                    wprintf(L"Got no album for id %s\n", t->album_id);
            }
        }

        /* uri */
        else if (!strncmp(buf, "uri", 3)) {
            char *uri = buf + 4;
            if(strlen(uri) == 0) {
                wprintf(L"usage: info <uri>\n");
                continue;
            }

            struct link* link = despotify_link_from_uri(uri);
            struct album_browse* al;
            struct artist_browse* ar;
            struct playlist* pls;
            struct search_result* s;
            struct track* t;

            switch(link->type) {
                case LINK_TYPE_ALBUM:
                    al = despotify_link_get_album(ds, link);
                    if(al) {
                        print_album(al);
                        despotify_free_album_browse(al);
                    }
                    break;

                case LINK_TYPE_ARTIST:
                    ar = despotify_link_get_artist(ds, link);
                    if(ar) {
                        print_artist(ar);
                        despotify_free_artist_browse(ar);
                    }
                    break;

                case LINK_TYPE_PLAYLIST:
                    pls = despotify_link_get_playlist(ds, link);
                    if(pls) {
                        print_playlist(pls);
                        despotify_free_playlist(pls);
                    }
                    break;

                case LINK_TYPE_SEARCH:
                    s = despotify_link_get_search(ds, link);
                    if(s) {
                        print_search(s);
                        despotify_free_search(s);
                    }
                    break;

                case LINK_TYPE_TRACK:
                    t = despotify_link_get_track(ds, link);
                    if(t) {
                        print_track_full(t);
                        despotify_free_track(t);
                    }
                    break;

                default:
                    wprintf(L"%s is a invalid Spotify URI\n", uri);
            }

            despotify_free_link(link);
        }

        /* portrait */
        else if (!strncmp(buf, "portrait", 8)) {
            int num = atoi(buf + 9);
            if (!num) {
                wprintf(L"usage: portrait [num]\n");
                continue;
            }
            if (!lastlist) {
                wprintf(L"No playlist\n");
                continue;
            }

            /* find the requested artist */
            struct track* t = lastlist->tracks;
            for (int i=1; i<num; i++)
                t = t->next;
            struct artist_browse* a = despotify_get_artist(ds, t->artist->id);
            if (a && a->portrait_id[0]) {
                int len;
                void* portrait = despotify_get_image(ds, a->portrait_id, &len);
                if (portrait && len) {
                    wprintf(L"Writing %d bytes into portrait.jpg\n", len);
                    FILE* f = fopen("portrait.jpg", "w");
                    if (f) {
                        fwrite(portrait, len, 1, f);
                        fclose(f);
                    }
                    free(portrait);
                }
            }
            else
                wprintf(L"Artist %s has no portrait.\n", a->name);
            despotify_free_artist_browse(a);
        }

        /* play */
        else if (!strncmp(buf, "play", 4)) {
            if (!lastlist) {
                wprintf(L"No list to play from. Use 'list' or 'search' to select a list.\n");
                continue;
            }

            /* skip to track <num> */
            listoffset = atoi(buf + 5);
            struct track* t = lastlist->tracks;
            for (int i=1; i<listoffset && t; i++)
                t = t->next;
            if (t)
                despotify_play(ds, t, true);
            else
                wprintf(L"Invalid track number %d\n", listoffset);
        }

        /* stop */
        else if (!strncmp(buf, "stop", 4)) {
            despotify_stop(ds);
        }

        /* pause */
        else if (!strncmp(buf, "pause", 5)) {
            despotify_pause(ds);
        }

        /* resume */
        else if (!strncmp(buf, "resume", 5)) {
            despotify_resume(ds);
        }

        /* info */
        else if (!strncmp(buf, "info", 4)) {
            print_info(ds);
        }

        /* help */
        else if (!strncmp(buf, "help", 4)) {
            print_help();
        }

        /* quit */
        else if (!strncmp(buf, "quit", 4)) {
            loop = false;
        }
    } while(loop);

    if (rootlist)
        despotify_free_playlist(rootlist);

    if (search)
        despotify_free_search(search);

    if (playalbum)
        despotify_free_album_browse(playalbum);
}