Ok, I got DTMF working. Here's the schematic:
The LM386 turned out to be a good choice. Its inputs are already referenced to ground, so I was able to simply connect the transformer secondary leads to the LM386 inputs. And its output is automatically Vcc/2, so perfect to feed to A0 directly. No capacitors or biasing transitors needed. And as it turned out, the default 20db amplification is a bit too much, so I added a 680R resistor across the secondary so it wouldn't clip, at least on dial tone.
Since this device will only call out, the ring detector circuit is just to try to prevent it from inadvertently answering the phone when it wants to dial out. However, it does another useful function. If I pick up any extension phone on the network, the line voltage will drop from 48V to about 7V. That's enough to generate a small spike in the optocoupler, which in turn is enough to trigger an interrupt on the Arduino. I can then have it listen for a special key sequence I might press, that would not be part of a dialed number, like "star, pound, star, pound", to have it perform a function without having to go to the device itself and press a button. This circuit is on the NC terminal of the relay, so it's connected to the line most of the time.
Everything else is on the NO terminal, so it's only connected to the line when the device needs to make a call, and at the same time all the ring detector stuff is disconnected from the line. Basically its just the audio path through the transformer to the LM386, and finally to the Arudino. But tapping off of that is the circuit that sinks enough DC current to take the line off-hook. That needs a FWBR because the polarity of tip and ring is not always certain.
I was able to test DTMF by calling in from my cell phone and pressing the keys on that phone. Everything worked perfectly:
DTMF Decoder V0_08P
9 (2,2) failed/rejected matches=2
1 (0,0) failed/rejected matches=1
1 (0,0) failed/rejected matches=1
1 (0,0) failed/rejected matches=3
1 (0,0) failed/rejected matches=2
8 (1,2) failed/rejected matches=2
9 (2,2) failed/rejected matches=2
# (2,3) failed/rejected matches=1
# (2,3) failed/rejected matches=3
# (2,3) failed/rejected matches=1
# (2,3) failed/rejected matches=1
* (0,3) failed/rejected matches=2
* (0,3) failed/rejected matches=2
* (0,3) failed/rejected matches=1
I dialed "918#*" from the cell phone, and it got all of them. I need to see what the failed/rejected is all about since it didn't fail. Also, it needs debouncing - one result per keypress.
Next I need to get dialtone and the other call progress tones working. Dialtone is almost 4V peak-to-peak at A0, so there should be no problem if I have the right frequencies. But Wikipedia has an audio file of the US standard 350/440 dialtone, and it doesn't quite sound like my Ooma dialtone. So I may have to alter the code to sequence through all the frequencies in that range to see which ones work.
Thanks very much for everyone's help, particularly @6v6gt for the code and the circuit suggestions.
I'll probably post this as a project when I get it finished.
Edit: Oops. I need a diode across the relay coil.