Home | History | Annotate | Download | only in server
      1 /* Copyright (c) 2015 The Chromium OS Authors. All rights reserved.
      2  * Use of this source code is governed by a BSD-style license that can be
      3  * found in the LICENSE file.
      4  */
      5 
      6 #include "cras_rstream.h"
      7 #include "cras_tm.h"
      8 #include "cras_types.h"
      9 #include "stream_list.h"
     10 #include "utlist.h"
     11 
     12 struct stream_list {
     13 	struct cras_rstream *streams;
     14 	struct cras_rstream *streams_to_delete;
     15 	stream_callback *stream_added_cb;
     16 	stream_callback *stream_removed_cb;
     17 	stream_create_func *stream_create_cb;
     18 	stream_destroy_func *stream_destroy_cb;
     19 	struct cras_tm *timer_manager;
     20 	struct cras_timer *drain_timer;
     21 };
     22 
     23 static void delete_streams(struct cras_timer *timer, void *data)
     24 {
     25 	struct cras_rstream *to_delete;
     26 	struct stream_list *list = (struct stream_list *)data;
     27 	int max_drain_delay = 0;
     28 
     29 	DL_FOREACH(list->streams_to_delete, to_delete) {
     30 		int drain_delay;
     31 
     32 		drain_delay = list->stream_removed_cb(to_delete);
     33 		if (drain_delay) {
     34 			max_drain_delay = MAX(max_drain_delay, drain_delay);
     35 			continue;
     36 		}
     37 		DL_DELETE(list->streams_to_delete, to_delete);
     38 		list->stream_destroy_cb(to_delete);
     39 	}
     40 
     41 	list->drain_timer = NULL;
     42 	if (max_drain_delay)
     43 		list->drain_timer = cras_tm_create_timer(list->timer_manager,
     44 				MAX(max_drain_delay, 10), delete_streams, list);
     45 }
     46 
     47 /*
     48  * Exported Interface
     49  */
     50 
     51 struct stream_list *stream_list_create(stream_callback *add_cb,
     52 				       stream_callback *rm_cb,
     53 				       stream_create_func *create_cb,
     54 				       stream_destroy_func *destroy_cb,
     55 				       struct cras_tm *timer_manager)
     56 {
     57 	struct stream_list *list = calloc(1, sizeof(struct stream_list));
     58 
     59 	list->stream_added_cb = add_cb;
     60 	list->stream_removed_cb = rm_cb;
     61 	list->stream_create_cb = create_cb;
     62 	list->stream_destroy_cb = destroy_cb;
     63 	list->timer_manager = timer_manager;
     64 	return list;
     65 }
     66 
     67 void stream_list_destroy(struct stream_list *list)
     68 {
     69 	free(list);
     70 }
     71 
     72 struct cras_rstream *stream_list_get(struct stream_list *list)
     73 {
     74 	return list->streams;
     75 }
     76 
     77 int stream_list_add(struct stream_list *list,
     78 		    struct cras_rstream_config *stream_config,
     79 		    struct cras_rstream **stream)
     80 {
     81 	int rc;
     82 
     83 	rc = list->stream_create_cb(stream_config, stream);
     84 	if (rc)
     85 		return rc;
     86 
     87 	DL_APPEND(list->streams, *stream);
     88 	rc = list->stream_added_cb(*stream);
     89 	if (rc) {
     90 		DL_DELETE(list->streams, *stream);
     91 		list->stream_destroy_cb(*stream);
     92 	}
     93 
     94 	return rc;
     95 }
     96 
     97 int stream_list_rm(struct stream_list *list, cras_stream_id_t id)
     98 {
     99 	struct cras_rstream *to_remove;
    100 
    101 	DL_SEARCH_SCALAR(list->streams, to_remove, stream_id, id);
    102 	if (!to_remove)
    103 		return -EINVAL;
    104 	DL_DELETE(list->streams, to_remove);
    105 	DL_APPEND(list->streams_to_delete, to_remove);
    106 	if (list->drain_timer) {
    107 		cras_tm_cancel_timer(list->timer_manager, list->drain_timer);
    108 		list->drain_timer = NULL;
    109 	}
    110 	delete_streams(NULL, list);
    111 
    112 	return 0;
    113 }
    114 
    115 int stream_list_rm_all_client_streams(struct stream_list *list,
    116 				      struct cras_rclient *rclient)
    117 {
    118 	struct cras_rstream *to_remove;
    119 	int rc = 0;
    120 
    121 	DL_FOREACH(list->streams, to_remove) {
    122 		if (to_remove->client == rclient) {
    123 			DL_DELETE(list->streams, to_remove);
    124 			DL_APPEND(list->streams_to_delete, to_remove);
    125 		}
    126 	}
    127 	if (list->drain_timer) {
    128 		cras_tm_cancel_timer(list->timer_manager, list->drain_timer);
    129 		list->drain_timer = NULL;
    130 	}
    131 	delete_streams(NULL, list);
    132 
    133 	return rc;
    134 
    135 }
    136 
    137