You have the right general idea. I would use the following approach:
1. Get a list of all libraries (using either DSPOBJD as I assume you are currently doing or the List Objects API QUSLOBJ — note that both support a special value *ALLUSR to subset the list of returned libraries).
2. Get a list of all files in each library identified in step 1 (again with DSPOBJD or QUSLOBJ).
3. Use the Retrieve File Description API QDBRTVFD and format FILD0100 to determine if the file is a source file. This API can appear overwhelming but fortunately all you want is the bit field Qdbfhfsu located in the ninth byte of the returned data — so you can ignore everything else. If this bit is on then the file is a source physical file. Note that a blank source file, source file library, and member name does NOT mean you have a source physical file. It just means no source was used to define the file — a CRTPF FILE(A) RCDLEN(100) would also have no source identified.
4. If a source physical file, use the List Database File Members API QUSLMBR and format MBRL0320. This will give you a list of all members in the file along with the current number of records in each member. Alternatively you could use QUSLMBR and format MBRL0100 to get just the list of member names and then the RTVMBRD command for each member and get the NBRCURRCD value.
5. Accumulate the values found in step 4 and you’re done.
If you are not familiar with APIs you might be interested in the book APIs at Work Second Edition. In there you will find RPG examples of all the APIs I referenced above and, in the case of QDBRTVFD how to test individual bit values. Note that I am the author of this book so I am a bit biased here…
I hope this helps,