seamus

commit dab620faeb16ecf1fff6177f93619be70a9ce73b

Author: Pedro Lucas Porcellis <porcellis@eletrotupi.com>

queue: preamble to re-rendering logic

Split between the max number of items we can display, the number of
items actually queued and only re-render if the version of the playlist
has changed (which we will use later on for fetching the data from MPD),
as when scrolling we don't need to fetch data from MPD, only update the
screen until reaches the end of the queue.

Now, seamus_frontend (horrible name), knows:

- version (the playlist version)
- queue_size (the number of items we actually have stored)

The latter, could be implemented by just hoping over
`seamus->queue`, but I think it's easier to just store the actually
number of items we have fetched.

Specially, because we have some scenarios, where: (1) you have a lot of
items queued on MPD but not enough room to display (2) have rows to
display but not enough items (3) have nothing queued at all (4) amount
of items == rows. All cases which should be handled differently,
specially on a scroll scenario.

 include/seamus.h | 5 +++
 include/ui.h | 1 
 src/queue.c | 31 +++++++++++++++++++++----
 src/ui.c | 60 ++++++++++++++++++++++++++++++--------------------


diff --git a/include/seamus.h b/include/seamus.h
index aaf49874a974e4629f6e820213f92d9034697e75..c772922e3b31d6079f0e00b1ab07a58025aa70fa 100644
--- a/include/seamus.h
+++ b/include/seamus.h
@@ -33,9 +33,12 @@
 struct seamus_frontend {
 	struct mpd_connection *conn;
 	struct seamus_song *queue;
-	size_t queue_size;
 	struct seamus_status *status;
+
+	int version;
+	int queue_size;
 	int scroll_position;
+
 	TickitWindow *main_window;
 	TickitWindow *status_window;
 	Tickit *t;




diff --git a/include/ui.h b/include/ui.h
index 8283311ba324484449d1857058bf87734a8f4685..a55b01bc6b54d373eb2f29b4886e2f717e38cd6d 100644
--- a/include/ui.h
+++ b/include/ui.h
@@ -14,4 +14,5 @@ static int update_status(Tickit *t, TickitEventFlags flags, void *_info, void *data);
 static int render_main_window(TickitWindow *win, TickitEventFlags flags, void *_info, void *data);
 static int render_status_window(TickitWindow *win, TickitEventFlags flags, void *_info, void *data);
 static int render_root(TickitWindow *win, TickitEventFlags flags, void *_info, void *data);
+static int render_queue(struct seamus_frontend *seamus, TickitRenderBuffer *render_buffer);
 #endif




diff --git a/src/queue.c b/src/queue.c
index 69b3e07f6462586cd5595d416eebb20ebc7e4538..7990c3ae6754412baebe1fc2c199d3bdc23a6bb5 100644
--- a/src/queue.c
+++ b/src/queue.c
@@ -10,14 +10,33 @@ 	assert(seamus->conn != NULL);
 
 	bool queue_status = mpd_send_list_queue_meta(seamus->conn);
 
-	if (queue_status == true) {
+	if (queue_status) {
 		struct mpd_entity *entity;
-		int index;
+		int index = 0;
+		int max_items = 0;
+
+		// XXX: The logic here is. We check the amount of items queued.
+		// Then we have the info o how many items we can fit into the
+		// screen. The decision we need to make here is: if the amount
+		// of items queued is larger than what we can display on the
+		// screen, alloc up to the number of items on screen (we can't
+		// show more than that anyway). If the number of items queued is
+		// lesser than the amount of rows we have available, only alloc
+		// up to the number of items on queue.
+
+		if (seamus->status->length > max_count) {
+			seamus->queue = calloc(max_count, sizeof(struct seamus_song));
+			max_items = max_count;
+		} else {
+			seamus->queue = calloc(seamus->status->length, sizeof(struct seamus_song));
+			max_items = seamus->status->length;
+		}
 
-		seamus->queue = calloc(max_count, sizeof(struct seamus_song));
+		seamus->queue_size = max_items;
 
-		for (index = 0; index < max_count; index++) {
+		while (index <= max_items) {
 			entity = mpd_recv_entity(seamus->conn);
+
 			if (entity == NULL) {
 				// TODO: Discover if the queue have ended, or we
 				// have received an error here
@@ -42,15 +61,17 @@
 					char *artist = malloc(sizeof(char) * strlen(sartist) + 1);
 					strcpy(artist, sartist);
 
+					new->song_id = mpd_song_get_id(song);
 					new->title = title;
 					new->artist = artist;
-					seamus->queue_size++;
 				}
 
 				// When freeing the entity, it'll automatically
 				// free the song for us
 				mpd_entity_free(entity);
 			}
+
+			index++;
 		}
 
 		mpd_response_finish(seamus->conn);




diff --git a/src/ui.c b/src/ui.c
index 146e61d26344df33e49ae55af9deafd647dae9ea..3838aca52f5272b8e9a3f5f38d20bd1eebd8cc97 100644
--- a/src/ui.c
+++ b/src/ui.c
@@ -40,8 +40,8 @@ {
 	TickitWindow *root = tickit_get_rootwin(s->t);
 	TickitTerm *tt = tickit_get_term(s->t);
 
-	tickit_window_bind_event(s->main_window, TICKIT_WINDOW_ON_EXPOSE, 0, &render_main_window, s);
 	tickit_window_bind_event(s->status_window, TICKIT_WINDOW_ON_EXPOSE, 0, &render_status_window, s);
+	tickit_window_bind_event(s->main_window, TICKIT_WINDOW_ON_EXPOSE, 0, &render_main_window, s);
 	tickit_window_bind_event(root, TICKIT_WINDOW_ON_EXPOSE, 0, &render_root, s);
 
 	tickit_term_bind_event(tt, TICKIT_TERM_ON_KEY, 0, &on_key_event, s);
@@ -193,38 +193,50 @@ 		tickit_renderbuffer_text(render_buffer, "Hello, welcome to seamus");
 		tickit_renderbuffer_restore(render_buffer);
 	}
 
-	int max_songs = tickit_window_lines(seamus->main_window);
-	log_debug("Max songs allowed: %d of total %d lines", max_songs, tickit_window_lines(win));
+	if (seamus->status->length == 0) {
+		tickit_renderbuffer_goto(render_buffer, 4, 0);
+		tickit_renderbuffer_text(render_buffer, "No songs queued.");
+	} else {
+		if (seamus->status->version != seamus->version) {
+			// Update the current version rendered
+			seamus->version = seamus->status->version;
 
-	fetch_current_queue(seamus, max_songs);
+			render_queue(seamus, render_buffer);
+		}
+	}
 
-	if (seamus->queue_size > 0) {
-		for (size_t i = 0; i < seamus->queue_size; ++i) {
-			if (i < max_songs) {
-				struct seamus_song *s = &seamus->queue[i];
+	return 1;
+}
 
-				if (s == NULL) {
-					log_info("Nothing here...");
-				} else {
-					char *song_str = malloc(
-							sizeof(char) *
-							(strlen(s->artist) + strlen(s->title) + 4));
+static int
+render_queue(struct seamus_frontend *seamus, TickitRenderBuffer *render_buffer)
+{
+	int max_window_size = tickit_window_lines(seamus->main_window);
+	fetch_current_queue(seamus, max_window_size);
 
-					sprintf(song_str, "%s - %s", s->artist, s->title);
+	for (size_t i = 0; i < seamus->queue_size; ++i) {
+		struct seamus_song *song = &seamus->queue[i];
 
-					tickit_renderbuffer_goto(render_buffer, 4 + i, 0);
-					tickit_renderbuffer_text(render_buffer, song_str);
+		if (song == NULL) {
+			log_info("Nothing to see here...");
+		} else {
+			char *song_str = malloc(
+					sizeof(char) *
+					(strlen(song->artist) + strlen(song->title) + 6));
 
-					free(song_str);
-				}
+			if (seamus->status->current_song_id == song->song_id) {
+				sprintf(song_str, "%s - %s", song->artist, song->title);
+				tickit_renderbuffer_goto(render_buffer, 4 + i, 2);
+			} else {
+				sprintf(song_str, "%s - %s", song->artist, song->title);
+				tickit_renderbuffer_goto(render_buffer, 4 + i, 0);
 			}
+
+			tickit_renderbuffer_text(render_buffer, song_str);
+
+			free(song_str);
 		}
-	} else {
-		tickit_renderbuffer_goto(render_buffer, 4, 0);
-		tickit_renderbuffer_text(render_buffer, "No songs queued.");
 	}
-
-	return 1;
 }
 
 int