X-Git-Url: http://sigrok.org/gitweb/?a=blobdiff_plain;f=decode.c;h=06400f36e87516caa56a97d2cd14e5e9bf88d9fb;hb=54614916a903;hp=d27703929fe7d34a7e972627b87a5e0fd7d723e9;hpb=69110b5cbe99a54937f108d239592e5afb55d008;p=sigrok-cli.git diff --git a/decode.c b/decode.c index d277039..06400f3 100644 --- a/decode.c +++ b/decode.c @@ -480,6 +480,116 @@ int setup_pd_binary(char *opt_pd_binary) return 0; } +/* + * Balance JSON object and array parentheses, and separate array items. + * Somewhat convoluted API to re-use the routine for individual items as + * well as the surrounding array and object, including deferred start of + * the output and late flush (and to keep the state strictly local to the + * routine). Some additional complexity due to JSON's inability to handle + * a trailing comma at the last item. Code phrased such that text literals + * are kept in their order of appearance in the output text. + */ +static void jsontrace_open_close(gboolean is_close_req) +{ + static gboolean is_opened; + + if (!is_close_req) { + if (!is_opened) { + printf("{\"traceEvents\": [\n"); + is_opened = TRUE; + } else { + printf(",\n"); + } + } else { + if (is_opened) { + printf("\n"); + printf("]}\n"); + fflush(stdout); + } + is_opened = FALSE; + } +} + +/* Convert uint64 sample number to double timestamp in microseconds. */ +static double jsontrace_ts_usec(uint64_t snum) +{ + double ts_usec; + + ts_usec = snum; + ts_usec *= 1e6; + ts_usec /= pd_samplerate; + return ts_usec; +} + +/* Emit two Google Trace Events (JSON) for one PD annotation (ss, es). */ +static void jsontrace_annotation(struct srd_decoder *dec, + struct srd_proto_data_annotation *pda, struct srd_proto_data *pdata) +{ + char *row_text; + GSList *lrow, *lcls; + struct srd_decoder_annotation_row *row; + int cls; + char **ann_descr; + + /* + * Search for an annotation row for this index, or use the + * annotation's descriptor. + */ + row_text = NULL; + if (dec->annotation_rows) { + for (lrow = dec->annotation_rows; lrow; lrow = lrow->next) { + row = lrow->data; + for (lcls = row->ann_classes; lcls; lcls = lcls->next) { + cls = GPOINTER_TO_INT(lcls->data); + if (cls == pda->ann_class) { + row_text = row->desc; + break; + } + } + if (row_text) + break; + } + } + if (!row_text) { + ann_descr = g_slist_nth_data(dec->annotations, pda->ann_class); + row_text = ann_descr[0]; + } + + /* + * Emit two Google Trace Events for the start and end times. + * Set the 'pid' (process ID) to the decoder name to group a + * decoder's annotations. Set the 'tid' (thread ID) to the + * annotation row's description. The 'ts' (timestamp) is in + * microseconds. Set 'name' to the longest annotation text. + * + * BEWARE of the unfortunate JSON format comma limitation. And + * some of the output formatting is motivated by the desire to + * further reduce text size, by eliminating some of the spaces. + * + * This implementation is strictly compatible to the initial + * implementation. Which might change in the future to increase + * readability of the output to humans, by generating a layout + * which is closer to other output modes. + */ + jsontrace_open_close(FALSE); + printf("{"); + printf("\"%s\": \"%s\"", "name", pda->ann_text[0]); + printf(", \"%s\": \"%s\"", "ph", "B"); + printf(", \"%s\": \"%s\"", "pid", pdata->pdo->proto_id); + printf(", \"%s\": \"%s\"", "tid", row_text); + printf(", \"%s\": %lf", "ts", jsontrace_ts_usec(pdata->start_sample)); + printf("}"); + + jsontrace_open_close(FALSE); + printf("{"); + printf("\"%s\": \"%s\"", "name", pda->ann_text[0]); + printf(", \"%s\": \"%s\"", "ph", "E"); + printf(", \"%s\": \"%s\"", "pid", pdata->pdo->proto_id); + printf(", \"%s\": \"%s\"", "tid", row_text); + printf(", \"%s\": %lf", "ts", jsontrace_ts_usec(pdata->end_sample)); + printf("}"); +} + void show_pd_annotations(struct srd_proto_data *pdata, void *cb_data) { struct srd_decoder *dec; @@ -514,6 +624,12 @@ void show_pd_annotations(struct srd_proto_data *pdata, void *cb_data) if (!show_ann) return; + /* Google Trace Events are rather special. Use a separate code path. */ + if (opt_pd_jsontrace) { + jsontrace_annotation(dec, pda, pdata); + return; + } + /* * Determine which fields of the annotation to display. Inspect * user specified options as well as the verbosity of the log level: @@ -601,4 +717,16 @@ void show_pd_binary(struct srd_proto_data *pdata, void *cb_data) fwrite(pdb->data, pdb->size, 1, stdout); fflush(stdout); } + +void show_pd_prepare(void) +{ + if (opt_pd_jsontrace) + jsontrace_open_close(TRUE); +} + +void show_pd_close(void) +{ + if (opt_pd_jsontrace) + jsontrace_open_close(TRUE); +} #endif