コード例 #1
0
ファイル: pre_suffix.c プロジェクト: chubbymaggie/Stranger
struct int_list_type *reachable_states_bounded_steps(DFA *M, int c1, int c2){

  paths state_paths, pp;
  int current;
  int steps;
  int sink = find_sink(M);

  struct int_list_type *worklist=NULL;
  struct int_list_type *nextlist=NULL;
  struct int_list_type *finallist = new_ilt();

  worklist = enqueue(worklist, M->s);

  for(steps=1; steps <=c2; steps++){
    while(worklist->count>0){
      current = dequeue(worklist); //dequeue returns the int value instead of the struct
      state_paths = pp = make_paths(M->bddm, M->q[current]);
      while (pp) {
	if(pp->to != sink){
	  nextlist=enqueue(nextlist, pp->to);
	  if(steps >= c1) finallist = enqueue(finallist, pp->to);
	}
	pp = pp->next;
      }
    }
    if(!nextlist) break;
    free(worklist);
    worklist = nextlist;
    nextlist = NULL;
  }

  print_ilt(finallist);
  return finallist;
}
コード例 #2
0
ファイル: pre_suffix.c プロジェクト: chubbymaggie/Stranger
/**
 * Muath documentation:
 * returns 1 (true) if there is a transition out of state 'state' not equal to lambda
 * end Muath documentation
 */
int isOtherLambdaOut(DFA* M, char* lambda, int state, int var){

	char* symbol;
	paths state_paths, pp;
	trace_descr tp;
	int j, sink;

    sink = find_sink(M);
    assert(sink >= 0);
    
	symbol = (char *) malloc((var + 1) * sizeof(char));
	state_paths = pp = make_paths(M->bddm, M->q[state]);

	while (pp) {
		if (pp->to != sink) {
			for (j = 0, tp = pp->trace; j < var && tp; j++, tp = tp->next) {
				if (tp) {
					if (tp->value)
						symbol[j] = '1';
					else
						symbol[j] = '0';
				} else
					symbol[j] = 'X';
			}
			symbol[j] = '\0';
			if (isNotExactEqual2Lambda(symbol, lambda, var))
				return 1;
		}
		pp = pp->next;
	} //end while
	return 0;
}
コード例 #3
0
ファイル: graph.c プロジェクト: SevensCao/LibStranger
bool isLengthFiniteTarjan(DFA *M, int var, int *indices)
{
    if (check_emptiness_minimized(M) || checkOnlyEmptyString(M, var, indices)) {
        return true;
    }

    int node;
    int SCCcount=0;
    bool sccFound = false;
    
    // we need sink just for printing
    int sink = find_sink(M);
    assert(sink >= 0);
    
    // convert dfa->graph, if there is any self cycle, stop and return
    if (dfa_to_graph(M)){
        return false;
    }

    
    vertexStatus=(int*) malloc(numOfNodes*sizeof(int));
    secondDFSrestarts=(int*) malloc(numOfNodes*sizeof(int));
    if (!vertexStatus || !secondDFSrestarts)
    {
        printf("malloc failedn");
        exit(0);
    }
    // DFS code
    for (node=0;node<numOfNodes;node++)
        vertexStatus[node]=WHITE;
    finishIndex=numOfNodes;
    for (node=0;node<numOfNodes;node++)
        if (vertexStatus[node]==WHITE)
            DFSvisit(node);
    
    reverseEdges();
    
    // DFS code
    for (node=0;node<numOfNodes;node++)
        vertexStatus[node]=WHITE;
    for (node=0;node<numOfNodes;node++)
        if (vertexStatus[secondDFSrestarts[node]]==WHITE)
        {
            SCCcount++;
//            printf("Strongly Connected Component %d\n",SCCcount);
            if(DFSvisit2(secondDFSrestarts[node], sink) == true){
//                printf("Found a real SCC on node %d\n", node);
                sccFound = true;
            }
            
        }
    
    free(edgeTab);
    free(firstEdge);
    free(vertexStatus);
    free(secondDFSrestarts);
    return !sccFound;
}
コード例 #4
0
static gboolean
create_sink (GstSplitMuxSink * splitmux)
{
  GstElement *provided_sink = NULL;

  g_return_val_if_fail (splitmux->active_sink == NULL, TRUE);

  GST_OBJECT_LOCK (splitmux);
  if (splitmux->provided_sink != NULL)
    provided_sink = gst_object_ref (splitmux->provided_sink);
  GST_OBJECT_UNLOCK (splitmux);

  if (provided_sink == NULL) {
    if ((splitmux->sink =
            create_element (splitmux, DEFAULT_SINK, "sink")) == NULL)
      goto fail;
    splitmux->active_sink = splitmux->sink;
  } else {
    if (!gst_bin_add (GST_BIN (splitmux), provided_sink)) {
      g_warning ("Could not add sink elements - splitmuxsink will not work");
      gst_object_unref (provided_sink);
      goto fail;
    }

    splitmux->active_sink = provided_sink;

    /* The bin holds a ref now, we can drop our tmp ref */
    gst_object_unref (provided_sink);

    /* Find the sink element */
    splitmux->sink = find_sink (splitmux->active_sink);
    if (splitmux->sink == NULL) {
      g_warning
          ("Could not locate sink element in provided sink - splitmuxsink will not work");
      goto fail;
    }
  }

  if (!gst_element_link (splitmux->muxer, splitmux->active_sink)) {
    g_warning ("Failed to link muxer and sink- splitmuxsink will not work");
    goto fail;
  }

  return TRUE;
fail:
  return FALSE;
}
コード例 #5
0
ファイル: pre_suffix.c プロジェクト: chubbymaggie/Stranger
DFA *dfa_Prefix(DFA *M, int c1, int c2, int var, int* indices) //Output M' so that L(M')={w| w'\in \Sigma*, ww' \in L(M), c_1 <= |w|<=c_2 }
{
  int i, sink;
  DFA *M1 = dfaSigmaC1toC2(c1, c2, var, indices);
  DFA *M2 = dfaCopy(M);
  //dfaPrintVerbose(M2);
  sink = find_sink(M);
  for(i=0; i<M2->ns; i++){
    if(i!= sink) M2->f[i]=1;
  }
  //dfaPrintVerbose(M2);
  DFA *result = dfa_intersect(M2, M1);
  //dfaPrintVerbose(result);
  dfaFree(M1);
  dfaFree(M2);
  return dfaMinimize(result);

}//end of prefix
コード例 #6
0
ファイル: graph.c プロジェクト: SevensCao/LibStranger
unsigned dfaGetDegree(DFA *M, unsigned state){
    int ssink = find_sink(M);
    unsigned sink;
    if (ssink == -1)
        sink = UINT_MAX;
    else
        sink = ssink;
    assert(state != sink);
    
    paths state_paths, pp;
    unsigned nextStatesSize = 16, nextStatesIndex = 0, degree = 0;
    unsigned *nextStates = (unsigned*) malloc((size_t) (nextStatesSize) * sizeof(unsigned));
    mem_zero(nextStates, (size_t) (nextStatesSize) * sizeof(unsigned));
    /*******************  find node degree *********************/
    state_paths = pp = make_paths(M->bddm, M->q[state]);
    while (pp) {
        if (pp->to != sink){
            bool found = false;
            for (nextStatesIndex = 0; nextStatesIndex < degree; nextStatesIndex++) {
                if (pp->to == nextStates[nextStatesIndex]){
                    found = true;
                    break;
                }
            }
            if (!found){
                if (degree < nextStatesSize){
                    nextStates[degree] = pp->to;
                }
                else {
                    unsigned oldSize = nextStatesSize;
                    nextStatesSize *= 2;
                    nextStates = (unsigned*) mem_resize(nextStates, (size_t)(nextStatesSize) * sizeof(unsigned));
                    mem_zero(nextStates + oldSize, (size_t) (nextStatesSize - oldSize) * sizeof(unsigned));
                    nextStates[degree] = pp->to;
                }
                degree++;
            }
        }
        pp = pp->next;
    }
    kill_paths(state_paths);
    free(nextStates);
    return degree;
}
コード例 #7
0
static osync_bool get_changes(Command *cmd, SyncType type, OSyncError **error)
{
	OSyncObjTypeSink *sink = NULL;
	OSyncList *list;
	OSyncList *objtypesinks = NULL;
	const char *objtype = cmd->arg;

	if (objtype) {
		sink = find_sink(objtype, error);
		if (!sink)
			goto error;

		cmd->sink = sink;
		if (!get_changes_sink(cmd, sink, type, error))
			goto error;

	} else {
		/* all available objtypes */
		objtypesinks = osync_plugin_info_get_objtype_sinks(plugin_info);
		list = objtypesinks;
		while(list) {
			sink = (OSyncObjTypeSink*)list->data;

			cmd->sink = sink;
			if (!get_changes_sink(cmd, sink, type, error))
				goto error;
			list = list->next;
		}
		/* last but not least - the main sink */
		if (get_main_sink())
			if (!get_changes_sink(cmd, get_main_sink(), type, error))
				goto error;
		
		osync_list_free(objtypesinks);
	}

	return TRUE;

 error:
	osync_list_free(objtypesinks);
	return FALSE;
}
コード例 #8
0
ファイル: graph.c プロジェクト: SevensCao/LibStranger
unsigned dfaGetMaxDegree(DFA *M, unsigned *p_maxState){
    int ssink = find_sink(M);
    unsigned sink;
    if (ssink == -1)
        sink = UINT_MAX;
    else
        sink = ssink;
    
    unsigned state = 0, maxState = 0, maxDegree = 0, degree = 0;
    
    for (state = 0; state < M->ns; state++){
        degree = dfaGetDegree(M, state);
        if (maxDegree < degree){
            maxDegree = degree;
            maxState = state;
        }
    }
    
    *p_maxState = maxState;
    return maxDegree;
}
コード例 #9
0
static osync_bool commit(Command *cmd, OSyncChange *change, OSyncError **error)
{
	OSyncList *list;
	OSyncList *objtypesinks = NULL;
	OSyncObjTypeSink *sink = NULL;
	const char *objtype = cmd->arg;

	assert(change);

	if (objtype) {
		sink = find_sink(objtype, error);
		if (!sink)
			goto error;

		if (!commit_sink(cmd, sink, change, error))
			goto error;
	} else {
		objtypesinks = osync_plugin_info_get_objtype_sinks(plugin_info);
		list = objtypesinks;
		while(list){
			sink = (OSyncObjTypeSink*)list->data;

			if (!commit_sink(cmd, sink, change, error))
				goto error;
			list = list->next;
		}

		/* last but not least - the main sink */
		if (get_main_sink())
			if (!commit_sink(cmd, get_main_sink(), change, error))
				goto error;
		
		osync_list_free(objtypesinks);
	}
	
	return TRUE;
 error:
	osync_list_free(objtypesinks);
	return FALSE;
}
コード例 #10
0
ファイル: pre_suffix.c プロジェクト: chubbymaggie/Stranger
/**
 * Muath documentation:
 * returns a list of states containing each state s that has at least one transition on lambda
 * into it and one transition on non-lambda out of it (except for sink state which is ignored)
 * end Muath documentation
 */
struct int_list_type *reachable_states_lambda_in_nout(DFA *M, char *lambda, int var){

	paths state_paths, pp;
	trace_descr tp;
	int j, current;
	int sink = find_sink(M);
	char *symbol;
	struct int_list_type *finallist=NULL;
	if(_FANG_DFA_DEBUG)dfaPrintVerbose(M);
	symbol=(char *)malloc((var+1)*sizeof(char));
	for(current=0; current<M->ns; current++){
		state_paths = pp = make_paths(M->bddm, M->q[current]);
		while (pp) {
			if(pp->to != sink){
				// construct transition from current to pp->to and store it in symbol
				for (j = 0, tp = pp->trace; j < var && tp; j++, tp = tp->next) {
					if (tp) {
						if (tp->value) symbol[j]='1';
						else symbol[j]='0';
					}
					else
						symbol[j]='X';
				}
				symbol[j]='\0';
				// if transition from current state to pp->to state is on labmda
				if(isEqual2Lambda(symbol, lambda, var)){
					// if there is a transition out of pp->to state on non-lambda then add pp->to to returned list
					if(isOtherLambdaOut(M, lambda, (pp->to), var)) finallist = enqueue(finallist, pp->to);
				}
			}
			pp = pp->next;
		}
	}

	if(_FANG_DFA_DEBUG) print_ilt(finallist);
	free(symbol);
	return finallist;
}
コード例 #11
0
ファイル: graph.c プロジェクト: SevensCao/LibStranger
/*
 TODO: should return transition relation with the sink in it then add a function to
 remove the sink.
 This will break Tarjan length algorithm so it should be changed to take relation
 after removing the sink.
 it will also break pre_add_slashes which should not do any shifting
 */
pTransitionRelation dfaGetTransitionRelation(DFA *M){
    unsigned state, degree, nextState, i;
    state = degree = nextState = 0;
    paths state_paths, pp;
    
    int sink = find_sink(M);
    assert(sink >= 0);//assert that there is a sink
    
    pTransitionRelation p_transitionRelation = (pTransitionRelation) malloc(sizeof(transitionRelation));
    p_transitionRelation->reverse = false;
    p_transitionRelation->selfCycles = false;
    p_transitionRelation->sink = (unsigned)sink;
    p_transitionRelation->num_of_nodes = M->ns - 1;
    p_transitionRelation->num_of_edges = 0;
    p_transitionRelation->adjList = (unsigned**) malloc((size_t)
                                                        (p_transitionRelation->num_of_nodes) * sizeof(unsigned*));
    mem_zero(p_transitionRelation->adjList, (size_t) p_transitionRelation->num_of_nodes * sizeof(unsigned*) );
    p_transitionRelation->degrees = (t_st_word*) malloc((size_t)
                                                             (p_transitionRelation->num_of_nodes) * sizeof(t_st_word));
    mem_zero(p_transitionRelation->degrees, (size_t) p_transitionRelation->num_of_nodes * sizeof(t_st_word));
    bool *nextStates = (bool*) malloc((size_t) (p_transitionRelation->num_of_nodes) * sizeof(bool));
    
    unsigned numOfAcceptStates = 0;
    // a heuristic assuming 1/20th of states are accepting
    unsigned acceptSizeTemp = (M->ns < 100)? 4 : roundToNextPow2(M->ns / 20);
    p_transitionRelation->acceptsSize = (p_transitionRelation->num_of_nodes < acceptSizeTemp)? p_transitionRelation->num_of_nodes : acceptSizeTemp;
    p_transitionRelation->accepts = (unsigned *) mem_alloc((size_t) p_transitionRelation->acceptsSize * sizeof(unsigned));
    mem_zero(p_transitionRelation->accepts, (size_t) p_transitionRelation->acceptsSize * sizeof(unsigned));
    
    for (i = 0; i < M->ns; i++){
        if (M->f[i] == 1){
            p_transitionRelation->accepts[numOfAcceptStates++] = (i < sink)? i : i - 1;
            if (numOfAcceptStates == p_transitionRelation->acceptsSize){
                unsigned acceptSizeTemp = p_transitionRelation->acceptsSize * 2;
                p_transitionRelation->acceptsSize = (p_transitionRelation->num_of_nodes < acceptSizeTemp)? p_transitionRelation->num_of_nodes : acceptSizeTemp;
                p_transitionRelation->accepts = (unsigned*) mem_resize(p_transitionRelation->accepts, (size_t) p_transitionRelation->acceptsSize * sizeof(unsigned));
                mem_zero(p_transitionRelation->accepts + numOfAcceptStates, (size_t) (p_transitionRelation->acceptsSize - numOfAcceptStates) * sizeof(unsigned));
            }
        }
        
        if (sink == i)
            continue;
        else if (sink < i)
            state = i - 1;//shift state
        else
            state = i;
//        printf("i = %d for state = %u\n", i, state);
        /*******************  find node degree *********************/
        memset(nextStates, false, sizeof(bool) * (p_transitionRelation->num_of_nodes));
        state_paths = pp = make_paths(M->bddm, M->q[i]);
        while (pp) {
            if (pp->to == i)
                p_transitionRelation->selfCycles = true;
            unsigned to = (sink < pp->to)? pp->to - 1 : pp->to;
            if (pp->to != sink){
                if (nextStates[to] == false){
                    nextStates[to] = true;
                    p_transitionRelation->degrees[state]++;
                    p_transitionRelation->num_of_edges++;
                }
            }
            pp = pp->next;
        }
        kill_paths(state_paths);
        /*******************  allocate node's adjacency list and fill it up *********************/
        if (p_transitionRelation->degrees[state] == 0) {
            p_transitionRelation->adjList[state]  = NULL;
        }
        else {
            p_transitionRelation->adjList[state] = (unsigned *) malloc((size_t) (p_transitionRelation->degrees[state]) * sizeof(unsigned) );
            mem_zero(p_transitionRelation->adjList[state],(size_t) (p_transitionRelation->degrees[state]) * sizeof(unsigned));
            for (nextState = 0, degree = 0; nextState < p_transitionRelation->num_of_nodes; nextState++) {
                if (nextStates[nextState] == true){
                    assert(degree < p_transitionRelation->degrees[state]);
                    p_transitionRelation->adjList[state][degree] = nextState;
                    degree++;
                }
            }
        }
    }
    
    p_transitionRelation->acceptsSize = numOfAcceptStates;
    p_transitionRelation->accepts = (unsigned*) mem_resize((p_transitionRelation->accepts), ((p_transitionRelation->acceptsSize) * sizeof(unsigned)));

    qsort(p_transitionRelation->accepts, p_transitionRelation->acceptsSize, sizeof(unsigned), intcmpfunc);
    
    free(nextStates);
    return p_transitionRelation;
}
コード例 #12
0
ファイル: pre_suffix.c プロジェクト: chubbymaggie/Stranger
DFA *dfa_Suffix(DFA *M, int c1, int c2, int var, int *oldindices)
{
  DFA *result = NULL;
  DFA *tmpM = NULL;
  int aux=0;
  struct int_list_type *states=NULL;
  struct int_type *tmpState=NULL;

  int maxCount = 0;

  int *indices = oldindices; //indices is updated if you need to add auxiliary bits

  paths state_paths, pp;
  trace_descr tp;

  int i, j, z, k;

  char *exeps;
  int *to_states;
  long max_exeps;
  char *statuces;
  int len=var;
  int sink;

  char *auxbit=NULL;


  //	char *apath =bintostr(a, var);

  states = reachable_states_bounded_steps(M, c1, c2);
  maxCount = states->count;

  if(maxCount>0){ //Need auxiliary bits when there exist some outgoing edges
    aux = get_hsig(maxCount);
    if(_FANG_DFA_DEBUG) printf("\n There are %d reachable states, need to add %d auxiliary bits\n", maxCount, aux);
    auxbit = (char *) malloc(aux*sizeof(char));
    len = var+aux; // extra aux bits
    indices = allocateArbitraryIndex(len);
  }



  max_exeps=1<<len; //maybe exponential
  sink=find_sink(M);
  assert(sink >-1);

  //pairs[i] is the list of all reachable states by \sharp1 \bar \sharp0 from i


  dfaSetup(M->ns+1, len, indices); //add one new initial state
  exeps=(char *)malloc(max_exeps*(len+1)*sizeof(char)); //plus 1 for \0 end of the string
  to_states=(int *)malloc(max_exeps*sizeof(int));
  statuces=(char *)malloc((M->ns+2)*sizeof(char));

  //printf("Before Replace Char\n");
  //dfaPrintVerbose(M);

  k=0;
  //setup for the initial state
  tmpState = states->head;
  for (z=1; z<=states->count; z++) {
    state_paths = pp = make_paths(M->bddm, M->q[tmpState->value]);
    while (pp) {
      if(pp->to!=sink){
	to_states[k]=pp->to+1; //insert itself as the initial state
	for (j = 0; j < var; j++) {
	  //the following for loop can be avoided if the indices are in order
	  for (tp = pp->trace; tp && (tp->index != indices[j]); tp =tp->next);
	  if (tp) {
	    if (tp->value) exeps[k*(len+1)+j]='1';
	    else exeps[k*(len+1)+j]='0';
	  }else{
	    exeps[k*(len+1)+j]='X';
	  }
	}
	set_bitvalue(auxbit, aux, z); // aux = 3, z=4, auxbit 001
	for (j = var; j < len; j++) { //set to xxxxxxxx100
	  exeps[k*(len+1)+j]=auxbit[len-j-1];
	}
	exeps[k*(len+1)+len]='\0';
	k++;
      }
      pp = pp->next;
    }//end while
    kill_paths(state_paths);
    tmpState = tmpState->next;
  } //end for

  dfaAllocExceptions(k);
  for(k--;k>=0;k--)
    dfaStoreException(to_states[k],exeps+k*(len+1));
  dfaStoreState(sink+1);

  if(check_accept(M, states))	statuces[0]='+';
  else 	statuces[0]='0';



  //for the rest of states (shift one state)
  for (i = 0; i < M->ns; i++) {

    state_paths = pp = make_paths(M->bddm, M->q[i]);
    k=0;

    while (pp) {
      if(pp->to!=sink){
	for (tp = pp->trace; tp && (tp->index != indices[var]); tp =tp->next); //find the bar value
	if (!tp || !(tp->value)) {
	  to_states[k]=pp->to+1;
	  for (j = 0; j < var; j++) {
	    //the following for loop can be avoided if the indices are in order
	    for (tp = pp->trace; tp && (tp->index != indices[j]); tp =tp->next);

	    if (tp) {
	      if (tp->value) exeps[k*(len+1)+j]='1';
	      else exeps[k*(len+1)+j]='0';
	    }
	    else
	      exeps[k*(len+1)+j]='X';
	  }
	  for (j = var; j < len; j++) {
	    exeps[k*(len+1)+j]='0';
	  }
	  exeps[k*(len+1)+len]='\0';
	  k++;
	}
      }
      pp = pp->next;
    }//end while

    dfaAllocExceptions(k);
    for(k--;k>=0;k--)
      dfaStoreException(to_states[k],exeps+k*(len+1));
    dfaStoreState(sink+1);

    if(M->f[i]==1)
      statuces[i+1]='+';
    else if(M->f[i]==-1)
      statuces[i+1]='-';
    else
      statuces[i+1]='0';

    kill_paths(state_paths);
  }

  statuces[M->ns+1]='\0';
  result=dfaBuild(statuces);
  //	dfaPrintVerbose(result);
  for(i=0; i<aux; i++){
    j=len-i-1;
    tmpM =dfaProject(result, (unsigned) j);
    dfaFree(result);
    result = dfaMinimize(tmpM);
    dfaFree(tmpM);
    //		printf("\n After projecting away %d bits", j);
    //		dfaPrintVerbose(result);
  }
  free(exeps);
  //printf("FREE ToState\n");
  free(to_states);
  //printf("FREE STATUCES\n");
  free(statuces);

  if(maxCount>0) free(auxbit);

  free_ilt(states);

  return dfaMinimize(result);

}
コード例 #13
0
static void on_set_debug(pa_core* c, pa_proplist* p, int debug_sink_id, const char* ext_args)
{
    const char* device_name = pa_proplist_gets(p, PROPLIST_KEY_DEVICE);
    if (!device_name) {
        pa_log_error("device not specific!");
        return;
    }

    int device_id = atoi(device_name);
    pa_sink* sink = NULL;
    pa_source* source = NULL;
    sink = find_sink(c, device_id);

    if (!sink) {
        source = find_source(c, device_id);
    }

    if (!sink && !source) {
        pa_log_error("sink/source of device id %s not found!", device_name);
        return;
    }

    pa_sample_spec ss;
    pa_channel_map map;

    if (sink) {
        ss = sink->sample_spec;
        map = sink->channel_map;
    }
    else {
        ss = source->sample_spec;
        map = source->channel_map;
    }

    if (debug_sink_id == EAUDIO_STREAM_DEVICE_VIRTUALOUPUT_REMOTE) {
        ss.rate = 8000;
        ss.format = PA_SAMPLE_U8;
        ss.channels = 1;
        map.channels = 1;
    }

    char sink_name[64];
    GET_PLUGIN_NAME(sink_name, debug_sink_id);

    pa_module* link_module = NULL;
    const char* str_func = pa_proplist_gets(p, PROPLIST_VALUE_FUNC);
    bool func_on = true;
    if (str_func) {
        func_on = !strcmp(str_func, PROPLIST_VALUE_TRUE);
    }

    if (sink) {
        link_module = sink->module;
    }
    else if (source) {
        link_module = source->module;
    }

    if (func_on) {

        pa_pre_load_func_t f = pa_get_user_data(PA_USER_SINK_PRELOAD_FUNC);
        if (f) {
            f(sink_name, c, &ss, &map, ext_args);
        }

        pa_sink* remote_sink = pa_namereg_get(c, sink_name, PA_NAMEREG_SINK);
        if (!remote_sink) {
            pa_log_error("remote-sink load failed");
            return;
        }

        char args[256] = { 0 };
        char loopback_name[128] = { 0 };
        const char* i_name = NULL;
        const char* o_name = NULL;

        if (sink) {
            i_name = sink->monitor_source->name;
            o_name = remote_sink->name;
        }
        else if (source) {
            i_name = source->name;
            o_name = remote_sink->name;
        }

        pa_snprintf(loopback_name, sizeof(loopback_name), "Loopback(%s->%s)", i_name, o_name);
        pa_snprintf(args, sizeof(args), "name=%s source=%s sink=%s token=%u %s", loopback_name, i_name, o_name, MAGIC_TOKEN_ID, ext_args ? ext_args : "");

        pa_log_info("load-module module-loopback args: %s", args);
        pa_module* m = pa_module_load(c, "module-loopback", args);
        if (!m) {
            pa_log_error("on_set_debug module load err.");
            return;
        }

        if (link_module) {
            pa_proplist_sets(link_module->proplist, PA_PROP_LINK_LOOPBACK_ID, loopback_name);
        }
    }
    else {

        pa_sink* remote_sink = find_sink(c, debug_sink_id);
        if (remote_sink) {
            pa_log_info("unloading remote_sink %d", debug_sink_id);
            pa_module_unload_request(remote_sink->module, true);
        }

    }
}
コード例 #14
0
void on_set_common(pa_proplist* p, pa_tagstruct* t, pa_core* c)
{
    pa_log_info("on_set_common");

    const char* attribute = pa_proplist_gets(p, PROPLIST_KEY_ATTRIBUTE);
    if (!attribute) {
        pa_log_error("on_set_common: attribute not found!");
        return;
    }

    if (!strcmp(attribute, PROPLIST_VALUE_GET_INFO)) {
        const char* str_device = pa_proplist_gets(p, PROPLIST_KEY_DEVICE);
        if (!str_device) {
            pa_log_error("on_set_common device not specific!");
            return;
        }

        int device_id = atoi(str_device);
        pa_sink* sink = NULL;
        pa_source* source = NULL;

        sink = find_sink(c, device_id);
        if (!sink) {
            source = find_source(c, device_id);
        }

        if (!sink && !source) {
            pa_log_error("do not find any sink or source of device %d", device_id);
            return;
        }

        int n_used = 0;
        if (sink) {
            n_used = pa_module_get_n_used(sink->module);
        }
        else {
            n_used = pa_module_get_n_used(source->module);
        }

        char value[32];
        snprintf(value, sizeof(value), "%d", n_used);
        pa_proplist* replyp = pa_proplist_new();
        pa_proplist_sets(replyp, PROPLIST_KEY_VALUE, value);
        pa_tagstruct_put_proplist(t, replyp);
        pa_proplist_free(replyp);
    }
    else if (!strcmp(attribute, PROPLIST_VALUE_REMOTE_SINK)) {
#ifdef HAVE_WEB_SOCKET
        extern void start_web_socket();
        start_web_socket();
#endif
        on_set_debug(c, p, EAUDIO_STREAM_DEVICE_VIRTUALOUPUT_REMOTE, NULL);
    }
    else if (!strcmp(attribute, PROPLIST_VALUE_FILE_SINK)) {
        const char* str_path = pa_proplist_gets(p, PROPLIST_VALUE_PATH);
        char args[64] = { 0 };
        if (str_path) {
            snprintf(args, sizeof(args), "path=%s", str_path);
        }
        on_set_debug(c, p, EAUDIO_STREAM_DEVICE_VIRTUALOUPUT_FILE, str_path ? args : NULL);
    }
    else if (!strcmp(attribute, PROPLIST_VALUE_ALSA_BUFFER)) {
        const char* str_device = pa_proplist_gets(p, PROPLIST_KEY_DEVICE);
        if (!str_device) {
            pa_log_error("on_set_common alsa-buffer device not specific!");
            return;
        }

        int device = atoi(str_device);
        pa_sink* s = find_sink(c, device);
        if (!s) {
            pa_log_error("sink not found %d", device);
            return;
        }

        pa_usec_t left_to_play = pa_sink_get_left_to_play(s);
        pa_proplist* replyp = pa_proplist_new();
        pa_proplist_set(replyp, PROPLIST_KEY_COMMAND_RESULT, &left_to_play, sizeof(left_to_play));
        pa_tagstruct_put_proplist(t, replyp);
        pa_proplist_free(replyp);
    }
    else if (!strcmp(attribute, PROPLIST_VALUE_STOP_TEST)) {
        pthread_t tid_stop;
        int err = pthread_create(&tid_stop, NULL, stop_thread, NULL);
        if (err != 0) {
            pa_log_error("can't create thread: %s\n", strerror(err));
            return;
        }
    }
#ifdef HAVE_WEB_SOCKET
        else if (!strcmp(attribute, "web-start")) {
            extern void start_web_socket();
            start_web_socket();
        }
        else if (!strcmp(attribute, "web-stop")) {
            extern void stop_web_socket();
            stop_web_socket();
        }
#endif
}