Author Topic: Code Where Orbiter Sends DCE Event?  (Read 10982 times)

Matthew

  • Douchebag
  • Addicted
  • *
  • Posts: 567
    • View Profile
Code Where Orbiter Sends DCE Event?
« on: January 25, 2008, 03:21:11 pm »
I'm working on debugging Mantis bug#3495, "0003495: DVD Changer rips CD's only with OGG". I've found in part of the codepath that the CD/DVD changer device (VGP-XL1B) works properly after getting a faulty command from DCE to rip with an empty target format string (which then defaults in the Powerfile_C200 code to OGG). But I'm having trouble finding where the format is not specified when initiating that command upstream. I don't know whether the format is specified (or should be) in the Orbiter code, or whether the DCERouter makes (or should make) another loop on receiving the Orbiter event by sending a command to some configuration device to further populate the command sent to the changer, or whether some other point in the critical path is failing to retrieve the format from the database (which seems to have the format successfully stored by the Adminsite).

Can you help me find where the Orbiter sends the event that gets logged in /var/log/pluto/DCERouter.log that seems to be missing params 20 (Format) and 157 (Disks: slot number list or "*")?
Code: [Select]
08      01/21/08 18:14:06.135           Received Message from 20 (OnScreen Orbiter / Bedroom (Master)) to 33 (VAIO DVD Changer / Bedroom (Master)), type 1 id 720 Command:Bulk Rip, retry none, parameters: <0x77804b90>
08      01/21/08 18:14:06.135             Parameter 13(Filename): /home/public/data/___audio___or___video___/ <0x77804b90>
08      01/21/08 18:14:06.135             Parameter 17(PK_Users): 1 <0x77804b90>
05      01/21/08 18:14:06.135           The target device 33 (routed to 33) has not registered. <0xb6c46b90>

hari

  • Administrator
  • LinuxMCE God
  • *****
  • Posts: 2428
    • View Profile
    • ago control
Re: Code Where Orbiter Sends DCE Event?
« Reply #1 on: January 25, 2008, 05:21:40 pm »
Can you help me find where the Orbiter sends the event that gets logged in /var/log/pluto/DCERouter.log that seems to be missing params 20 (Format) and 157 (Disks: slot number list or "*")?

look for the generated command definition (from sql2cpp) and grep for that in the source code.

best regards,
Hari
rock your home - http://www.agocontrol.com home automation

Matthew

  • Douchebag
  • Addicted
  • *
  • Posts: 567
    • View Profile
Re: Code Where Orbiter Sends DCE Event?
« Reply #2 on: January 25, 2008, 09:15:17 pm »
Can you help me find where the Orbiter sends the event that gets logged in /var/log/pluto/DCERouter.log that seems to be missing params 20 (Format) and 157 (Disks: slot number list or "*")?

look for the generated command definition (from sql2cpp) and grep for that in the source code.

Is that the C++ code in src/Gen_Devices ?

hari

  • Administrator
  • LinuxMCE God
  • *****
  • Posts: 2428
    • View Profile
    • ago control
Re: Code Where Orbiter Sends DCE Event?
« Reply #3 on: January 25, 2008, 09:18:08 pm »
Can you help me find where the Orbiter sends the event that gets logged in /var/log/pluto/DCERouter.log that seems to be missing params 20 (Format) and 157 (Disks: slot number list or "*")?

look for the generated command definition (from sql2cpp) and grep for that in the source code.

Is that the C++ code in src/Gen_Devices ?
yes. Sorry, sql2cpp was plain wrong. Of course i meant dcegen.

best regards,
Hari
rock your home - http://www.agocontrol.com home automation

Matthew

  • Douchebag
  • Addicted
  • *
  • Posts: 567
    • View Profile
Re: Code Where Orbiter Sends DCE Event?
« Reply #4 on: January 25, 2008, 10:22:46 pm »
Can you help me find where the Orbiter sends the event that gets logged in /var/log/pluto/DCERouter.log that seems to be missing params 20 (Format) and 157 (Disks: slot number list or "*")?

look for the generated command definition (from sql2cpp) and grep for that in the source code.

Is that the C++ code in src/Gen_Devices ?
yes. Sorry, sql2cpp was plain wrong. Of course i meant dcegen.

This is like a wild goose chase. I don't see where in Orbiter{Base,_PluginBase}.{cpp,h} the Orbiter sends the event to the DCERouter, let alone where it composes that event (missing its format param). It's like a maze of pliled up abstraction layers in there.

hari

  • Administrator
  • LinuxMCE God
  • *****
  • Posts: 2428
    • View Profile
    • ago control
Re: Code Where Orbiter Sends DCE Event?
« Reply #5 on: January 25, 2008, 10:37:57 pm »
Can you help me find where the Orbiter sends the event that gets logged in /var/log/pluto/DCERouter.log that seems to be missing params 20 (Format) and 157 (Disks: slot number list or "*")?

look for the generated command definition (from sql2cpp) and grep for that in the source code.

Is that the C++ code in src/Gen_Devices ?
yes. Sorry, sql2cpp was plain wrong. Of course i meant dcegen.

This is like a wild goose chase. I don't see where in Orbiter{Base,_PluginBase}.{cpp,h} the Orbiter sends the event to the DCERouter, let alone where it composes that event (missing its format param). It's like a maze of pliled up abstraction layers in there.

Matthew, please don't get me wrong, a simple find/grep would have given you all the information you want. Sometimes i wonder if you are too lazy to look that up yourself.

Search for the command:
Code: [Select]
dcerouter_48407:/usr/src/svn/trunk/trunk/src# grep Bulk Gen_Devices/* | grep COMMAND
Gen_Devices/AllCommandsRequests.h:                      COMMAND_Bulk_Rip_CONST,
[...]

Look where it gets used in the code:
Code: [Select]
dcerouter_48407:/usr/src/svn/trunk/trunk/src# find . -name '*.cpp' -exec grep -H COMMAND_Bulk_Rip_CONST \{} \;
./Orbiter/ScreenHandler.cpp:                    TOSTRING(COMMAND_Bulk_Rip_CONST) " "

Look at the ScreenHandler code:
Code: [Select]
        else if( pObjectInfoData->m_pObj->m_iBaseObjectID==DESIGNOBJ_butRipAll_CONST )
        {
                string sRipMessage =
                        StringUtils::itos(m_pOrbiter->m_dwPK_Device) + " " +
                        StringUtils::itos(PK_Device_JukeBox) + " 1 "
                        TOSTRING(COMMAND_Bulk_Rip_CONST) " "
                        TOSTRING(COMMANDPARAMETER_PK_Users_CONST) " <%=U%> "
                        TOSTRING(COMMANDPARAMETER_Filename_CONST) " \"<%=9%>\" ";
                string sTitle = m_pOrbiter->m_mapTextString[TEXT_Choose_Filename_CONST];

                DCE::SCREEN_FileSave SCREEN_FileSave(m_pOrbiter->m_dwPK_Device,m_pOrbiter->m_dwPK_Device,0,-999,sTitle,sRipMessage,true);
                m_pOrbiter->SendCommand(SCREEN_FileSave);
        }

hope that helps,

best regards,
Hari
« Last Edit: January 25, 2008, 10:40:55 pm by hari »
rock your home - http://www.agocontrol.com home automation

Matthew

  • Douchebag
  • Addicted
  • *
  • Posts: 567
    • View Profile
Re: Code Where Orbiter Sends DCE Event?
« Reply #6 on: January 25, 2008, 11:03:10 pm »
Can you help me find where the Orbiter sends the event that gets logged in /var/log/pluto/DCERouter.log that seems to be missing params 20 (Format) and 157 (Disks: slot number list or "*")?

look for the generated command definition (from sql2cpp) and grep for that in the source code.

Is that the C++ code in src/Gen_Devices ?
yes. Sorry, sql2cpp was plain wrong. Of course i meant dcegen.

This is like a wild goose chase. I don't see where in Orbiter{Base,_PluginBase}.{cpp,h} the Orbiter sends the event to the DCERouter, let alone where it composes that event (missing its format param). It's like a maze of pliled up abstraction layers in there.

Matthew, please don't get me wrong, a simple find/grep would have given you all the information you want. Sometimes i wonder if you are too lazy to look that up yourself.

I don't think I get you wrong. I spent the time between our posts in this thread grepping (-i) for strings like "cmd", "format", "720", "bulk" in the Orbiter* code, and -r on the whole source tree again. The ScreenHandler code isn't in the Gen_Devices/ code you pointed me to. I didn't have a string like "COMMAND" to go on, as "CMD" is what's used in all the target code. It's a little exasperating when others seem to know enough about where to find these undocumented code artifacts, but don't mention the specific detail that lets us skip the "rite of passage" and just go right to where the faulty codepath lies buried.


Search for the command:
Code: [Select]
dcerouter_48407:/usr/src/svn/trunk/trunk/src# grep Bulk Gen_Devices/* | grep COMMAND
Gen_Devices/AllCommandsRequests.h:                      COMMAND_Bulk_Rip_CONST,
[...]

Look where it gets used in the code:
Code: [Select]
dcerouter_48407:/usr/src/svn/trunk/trunk/src# find . -name '*.cpp' -exec grep -H COMMAND_Bulk_Rip_CONST \{} \;
./Orbiter/ScreenHandler.cpp:                    TOSTRING(COMMAND_Bulk_Rip_CONST) " "

Look at the ScreenHandler code:
Code: [Select]
        else if( pObjectInfoData->m_pObj->m_iBaseObjectID==DESIGNOBJ_butRipAll_CONST )
        {
                string sRipMessage =
                        StringUtils::itos(m_pOrbiter->m_dwPK_Device) + " " +
                        StringUtils::itos(PK_Device_JukeBox) + " 1 "
                        TOSTRING(COMMAND_Bulk_Rip_CONST) " "
                        TOSTRING(COMMANDPARAMETER_PK_Users_CONST) " <%=U%> "
                        TOSTRING(COMMANDPARAMETER_Filename_CONST) " \"<%=9%>\" ";
                string sTitle = m_pOrbiter->m_mapTextString[TEXT_Choose_Filename_CONST];

                DCE::SCREEN_FileSave SCREEN_FileSave(m_pOrbiter->m_dwPK_Device,m_pOrbiter->m_dwPK_Device,0,-999,sTitle,sRipMessage,true);
                m_pOrbiter->SendCommand(SCREEN_FileSave);
        }

hope that helps,

Indeed, that helps quite a lot. That doesn't only show a rip message being created without a format parameter,. It also illustrates how to trace this code with simple commandline lexical tools, which I've been dying to do for weeks. And it just generally demonstrates the actual procedure for DCE messaging among objects in the actual code. Thanks for opening this process up. Now I'm closer to actually debugging the damn thing.

hari

  • Administrator
  • LinuxMCE God
  • *****
  • Posts: 2428
    • View Profile
    • ago control
Re: Code Where Orbiter Sends DCE Event?
« Reply #7 on: January 25, 2008, 11:26:30 pm »
I don't think I get you wrong. I spent the time between our posts in this thread grepping (-i) for strings like "cmd", "format", "720", "bulk" in the Orbiter* code, and -r on the whole source tree again. The ScreenHandler code isn't in the Gen_Devices/ code you pointed me to. I didn't have a string like "COMMAND" to go on, as "CMD" is what's used in all the target code. It's a little exasperating when others seem to know enough about where to find these undocumented code artifacts, but don't mention the specific detail that lets us skip the "rite of passage" and just go right to where the faulty codepath lies buried.

It's not that somebody gave me some big map either. Maybe you want to create a simple device with DCEGen and sql2cpp. That gives big insights.

Quote
Indeed, that helps quite a lot. That doesn't only show a rip message being created without a format parameter,. It also illustrates how to trace this code with simple commandline lexical tools, which I've been dying to do for weeks.
hey, i gave you some hints in other threads ;)
Quote
And it just generally demonstrates the actual procedure for DCE messaging among objects in the actual code. Thanks for opening this process up. Now I'm closer to actually debugging the damn thing.
no prob, feel free to ask,

best regards,
Hari

ps: i'm still waiting on that wiki page for compiling ;)
rock your home - http://www.agocontrol.com home automation

Matthew

  • Douchebag
  • Addicted
  • *
  • Posts: 567
    • View Profile
Re: Code Where Orbiter Sends DCE Event?
« Reply #8 on: January 26, 2008, 12:31:05 am »
I don't think I get you wrong. I spent the time between our posts in this thread grepping (-i) for strings like "cmd", "format", "720", "bulk" in the Orbiter* code, and -r on the whole source tree again. The ScreenHandler code isn't in the Gen_Devices/ code you pointed me to. I didn't have a string like "COMMAND" to go on, as "CMD" is what's used in all the target code. It's a little exasperating when others seem to know enough about where to find these undocumented code artifacts, but don't mention the specific detail that lets us skip the "rite of passage" and just go right to where the faulty codepath lies buried.

It's not that somebody gave me some big map either. Maybe you want to create a simple device with DCEGen and sql2cpp. That gives big insights.

Probably I will. I've been thinking about creating a "presence" device, a Bluetooth device that floats around the Floorplan, which can be used for logic to know where someone/something is. That could send a presence server commands that could update other devices' state in the floorplan. Like if it were a Bluetooth phone that showed where I am, and turned MDs and lights on/off only in rooms where they reach me. Or even if I leave my home, and I get a call asking if I want to activate the alarm, and/or return home and get a call asking if I want to turn the alarm off, etc. I'm also working on adding Bluetooth speakers to the audio streaming system. Either of those could start with a simple device, and then add Bluetooth and then interactive/control features.

FWIW, is there an existing skeleton device that does nothing, but can be populated and run through DCEGen and sql2cpp? And a wiki? Or at least someone who knows how who I can brainpick to make those things for the community?

Quote
Indeed, that helps quite a lot. That doesn't only show a rip message being created without a format parameter,. It also illustrates how to trace this code with simple commandline lexical tools, which I've been dying to do for weeks.
hey, i gave you some hints in other threads ;)

I know that once you've got the info you learned by direct hand-to-hand combat, answering questions with just reassurances that it exists and can be found is easy. But part of my point in asking in these forums is to get it documented somewhere searchable. By me, if I wiki it, or by somone else later searching (who I'd hope would wiki it). The main reason to ask instead of digging is to reuse the knowledge that the long toil has already produced. Because then the answer lets us spend that time pushing LMCE forward, instead of reinventing (or rediscovering) the wheel.

Quote
And it just generally demonstrates the actual procedure for DCE messaging among objects in the actual code. Thanks for opening this process up. Now I'm closer to actually debugging the damn thing.
no prob, feel free to ask,

OK, here's probably the last link in this ripping bug. Do you know where in the pluto DB is stored the format for ripping, as set in the Adminsite Installation Settings? I'm digging through the PHP right now, but it would be easier to decipher if I could see by the light at the end  of the tunnel.


ps: i'm still waiting on that wiki page for compiling ;)

By the time I got it compiled, I was so overdue with helping "add Events to Floorplan" and fixing the CD ripping format (still am) that I've spent every available 15 minutes trying to trace this code. I thought tracing the rip format bug would be faster, and introduce me to the code more comprehensively than would starting with events, and I was probably right. But I've had no time to update. And I'm still not sure I am compiling from the instructions I got correctly, because I haven't edited any code to recompile and run and test - because I didn't really understand the code well enough to mess with it. Once I've tested a fix to the rip format OK, I'll have tested all the procedures enough that I can post info on inter-device event code, on the ripping, on programmatic DB access from PHP and from C++, on debugging, on tracing, on compiling, on SVN, on downloading betas, on installing DVDs from images, the works.

But since I'm using my time as efficiently as possible, I won't have tested any of those things well enough to publish them on a wiki until I've actually compiled some ripping fixes. I'm still feeling burned from botching the 7970 instructions, which I want to revise after I get to that, once I've got a 0710 to try my 7970 phone with again.

Which could be any day. Maybe tonight's the night ;).

hari

  • Administrator
  • LinuxMCE God
  • *****
  • Posts: 2428
    • View Profile
    • ago control
Re: Code Where Orbiter Sends DCE Event?
« Reply #9 on: January 26, 2008, 12:45:22 am »
FWIW, is there an existing skeleton device that does nothing, but can be populated and run through DCEGen and sql2cpp? And a wiki? Or at least someone who knows how who I can brainpick to make those things for the community?
yes:
Quote from: hari link=http://forum.linuxmce.org/index.php?topic=3675.msg20083#msg20083
It's pretty straight forward:
1.) Add the device and the command it implements in the Webadmin (see e.g. CM11A for examples).
2.) go to trunk/src/sql2cpp from a compiled svn checkout and simply run "./sql2cpp"
(that will update the c++ database constants/objects to include your new devicetemplate id)
3.) go to trunk/src/DCEGen and run "./DCEGen -d <your devicetemplate id>"
4.) go to the newly created directory trunk/src/<your device template name> and do a "make bin"
5.) add a new device from your template
6.) start your device with "./<your device template name> -d <your device id>"
7.) watch the successful connection to the router and verify the "Registered: yes" for your device in the web interface
I was busy with other wiki pages so this one is not set up yet ;)

Quote
The main reason to ask instead of digging is to reuse the knowledge that the long toil has already produced. Because then the answer lets us spend that time pushing LMCE forward, instead of reinventing (or rediscovering) the wheel.
Maybe that was my frustration because I spent countless weeks starring at the code and database without help.. You are of course completely right on that.

Quote
OK, here's probably the last link in this ripping bug. Do you know where in the pluto DB is stored the format for ripping, as set in the Adminsite Installation Settings? I'm digging through the PHP right now, but it would be easier to decipher if I could see by the light at the end  of the tunnel.
iirc it should be in the device data for the media plugin. (Database pluto_main, Table DeviceData, connected to DeviceTemplate with DeviceTemplate_DeviceData).
Quote
[...]
Which could be any day. Maybe tonight's the night ;).
hey, your task list is nearly as long as mine *lol*

happy hackin9
« Last Edit: January 26, 2008, 12:49:00 am by hari »
rock your home - http://www.agocontrol.com home automation

hari

  • Administrator
  • LinuxMCE God
  • *****
  • Posts: 2428
    • View Profile
    • ago control
Re: Code Where Orbiter Sends DCE Event?
« Reply #10 on: January 26, 2008, 12:57:53 am »
some db hints:

Show the Media Plugin Device Template:
Code: [Select]
mysql> select * from DeviceTemplate where PK_DeviceTemplate = 2;

Show the device data for the Template:
Code: [Select]
mysql> select * from DeviceTemplate_DeviceData where FK_DeviceTemplate = 2;

Show the actual Media Plugin Device ID:
Code: [Select]
mysql> select PK_Device from Device where FK_DeviceTemplate = 2;
+-----------+
| PK_Device |
+-----------+
|        10 |
+-----------+
1 row in set (0.00 sec)

Show the DeviceData for the Device itself:
Code: [Select]
mysql> select * from Device_DeviceData where FK_Device = 10;
+-----------+---------------+---------------+--------+-----------+----------+------------+---------------------+--------------+
| FK_Device | FK_DeviceData | IK_DeviceData | psc_id | psc_batch | psc_user | psc_frozen | psc_mod             | psc_restrict |
+-----------+---------------+---------------+--------+-----------+----------+------------+---------------------+--------------+
|        10 |            47 | flac          |   NULL |      NULL |     NULL |          0 | 2007-12-07 20:44:56 |         NULL |
+-----------+---------------+---------------+--------+-----------+----------+------------+---------------------+--------------+
1 row in set (0.00 sec)

best regards,
Hari
« Last Edit: January 26, 2008, 01:00:31 am by hari »
rock your home - http://www.agocontrol.com home automation

Matthew

  • Douchebag
  • Addicted
  • *
  • Posts: 567
    • View Profile
Re: Code Where Orbiter Sends DCE Event?
« Reply #11 on: January 26, 2008, 01:14:41 am »
some db hints:

Show the Media Plugin Device Template:
Code: [Select]
mysql> select * from DeviceTemplate where PK_DeviceTemplate = 2;

Thanks. How do you know that the Media Plugin Device Template PK_DeviceTemplate == 2 ? Where are those consts defined?

hari

  • Administrator
  • LinuxMCE God
  • *****
  • Posts: 2428
    • View Profile
    • ago control
Re: Code Where Orbiter Sends DCE Event?
« Reply #12 on: January 26, 2008, 01:24:11 am »
some db hints:

Show the Media Plugin Device Template:
Code: [Select]
mysql> select * from DeviceTemplate where PK_DeviceTemplate = 2;

Thanks. How do you know that the Media Plugin Device Template PK_DeviceTemplate == 2 ? Where are those consts defined?
it's the primary key of the DeviceTemplate Table. That holds all device templates for pluto. You can browse your device tree in the pluto-admin. When you select a device you see the template it's derived from. Or browse the templates with Advanced -> Configuration -> Device Templates.

Example:
Code: [Select]
My Devices
CORE
DCERouter
File Grids Plug-in
General Info Plug-in
Climate Plug-in
Datagrid Plug-in
Infrared Plug-in
Lighting Plug-in
Orbiter Plug-in
Media Plug-in   <- click on that
       [...]

That shows the device:
Code: [Select]
Advanced | Device #10: Media Plug-in
Description * Media Plug-in
Device Template  Media Plug-in #2
[...]

best regards,
Hari
rock your home - http://www.agocontrol.com home automation

hari

  • Administrator
  • LinuxMCE God
  • *****
  • Posts: 2428
    • View Profile
    • ago control
Re: Code Where Orbiter Sends DCE Event?
« Reply #13 on: January 26, 2008, 01:28:26 am »
and you probably want to look into
Code: [Select]
trunk/src/pluto_main/Table_Device_DeviceData.*

that gives you a Table object for the device data.

best regards,
Hari
rock your home - http://www.agocontrol.com home automation

Matthew

  • Douchebag
  • Addicted
  • *
  • Posts: 567
    • View Profile
Re: Code Where Orbiter Sends DCE Event?
« Reply #14 on: January 26, 2008, 01:48:05 am »
OK, here's probably the last link in this ripping bug. Do you know where in the pluto DB is stored the format for ripping, as set in the Adminsite Installation Settings? I'm digging through the PHP right now, but it would be easier to decipher if I could see by the light at the end  of the tunnel.
iirc it should be in the device data for the media plugin. (Database pluto_main, Table DeviceData, connected to DeviceTemplate with DeviceTemplate_DeviceData).

From the Adminsite Installation Settings page, I viewed the source of the settings form that has the current ripping setting ('flac'):
Code: [Select]
<td align="left" colspan="2"><B>Ripping format for cd's: </B><select name="rip" onChange="setOptions();"><option value="0">- Please select -</option><option value="mp3"   title="mp3">mp3</option>
<option value="ogg"   title="ogg">ogg</option>
[b]<option value="flac" selected  title="flac">flac</option>[/b]
<option value="wav"   title="wav">wav</option>
</select></td>

When I View Frame Info, that frame's Address is http://192.168.0.101/pluto-admin/index.php?section=installationSettings . In /var/www/pluto-admin/index.php , I searched for "installationSettings" and found
Code: [Select]
        case 'installationSettings':
                $output = new Template($dbADO);
                $output->setTemplateFileType('large');

            include_once('operations/users_settings/installationSettings.php');
            installationSettings($output,$dbADO);
        break;

In /var/www/pluto-admin/operations/users_settings/installationSettings.php I searched for "rip", the name of the HTML form field until I found it mentioned in the code that updates the DB with the rip value:
Code: [Select]
        $rip=$_POST['rip'];
        switch ($rip){
            case 'mp3':
                $bit_rate=($_POST['bit_rate_user']!=0 && $_POST['bit_rate_user']>=96 && $_POST['bit_rate_user']<=320)?$_POST['bit_rate_user']:$_POST['bit_rate_predefined'];
                $cbr_vbr=$_POST['cbr_vbr'];
                $rip="$rip;$bit_rate;$cbr_vbr";
            break;
            case 'ogg':
                $ql=$_POST['ogg_ql'];
                $rip="$rip;$ql";
            break;
        }
        if($mediaPluginID!==null){
            [b]$dbADO->Execute($updateDD,array($rip,$mediaPluginID,$GLOBALS['RipFormat']));[/b]
        }else{
            $err.=$TEXT_ERROR_UNABLE_TO_FIND_MEDIA_PLUGIN_CONST.'<br>';
        }

From which I can see that the SQL is contained in $updateDD , so I search backwards in the code to find it defined:
Code: [Select]
        $updateDD='UPDATE Device_DeviceData SET IK_DeviceData=? WHERE FK_Device=? AND FK_DeviceData=?';

So I connect to the pluto_main DB and look for the record:
Code: [Select]
# mysql pluto_main
(...)
mysql> select * from Device_DeviceData where IK_DeviceData='flac';
+-----------+---------------+---------------+--------+-----------+----------+------------+---------------------+--------------+
| FK_Device | FK_DeviceData | IK_DeviceData | psc_id | psc_batch | psc_user | psc_frozen | psc_mod             | psc_restrict |
+-----------+---------------+---------------+--------+-----------+----------+------------+---------------------+--------------+
|        10 |            47 | flac          |   NULL |      NULL |     NULL |          0 | 2008-01-19 00:34:53 |         NULL |
+-----------+---------------+---------------+--------+-----------+----------+------------+---------------------+--------------+
1 row in set (0.00 sec)

Eureka!

That's everything.

The Orbiter message to the Powerfile_C200 is supposed to include a format parameter, according to the command's specs. But it doesn't. Which is probably OK, because the Powerfile_C200 has logic to check for a missing format param. But that logic just defaults to ogg, instead of looking in the DB for the stored format setting. The Powerfile_C200 should be the object to decide in what format to rip unless it's specified, so I will add the DB lookup there when the sent param is missing. Later, if the Orbiter has a GUI to specify a rip format, it can specify so in the param, which will override the default logic. The Powerfile_C200 should be managing its own defaults, not the Orbiter, anyway.