static void change_transport_state(enum transport_state new_state) { transport_state_ = new_state; assert(new_state >= TRANSPORT_STOPPED && new_state < TRANSPORT_NO_MEDIA_PRESENT); if (!replace_var(TRANSPORT_VAR_TRANSPORT_STATE, transport_states[new_state])) { return; // no change. } const char *available_actions = NULL; switch (new_state) { case TRANSPORT_STOPPED: if (strlen(get_var(TRANSPORT_VAR_AV_URI)) == 0) { available_actions = "PLAY"; } else { available_actions = "PLAY,SEEK"; } break; case TRANSPORT_PLAYING: available_actions = "PAUSE,STOP,SEEK"; break; case TRANSPORT_PAUSED_PLAYBACK: available_actions = "PLAY,STOP,SEEK"; break; case TRANSPORT_TRANSITIONING: case TRANSPORT_PAUSED_RECORDING: case TRANSPORT_RECORDING: case TRANSPORT_NO_MEDIA_PRESENT: // We should not switch to this state. break; } if (available_actions) { replace_var(TRANSPORT_VAR_CUR_TRANSPORT_ACTIONS, available_actions); } }
static int set_next_avtransport_uri(struct action_event *event) { if (obtain_instanceid(event, NULL) < 0) { return -1; } char *next_uri = upnp_get_string(event, "NextURI"); if (next_uri == NULL) { return -1; } int rc = 0; service_lock(); output_set_next_uri(next_uri); replace_var(TRANSPORT_VAR_NEXT_AV_URI, next_uri); char *next_uri_meta = upnp_get_string(event, "NextURIMetaData"); if (next_uri_meta == NULL) { rc = -1; } else { replace_var(TRANSPORT_VAR_NEXT_AV_URI_META, next_uri_meta); } service_unlock(); free(next_uri); free(next_uri_meta); return rc; }
static void change_and_notify_transport(enum transport_state new_state) { const int state_different = (transport_state_ != new_state); transport_state_ = new_state; assert(new_state >= TRANSPORT_STOPPED && new_state < TRANSPORT_NO_MEDIA_PRESENT); change_var_and_notify(TRANSPORT_VAR_TRANSPORT_STATE, transport_states[new_state]); if (!state_different) return; switch (new_state) { case TRANSPORT_STOPPED: if (strlen(transport_values[TRANSPORT_VAR_AV_URI]) == 0) { replace_var(TRANSPORT_VAR_CUR_TRANSPORT_ACTIONS, "PLAY"); } else { replace_var(TRANSPORT_VAR_CUR_TRANSPORT_ACTIONS, "PLAY,SEEK"); } break; case TRANSPORT_PLAYING: replace_var(TRANSPORT_VAR_CUR_TRANSPORT_ACTIONS, "PAUSE,STOP,SEEK"); break; case TRANSPORT_PAUSED_PLAYBACK: replace_var(TRANSPORT_VAR_CUR_TRANSPORT_ACTIONS, "PLAY,STOP,SEEK"); break; case TRANSPORT_TRANSITIONING: case TRANSPORT_PAUSED_RECORDING: case TRANSPORT_RECORDING: case TRANSPORT_NO_MEDIA_PRESENT: break; } }
// We constantly update the track time to event about it to our clients. static void *thread_update_track_time(void *userdata) { const gint64 one_sec_unit = 1000000000LL; char tbuf[32]; gint64 last_duration = -1, last_position = -1; for (;;) { usleep(500000); // 500ms service_lock(); gint64 duration, position; const int pos_result = output_get_position(&duration, &position); if (pos_result == 0) { if (duration != last_duration) { print_upnp_time(tbuf, sizeof(tbuf), duration); replace_var(TRANSPORT_VAR_CUR_TRACK_DUR, tbuf); last_duration = duration; } if (position / one_sec_unit != last_position) { print_upnp_time(tbuf, sizeof(tbuf), position); replace_var(TRANSPORT_VAR_REL_TIME_POS, tbuf); last_position = position / one_sec_unit; } } service_unlock(); } return NULL; // not reached. }
static void shared_meta_time_change(uint32_t total, uint32_t current) { char tbuf[32]; service_lock(); print_upnp_time(tbuf, sizeof(tbuf), total); replace_var(TRANSPORT_VAR_CUR_TRACK_DUR, tbuf); print_upnp_time(tbuf, sizeof(tbuf), current); replace_var(TRANSPORT_VAR_REL_TIME_POS, tbuf); service_unlock(); }
// Callback from our output if the song meta data changed. static void update_meta_from_stream(const struct SongMetaData *meta) { if (meta->title == NULL || strlen(meta->title) == 0) { return; } const char *original_xml = get_var(TRANSPORT_VAR_AV_URI_META); char *didl = SongMetaData_to_DIDL(meta, original_xml); service_lock(); replace_var(TRANSPORT_VAR_AV_URI_META, didl); replace_var(TRANSPORT_VAR_CUR_TRACK_META, didl); service_unlock(); free(didl); }
// Callback from our output if the song meta data changed. static void update_meta_from_stream(const struct SongMetaData *meta) { if (meta->title == NULL || strlen(meta->title) == 0) { return; } const char *original_xml = transport_values[TRANSPORT_VAR_AV_URI_META]; char *didl = SongMetaData_to_DIDL(original_xml, meta); service_lock(); replace_var(TRANSPORT_VAR_AV_URI_META, didl); replace_var(TRANSPORT_VAR_CUR_TRACK_META, didl); notify_changed_uris(); service_unlock(); free(didl); }
// Transport uri always comes in uri/meta pairs. Set these and also the related // track uri/meta variables. // Returns 1, if this meta-data likely needs to be updated while the stream // is playing (e.g. radio broadcast). static int replace_transport_uri_and_meta(const char *uri, const char *meta) { replace_var(TRANSPORT_VAR_AV_URI, uri); replace_var(TRANSPORT_VAR_AV_URI_META, meta); // This influences as well the tracks. If there is a non-empty URI, // we have exactly one track. const char *tracks = (uri != NULL && strlen(uri) > 0) ? "1" : "0"; replace_var(TRANSPORT_VAR_NR_TRACKS, tracks); // We only really want to send back meta data if we didn't get anything // useful or if this is an audio item. const int requires_stream_meta_callback = (strlen(meta) == 0) || strstr(meta, "object.item.audioItem"); return requires_stream_meta_callback; }
void MatLabExporter::paracada(t_output &out, t_proceso_it r, t_proceso_it q, string tabs){ string var=ToLower((*r).par2), aux=ToLower((*r).par1); const int *dims=memoria->LeerDims(var); if (!dims) { insertar(out,string("ERROR: ")+var+" NO ES UN ARREGLO"); return; } int n=dims[0]; string *auxvars=new string[n]; for(int i=0;i<n;i++) auxvars[i]=get_aux_varname("aux_index_"); string vname=var, sep="("; for(int i=0;i<n;i++) { string idx=auxvars[i]; insertar(out,tabs+"for "+idx+"=1:size("+var+","+IntToStr(i+1)+")"); vname+=sep+idx; sep=","; tabs+="\t"; } vname+=")"; for(int i=n-1;i>=0;i--) release_aux_varname(auxvars[i]); delete []auxvars; t_output aux_out; bloque(aux_out,++r,q,tabs); replace_var(aux_out,aux,vname); insertar_out(out,aux_out); for(int i=0;i<n;i++) { tabs.erase(tabs.size()-1); insertar(out,tabs+"end"); } }
void upnp_transport_init(struct upnp_device *device) { assert(transport_service_.last_change == NULL); transport_service_.last_change = UPnPLastChangeCollector_new(state_variables_, TRANSPORT_EVENT_XML_NS, device, TRANSPORT_SERVICE_ID); // Times and counters should not be evented. We only change REL_TIME // right now anyway (AVTransport-v1 document, 2.3.1 Event Model) UPnPLastChangeCollector_add_ignore(transport_service_.last_change, TRANSPORT_VAR_REL_TIME_POS); UPnPLastChangeCollector_add_ignore(transport_service_.last_change, TRANSPORT_VAR_ABS_TIME_POS); UPnPLastChangeCollector_add_ignore(transport_service_.last_change, TRANSPORT_VAR_REL_CTR_POS); UPnPLastChangeCollector_add_ignore(transport_service_.last_change, TRANSPORT_VAR_ABS_CTR_POS); pthread_t thread; pthread_create(&thread, NULL, thread_update_track_time, NULL); //we auto play when device start , slave mode do not auto play if(g_device_play_mode != DEVICE_PLAY_MODE_SLAVE && !access(M3U_STREAMINGPLAYLIST_PATH, 0)){ if(!output_set_playlist(M3U_STREAMINGPLAYLIST_PATH)){ replace_var(TRANSPORT_VAR_AAT_PLAYLIST_STEP, "Reset"); if(!output_play(NULL)) change_transport_state(TRANSPORT_PLAYING); } //auto play end } }
static int seek(struct action_event *event) { if (obtain_instanceid(event, NULL) < 0) { return -1; } char *unit = upnp_get_string(event, "Unit"); if (strcmp(unit, "REL_TIME") == 0) { // This is the only thing we support right now. char *target = upnp_get_string(event, "Target"); gint64 nanos = parse_upnp_time(target); service_lock(); if (output_seek(nanos) == 0) { // TODO(hzeller): Seeking might take some time, // pretend to already be there. Should we go into // TRANSITION mode ? // (gstreamer will go into PAUSE, then PLAYING) replace_var(TRANSPORT_VAR_REL_TIME_POS, target); } service_unlock(); free(target); } free(unit); return 0; }
static int set_streaming_playlist(struct action_event *event) { if (obtain_instanceid(event, NULL) < 0) { return -1; } char *playlistdata = upnp_get_string(event, "PlaylistData"); if (playlistdata == NULL) { return -1; } int playlistdatalength = atoi(upnp_get_string(event, "PlaylistDataLength")); /*char *playlistmimetype = upnp_get_string(event, "PlaylistMIMEType"); if (playlistmimetype == NULL) { free(playlistdata); return -1; } */ char *playliststep = upnp_get_string(event, "PlaylistStep"); //Initial Continue Stop Reset if (playliststep == NULL) { free(playlistdata); // free(playlistmimetype); return -1; } int rc = 0; service_lock(); if(strcmp(playliststep, "Initial") == 0){ //TODO: rc = write_playlist(event, playlistdata, playlistdatalength, "w"); } if(strcmp(playliststep, "Continue") == 0){ rc = write_playlist(event, playlistdata, playlistdatalength, "a"); } if(strcmp(playliststep, "Stop") == 0){ //TODO: Indicates that the current streaming playlist operation will end when all pending playlist data at then device is consumed. if(playlistdata) rc = write_playlist(event, playlistdata, playlistdatalength, "a"); output_set_playlist(M3U_STREAMINGPLAYLIST_PATH); } if(strcmp(playliststep, "Reset") == 0){ //TODO: Indicates that processing of the current streaming playlist ends immediately. any pending playlist data for the streaming playlist is discarded. output_set_playlist(M3U_STREAMINGPLAYLIST_PATH); } if(!rc) replace_var(TRANSPORT_VAR_AAT_PLAYLIST_STEP, playliststep); service_unlock(); if(playlistdata) free(playlistdata); free(playliststep); return rc; }
static int set_mute(struct action_event *event) { const char *value = upnp_get_string(event, "DesiredMute"); service_lock(); const int do_mute = atoi(value); set_mute_toggle(do_mute); replace_var(CONTROL_VAR_MUTE, do_mute ? "1" : "0"); service_unlock(); return 0; }
static void inform_done_playing(enum PlayFeedback fb) { printf("---------------------------------- Done playing....%d\n", fb); service_lock(); switch (fb) { case PLAY_STOPPED: replace_transport_uri_and_meta("", ""); change_and_notify_transport(TRANSPORT_STOPPED); notify_changed_uris(); break; case PLAY_STARTED_NEXT_STREAM: replace_transport_uri_and_meta( transport_values[TRANSPORT_VAR_NEXT_AV_URI], transport_values[TRANSPORT_VAR_NEXT_AV_URI_META]); replace_var(TRANSPORT_VAR_NEXT_AV_URI, ""); replace_var(TRANSPORT_VAR_NEXT_AV_URI_META, ""); notify_changed_uris(); break; } service_unlock(); }
void parse_args(t_all *all) { int i; i = 0; while (all->cmd.args[i]) { all->cmd.args[i] = replace_tilde(all, all->cmd.args[i]); all->cmd.args[i] = replace_var(all, all->cmd.args[i]); i++; } }
static void inform_play_transition_from_output(enum PlayFeedback fb) { service_lock(); switch (fb) { case PLAY_STOPPED: replace_transport_uri_and_meta("", ""); replace_current_uri_and_meta("", ""); change_transport_state(TRANSPORT_STOPPED); break; case PLAY_STARTED_NEXT_STREAM: { const char *av_uri = get_var(TRANSPORT_VAR_NEXT_AV_URI); const char *av_meta = get_var(TRANSPORT_VAR_NEXT_AV_URI_META); replace_transport_uri_and_meta(av_uri, av_meta); replace_current_uri_and_meta(av_uri, av_meta); replace_var(TRANSPORT_VAR_NEXT_AV_URI, ""); replace_var(TRANSPORT_VAR_NEXT_AV_URI_META, ""); break; } } service_unlock(); }
static int play(struct action_event *event) { if (obtain_instanceid(event, NULL) < 0) { return -1; } int rc = 0; service_lock(); switch (transport_state_) { // even if already playing, we must restart playback when Play // action is executed. Kinsky, for example, would not send Stop // when changing tracks and playback is already in progress - // it will just set new URI, and send Play command case TRANSPORT_PLAYING: case TRANSPORT_STOPPED: // If we were stopped before, we start a new song now. So just // set the time to zero now; otherwise we will see the old // value of the previous song until it updates some fractions // of a second later. replace_var(TRANSPORT_VAR_REL_TIME_POS, kZeroTime); /* >>> fall through */ case TRANSPORT_PAUSED_PLAYBACK: if (output_play(&inform_play_transition_from_output)) { upnp_set_error(event, 704, "Playing failed"); rc = -1; } else { change_transport_state(TRANSPORT_PLAYING); const char *av_uri = get_var(TRANSPORT_VAR_AV_URI); const char *av_meta = get_var(TRANSPORT_VAR_AV_URI_META); replace_current_uri_and_meta(av_uri, av_meta); } break; case TRANSPORT_NO_MEDIA_PRESENT: case TRANSPORT_TRANSITIONING: case TRANSPORT_PAUSED_RECORDING: case TRANSPORT_RECORDING: /* action not allowed in these states - error 701 */ upnp_set_error(event, UPNP_TRANSPORT_E_TRANSITION_NA, "Transition not allowed; allowed=%s", get_var(TRANSPORT_VAR_CUR_TRANSPORT_ACTIONS)); rc = -1; break; } service_unlock(); return rc; }
static int init_parsing(char **str, t_shenv *shenv, int *ret, char ***cmd) { *ret = 0; if (!(*str = replace_var(*str, shenv, 0, 0))) return (EXIT_SUCCESS); add_history_line(*str, shenv); if (!(*cmd = make_tab_cmd(*str))) return (EXIT_SUCCESS); if (strncmp(*cmd[0], ";", 1) && strncmp(*cmd[0], "&&", 2) && strncmp(*cmd[0], "||", 2)) *ret = parse_cmd(*cmd[0], shenv, 0); return (EXIT_FAILURE); }
// Change volume. Also for setting the initial volume that we read from the // output device. This prepares a LastChange variable that can be send as an // initial change. static void change_volume(const char *volume, const char *db_volume) { char *buf; replace_var(CONTROL_VAR_VOLUME, volume); replace_var(CONTROL_VAR_VOLUME_DB, db_volume); char *xml[2]; xml[0] = xmlescape(control_values[CONTROL_VAR_VOLUME], 1); xml[1] = xmlescape(control_values[CONTROL_VAR_VOLUME_DB], 1); asprintf(&buf, "<Event xmlns = \"urn:schemas-upnp-org:metadata-1-0/AVT/\">" "<InstanceID val=\"0\">\n" "\t<%s val=\"%s\"/>\n" "\t<%s val=\"%s\"/>\n" "</InstanceID></Event>", control_variables[CONTROL_VAR_VOLUME], xml[0], control_variables[CONTROL_VAR_VOLUME_DB], xml[1]); replace_var(CONTROL_VAR_LAST_CHANGE, buf); free(buf); int i; for (i = 0; i < 2; ++i) { free(xml[i]); } }
int main(int argc, char *argv[]) { char *r; assert_se(r = replace_var("@@@foobar@xyz@HALLO@foobar@test@@testtest@TEST@...@@@", lookup, NULL)); puts(r); assert_se(streq(r, "@@@foobar@xyz<<<HALLO>>>foobar@test@@testtest<<<TEST>>>...@@@")); free(r); assert_se(r = strreplace("XYZFFFFXYZFFFFXYZ", "XYZ", "ABC")); puts(r); assert_se(streq(r, "ABCFFFFABCFFFFABC")); free(r); return 0; }
//TODO:FIXME static int set_playmode(struct action_event *event) { if (obtain_instanceid(event, NULL) < 0) { return -1; } char *playmode = upnp_get_string(event, "NewPlayMode"); if (playmode == NULL) { return -1; } //TODO: support this playmode? error 712 // This is the only thing we support right now. service_lock(); replace_var(TRANSPORT_VAR_CUR_PLAY_MODE, playmode); service_unlock(); free(playmode); return 0; }
void timerPlay(char *uri) { service_lock(); output_stop(); change_transport_state(TRANSPORT_STOPPED); output_set_uri(uri, NULL); replace_var(TRANSPORT_VAR_REL_TIME_POS, kZeroTime); if (output_play(&inform_play_transition_from_output)) { } else { change_transport_state(TRANSPORT_PLAYING); const char *av_uri = get_var(TRANSPORT_VAR_AV_URI); const char *av_meta = get_var(TRANSPORT_VAR_AV_URI_META); replace_current_uri_and_meta(av_uri, av_meta); } service_unlock(); }
// TODO: this code is somewhat duplicate in upnp_transport. static void notify_lastchange(struct action_event *event, const char *value) { const char *varnames[] = { "LastChange", NULL }; const char *varvalues[] = { NULL, NULL }; replace_var(CONTROL_VAR_LAST_CHANGE, value); varvalues[0] = xmlescape(value, 0); upnp_device_notify(event->device_priv, control_service_.service_name, varnames, varvalues, 1); free((char*)varvalues[0]); }
static void change_var_and_notify(struct action_event *event, control_variable varnum, const char *value) { char *buf; replace_var(varnum, value); char *xml_value = xmlescape(control_values[varnum], 1); asprintf(&buf, "<Event xmlns = \"urn:schemas-upnp-org:metadata-1-0/AVT/\"><InstanceID val=\"0\">" "<%s val=\"%s\"/></InstanceID></Event>", control_variables[varnum], xml_value); free(xml_value); fprintf(stderr, "HZ: ----------------------------------------------- push notification : %s = '%s'\n", control_variables[varnum], value); notify_lastchange(event, buf); free(buf); return; }
static void notify_lastchange(const char *value) { const char *varnames[] = { "LastChange", NULL }; const char *varvalues[] = { NULL, NULL }; if (!replace_var(TRANSPORT_VAR_LAST_CHANGE, value)) return; // nothing to notify. varvalues[0] = xmlescape(value, 0); upnp_device_notify(upnp_device_, transport_service_.service_name, varnames, varvalues, 1); free((char*)varvalues[0]); }
int parsexec(char *cmd, t_shell *shell) { int ret; t_cmd *cmd_data; t_tree *cmd_tree; g_is_a_term = 0; if ((cmd = add_some_space(cmd)) == NULL || (cmd_data = get_cmd_data(cmd)) == NULL) return (-1); lexing(cmd_data); if ((ret = replace_var(cmd_data, shell)) != -1 && ret != -2 && parsing(cmd_data)) { if ((cmd_tree = get_tree(cmd_data)) == NULL || exec_tree(cmd_tree, shell) == -1) return (-1); clean_memory(cmd_tree, cmd_data, cmd); } return (ret); }
// Transport uri always comes in uri/meta pairs. Set these and also the related // track uri/meta variables. // Returns 1, if this meta-data likely needs to be updated while the stream // is playing (e.g. radio broadcast). static int replace_transport_uri_and_meta(const char *uri, const char *meta) { replace_var(TRANSPORT_VAR_AV_URI, uri); replace_var(TRANSPORT_VAR_AV_URI_META, meta); // This influences as well the tracks. If there is a non-empty URI, // we have exactly one track. const char *tracks = (uri != NULL && strlen(uri) > 0) ? "1" : "0"; replace_var(TRANSPORT_VAR_NR_TRACKS, tracks); replace_var(TRANSPORT_VAR_CUR_TRACK, tracks); // Also the current track URI mirrors the transport URI. replace_var(TRANSPORT_VAR_CUR_TRACK_URI, uri); replace_var(TRANSPORT_VAR_CUR_TRACK_META, meta); int requires_stream_meta_callback = (strlen(meta) == 0) || strstr(meta, "object.item.audioItem.audioBroadcast"); return requires_stream_meta_callback; }
static int get_position_info(struct action_event *event) { int rc; ENTER(); if (obtain_instanceid(event, NULL)) { rc = -1; goto out; } gint64 duration, position; service_lock(); const int pos_result = output_get_position(&duration, &position); service_unlock(); if (pos_result == 0) { char tbuf[32]; print_upnp_time_into_buffer(tbuf, sizeof(tbuf), duration); replace_var(TRANSPORT_VAR_CUR_TRACK_DUR, tbuf); print_upnp_time_into_buffer(tbuf, sizeof(tbuf), position); replace_var(TRANSPORT_VAR_REL_TIME_POS, tbuf); } rc = upnp_append_variable(event, TRANSPORT_VAR_CUR_TRACK, "Track"); if (rc) goto out; rc = upnp_append_variable(event, TRANSPORT_VAR_CUR_TRACK_DUR, "TrackDuration"); if (rc) goto out; rc = upnp_append_variable(event, TRANSPORT_VAR_CUR_TRACK_META, "TrackMetaData"); if (rc) goto out; rc = upnp_append_variable(event, TRANSPORT_VAR_CUR_TRACK_URI, "TrackURI"); if (rc) goto out; rc = upnp_append_variable(event, TRANSPORT_VAR_REL_TIME_POS, "RelTime"); if (rc) goto out; rc = upnp_append_variable(event, TRANSPORT_VAR_ABS_TIME_POS, "AbsTime"); if (rc) goto out; rc = upnp_append_variable(event, TRANSPORT_VAR_REL_CTR_POS, "RelCount"); if (rc) goto out; rc = upnp_append_variable(event, TRANSPORT_VAR_ABS_CTR_POS, "AbsCount"); if (rc) goto out; out: LEAVE(); return rc; }
// Similar to replace_transport_uri_and_meta() above, but current values. static void replace_current_uri_and_meta(const char *uri, const char *meta){ const char *tracks = (uri != NULL && strlen(uri) > 0) ? "1" : "0"; replace_var(TRANSPORT_VAR_CUR_TRACK, tracks); replace_var(TRANSPORT_VAR_CUR_TRACK_URI, uri); replace_var(TRANSPORT_VAR_CUR_TRACK_META, meta); }
static void set_mute_toggle(int do_mute) { replace_var(CONTROL_VAR_MUTE, do_mute ? "1" : "0"); output_set_mute(do_mute); }