bool pback_should_cont(node_t *node, int8_t cont) { /* CONT_NONE: Never continue. * CONT_LEAF: Continue to the end of the current branch, over leaves only. * CONT_BRANCH: Continue to the end of the played branch. * CONT_SIBLINGS: Continue to the end of the played branch and all its siblings. * CONT_ALL, Always continue. */ switch (cont) { case CONT_NONE: info("cont_none\n"); return false; case CONT_ALL: info("cont_all\n"); return true; case CONT_LEAF: info("cont_leaf: is leaf: %d, pars equal: %d\n", node_isleaf(node), node->par == lists.leaf->par); return (node_isleaf(node) && (node->par == lists.leaf->par)); case CONT_BRANCH: info("cont_branch: lists.play is par: %d\n", node_ispar(lists.play, node)); return node_ispar(lists.play, node); case CONT_SIBLINGS: info("cont_siblings: lists.play->par is par: %d\n", node_ispar(lists.play->par, node)); return node_ispar(lists.play->par, node); default: info("pback_should_cont(): Bad value '%d'.\n", cont); return false; } }
point_t* insert_(quadtree_t* tree, node_t *root, point_t *point, bool update) { if (node_isempty(root)) { root->point = point; return point; } else if (node_isleaf(root)) { if (root->point->x == point->x && root->point->y == point->y) { if(update) { reset_node_(tree, root); root->point = point; point = NULL; return root->point; } else { return root->point; } } else { if (!split_node_(tree, root)) return NULL; return insert_(tree, root, point, update); } } else if (node_ispointer(root)) { node_t* quadrant = get_quadrant_(root, point); if(!quadrant) return NULL; return insert_(tree, quadrant, point, update); } return NULL; }
state_t pback_decide(pback_t *pback) { state_t state; node_t *cur = NULL; if (lists.leaf != NULL) { /* If there are any nodes in the queue, we want to start the first one. */ if (g_opts.pl.usequeue && (lists.queue.list.br->count > 0)) { /* Find the node in the playlist matching the first queue track. */ if (node_isleaf(lists.queue.list.br->head)) cur = node_findleaf(&lists.pl.list, lists.queue.list.br->head->t->fn.str); else cur = node_findbranch(&lists.pl.list, lists.queue.list.br->head->br->type, lists.queue.list.br->head->br->name.str); if (cur != NULL) /* found the track */ { /* Record the current track so we can jump back to it later if * we want to. */ lists.saveleaf = lists.leaf; lists.delleaf = lists.queue.list.br->head; state = OK; } else state = ERR_NULL; } else { cur = lists.leaf; state = pback_getnew(&cur, DOWN); } } else { error("pback_decide(): lists.leaf was NULL, nothing to decide.\n"); state = ERR_NULL; } if ((cur != NULL) && (state == OK)) { if ((state = pback_play_node(pback, cur, TR_FLOW)) == OK) info("pback_decide(): started.\n"); else error("pback_decide(): couldn't start ('%s').\n", err_tostr(state)); } else info("pback_decide(): Some error occurred earlier, not attempting to start playback.\n"); return state; }
point_t* find_(node_t* node, double x, double y) { if (node_isleaf(node)) { if (node->point->x == x && node->point->y == y) { return node->point; } } else { point_t test; test.x = x; test.y = y; return find_(get_quadrant_(node, &test), x, y); } return NULL; }
state_t pback_getnew(node_t **node, int8_t dir) { state_t state; node_t *tmp = *node, *last; while (true) { last = tmp; tmp = node_traverse(tmp, dir, 1); if ((tmp == NULL) /* no more tracks */ || (tmp == last)) /* no more visible tracks */ break; if (node_isleaf(tmp)) { if (tmp->t->avail && tmp->t->sane) /* found a playable track */ break; info("pback_getnew(): ignoring %s%s%s track %s.\n", !tmp->t->avail ? "unavailable" : "", !(tmp->t->avail || tmp->t->sane) ? " and " : "", !tmp->t->sane ? "insane" : "", tmp->t->fn); } else /* found a branch -- always 'playable' */ break; } if (tmp == *node) /* nowhere visible to go */ state = ERR_VIS; else if (tmp == NULL) /* nowhere at all to go */ state = ERR_NULL; else /* got a new track */ { if (pback_should_cont(tmp, g_opts.tr.cont)) { *node = tmp; state = OK; } else state = ERR_RULES; } return state; }
state_t pback_play_node(pback_t *pback, node_t *node, int8_t mode) { state_t state; node_t *cur; if (node != NULL) { if (node_isleaf(node)) cur = node; else for (cur = node->br->head; node_isbranch(cur) && (cur->br->head != NULL); cur = cur->br->head); if (cur != NULL) { if (cur->t != NULL) { lists.play = node; if ((state = pback_play_leaf(pback, cur, mode)) == OK) { /* success */ } else info("pback_play_node(): pback_play_leaf() failed!\n"); } else { error("pback_play_node(): A trackless node!\n"); state = ERR_BADNODE; } } else { error("pback_play_node(): That branch has no leaves!\n"); state = ERR_NODE; } } else { error("pback_play_node(): Called on NULL node!\n"); state = ERR_NULL; } return state; }
/** * Find points in bbox * * quadtree_within(quadtree_t *tree, bbox_t *bbox, results_t *results) * @return void */ void quadtree_within(node_t *root, bounds_t *bounds, within_callback_t cb) { if (node_isleaf(root)) { cb(root->point); } else { if (root->sw && bounds_intersect(bounds, root->sw)) { quadtree_within(root->sw, bounds, cb); } if (root->se && bounds_intersect(bounds, root->se)) { quadtree_within(root->se, bounds, cb); } if (root->nw && bounds_intersect(bounds, root->nw)) { quadtree_within(root->nw, bounds, cb); } if (root->ne && bounds_intersect(bounds, root->ne)) { quadtree_within(root->ne, bounds, cb); } } }
state_t pback_start_strands(pback_t *pback, node_t *leaf, int8_t mode) { state_t state; /* check if libao is initialised */ if (!g_data.started.audio) { error("pback_start_strands(): libao isn't running! Bailing out.\n"); return ERR_AUDIO; } /* make sure we're not trying to play a branch */ if (!node_isleaf(leaf)) { error("pback_start_strands(): node parameter wasn't a leaf! Bailing out.\n"); return ERR_NODE; } /* If we weren't already playing, make a buffer and an output strand. */ if (mode == TR_START) { buf_init(&pback->buf, g_opts.au.numbufs); strand_outp_init(&pback->outp, &pback->buf, &leaf->t->au, &pback->outp.state); } /* Otherwise, delete the old decoder; a new one will be made below. */ else { strand_uninit(&pback->dec); /* If we're changing to a new track immediately, flush the buffer. */ if (mode == TR_CHANGE) buf_flush(&pback->buf); /* If the output strand encountered an error, it should also be * restarted. */ if (IS_ERR(pback->outp.state)) { buf_flush(&pback->buf); strand_uninit(&pback->outp); strand_outp_init(&pback->outp, &pback->buf, &leaf->t->au, &pback->outp.state); } } /* Now, create the new decoder. This is done every time a new track is * started, for obvious reasons. */ if (pback->dec.inited) { warn("pback_start_strands(): decoder already inited.\n"); strand_uninit(&pback->dec); } strand_dec_init(&pback->dec, leaf->t, &pback->buf, fmt_getfmts()[leaf->t->au.fmt], &pback->dec.state); if ((state = strand_setup(&pback->dec)) == OK) /* the decoder is happy */ { pback->dec.state = ST_STARTING; if ((state = strand_start(&pback->dec)) == OK) /* The decoder is running */ { /* the decoder started, so wipe the slate clean for this track */ leaf->t->avail = true; leaf->t->sane = true; lists.newleaf = leaf; if ((mode == TR_START) || IS_ERR(pback->outp.state)) /* The output strand must also be started */ { if ((state = strand_setup(&pback->outp)) == OK) /* the output strand is happy */ { pback->outp.state = ST_STARTING; if ((state = strand_start(&pback->outp)) == OK) /* The output strand is running */ { g_data.state = ST_PLAYING; pback->buf.lock = false; state = OK; } else { info("pback_start_strands(): strand_start(pback->outp) failed!\n"); pback->outp.state = state; } } else { info("pback_start_strands(): strand_setup(&pback->outp) failed!\n"); pback->outp.state = state; } } else /* the output strand was already running */ { pback->buf.lock = false; state = OK; } } else { info("pback_start_strands(): strand_start(pback->dec) failed!\n"); pback->dec.state = state; } } else { info("pback_start_strands(): strand_setup(&pback->dec) failed!\n"); pback->dec.state = state; leaf->t->sane = false; } return state; }