Skip to content

Commit

Permalink
Add an update_progress implementation
Browse files Browse the repository at this point in the history
This allows for Python code providing a callback function that
is used to indicate progress.

Also fix a few minor things in message callback (reference
counting of Python objects).
  • Loading branch information
dl8dtl committed Mar 18, 2024
1 parent 296883c commit 858c3f6
Show file tree
Hide file tree
Showing 2 changed files with 46 additions and 5 deletions.
41 changes: 36 additions & 5 deletions src/libavrdude.i
Original file line number Diff line number Diff line change
Expand Up @@ -35,12 +35,35 @@ const char *partdesc = "";
const char *pgmid = "";

static PyObject *msg_cb = NULL;
static PyObject *progress_cb = NULL;
static void swig_progress(int percent, double etime, const char *hdr, int finish);

void set_msg_callback(PyObject *PyFunc) {
if (PyFunc == Py_None)
if (PyFunc == Py_None) {
if (msg_cb)
Py_XDECREF(msg_cb); // Remove reference to previous callback
msg_cb = NULL;
else
} else {
if (msg_cb)
Py_XDECREF(msg_cb); // Remove reference to previous callback
Py_XINCREF(PyFunc); // Add reference to new callback
msg_cb = PyFunc;
}
}

void set_progress_callback(PyObject *PyFunc) {
if (PyFunc == Py_None) {
if (progress_cb)
Py_XDECREF(progress_cb); // Remove reference to previous callback
update_progress = NULL;
progress_cb = NULL;
} else {
if (progress_cb)
Py_XDECREF(progress_cb); // Remove reference to previous callback
progress_cb = PyFunc;
Py_XINCREF(PyFunc); // Add reference to new callback
update_progress = swig_progress;
}
}

// We cannot pass va_args to Python, so pre-process the message here
Expand Down Expand Up @@ -92,15 +115,22 @@ int avrdude_message2(FILE *fp, int lno, const char *file,
PyObject *result =
PyObject_CallFunction(msg_cb, "(sissiis)", target, lno, file, func, msgmode, msglvl, p);
Py_XDECREF(result);
} else {
fprintf(stderr, "Would call msg callback here\n");
}
free(p);
}

return rc;
}

static void swig_progress(int percent, double etime, const char *hdr, int finish)
{
if (progress_cb) {
PyObject *result =
PyObject_CallFunction(progress_cb, "(idsi)", percent, etime, hdr, finish);
Py_XDECREF(result);
}
}

PROGRAMMER *ldata_programmer(LNODEID p) {
return (PROGRAMMER *)ldata(p);
}
Expand Down Expand Up @@ -161,7 +191,7 @@ enum msgmode {
MSG2_FLUSH = 64, // Flush before and after printing
};

// Function to record a callback
// Functions to record a callback
%typemap(in) PyObject *PyFunc {
// calling with None removes previous callback
if ($input != Py_None && !PyCallable_Check($input)) {
Expand All @@ -171,6 +201,7 @@ enum msgmode {
$1 = $input;
}
void set_msg_callback(PyObject *PyFunc);
void set_progress_callback(PyObject *PyFunc);

// These things are read from config file(s), and must be considered
// read-only by any program. Most internals are only relevant for
Expand Down
10 changes: 10 additions & 0 deletions src/swigtest.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
# getavr("m128")

# ad.set_msg_callback(msg_callback)
# ad.set_progress_callback(progress_callback)
# ad.cvar.verbose=2
# p = ad.locate_part(ad.cvar.part_list, 'm168pb')
# ad.avr_initmem(p)
Expand Down Expand Up @@ -178,3 +179,12 @@ def msg_callback(target: str, lno: int, fname: str, func: str,
s += msg
print(s, end='')

# very simplified progress callback
global prog_hdr
def progress_callback(percent: int, etime: float, hdr: str, finish: int):
if hdr:
global prog_hdr
prog_hdr = hdr
print(f"{prog_hdr} {percent:3d} %", end='\r', file=sys.stderr, flush=True)
if (percent == 100):
print("", file=sys.stderr)

0 comments on commit 858c3f6

Please sign in to comment.