Andrew de Quincey schrieb:

Hi, I've just tried my MPEX under 2.6.8.1 - no problems here. I *AM* using my updated patch (which I have attached) but I wouldn't have thought that would fix sound muting problems.
[...]


Hi Andrew,

the list seems to be down, therefore I send this mail to you directly.
I tried your patch, but without success. :-( Maybe I'm doing something wrong.


Please take a look to the attached code. This one was, slightly modificated, running under kernel 2.4.24 to 2.4.26 with the v4l2 patch.

The only thing I have changed is the way how to set uo the video and audio pid's. I hope that you are familar with vdr.

I have some entries in my channels.conf like this:

C-Video:1:h:S28.2E:0:260:256:0:5:1:0:0:0
S-Video:1:h:S28.2E:0:260:256:0:5:2:0:0:0
M-Tuner:1:h:S28.2E:0:260:256:0:5:3:0:0:0

The first parameters are ignored
260 is the video pid (this was 256 before)
256 is the audio pid (this was 259 before)
0 is the nonexisting teletext pid
5 is the ca device number, it directs to my card
1,2,3 are the v4l2-inputs of the card

With the 2.4.x kernels I could adjust the colour, brightness and contrast. Controling the volume or loudness was not possible. I don't have to unmute anything.

In my setup the 1st device was the v4l2-device witch was opend to set up the colour and the second device was the ts-device

With the new kernel everything is working as before but I have no sound. This is also the case if I reboot from 2.6.8.1 to 2.4.26 without switching off. I tried different things (unmuting, input switching, etc) That is the reason why the source is a little bit messed up with comments.

I gave up for now, you are my last hope.  :-)


Alfred

/*
 * mpex.c: A plugin for the Video Disk Recorder
 *
 * See the README file for copyright information and how to reach the author.
 */

#include <sys/ioctl.h>
#include <stdio.h>
#include <stdarg.h>
#include <string.h>
#include <time.h>
#include <syslog.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/select.h>
#include <fcntl.h>
#include <unistd.h>
#include <errno.h>
#include <signal.h>
#include <sys/mman.h>
#include <sys/sysinfo.h>
#include <sys/soundcard.h>
#include <linux/videodev.h>
#include <getopt.h>
#include <sys/socket.h>
#include <sys/time.h>
#include <sys/un.h>
#include <vdr/plugin.h>
#include <vdr/sources.h>

static const char *VERSION        = "0.0.1";
static const char *DESCRIPTION    = "MPEX card interface";
static const char *MAINMENUENTRY  = NULL;  //Hide main menu entry



// Global variables that control the overall behaviour:

int Volume;
int Loudness;
int Brightness;
int Contrast;
int Colour;


// --- cDigiboxDevice --------------------------------------------------------

#define DUMMYVPID 260
#define DUMMYAPID 256

/*
class cMpexChannel : public cListObject {
public:
  tChannelID channelID;
  int digiboxChannelNumber;
  bool Parse(const char *s);
  };

bool cMpexChannel::Parse(const char *s)
{
  char *id = NULL;
  if (2 == sscanf(s, "%a[^:]:%d", &id, &digiboxChannelNumber))
     channelID = tChannelID::FromString(id);
  free(id);
  return digiboxChannelNumber && channelID.Valid();
}

class cMpexChannels : public cConfig<cMpexChannel> {
public:
  cMpexChannel *GetMpexChannel(const cChannel *Channel);
  };

cMpexChannel *cMpexChannels::GetMpexChannel(const cChannel *Channel)
{
  tChannelID ChannelID = Channel->GetChannelID();
  for (cMpexChannel *sc = First(); sc; sc = Next(sc)) {
      if (ChannelID == sc->channelID)
         return sc;
      }
  return NULL;
}

cMpexChannels MpexChannels;
*/

class cDigiboxDevice : public cDevice
{
  private:
    int source;
    int digiboxChannelNumber;
    int fd_dvr;
    int fd;
    int apid, vpid, sid, tid;
    cTSBuffer *tsBuffer;
    static const char *videodevice;
    static const char *tsdevice;
  protected:
    virtual bool SetPid(cPidHandle *Handle, int Type, bool On);
    virtual bool OpenDvr(void);
    virtual void CloseDvr(void);
    virtual bool GetTSPacket(uchar *&Data);
  public:
    cDigiboxDevice(void);
    virtual ~cDigiboxDevice();
    virtual bool ProvidesSource(int Source) const;
    virtual bool ProvidesTransponder(const cChannel *Channel) const;
    virtual bool ProvidesChannel(const cChannel *Channel, int Priority = -1, bool 
*NeedsSetChannel = NULL) const;
    virtual bool SetChannelDevice(const cChannel *Channel, bool LiveView);
    static void SetVideoDevice(const char *VideoDevice);
    static const char *VideoDevice(void);
    static void SetTSDevice(const char *TSDevice);
    static const char *TSDevice(void);
};

const char *cDigiboxDevice::tsdevice = "/dev/video1";
const char *cDigiboxDevice::videodevice = "/dev/video0";

cDigiboxDevice::cDigiboxDevice(void)
{
  source = cSource::FromString("S28.2E");
  digiboxChannelNumber = 0;
  fd_dvr = -1;
  apid = vpid = 0;
}

cDigiboxDevice::~cDigiboxDevice()
{
  // Clean up after yourself!
}


bool cDigiboxDevice::SetPid(cPidHandle *Handle, int Type, bool On)
{
  dsyslog("SetPid %d %d", Handle->pid, On);
  return true;
}

bool cDigiboxDevice::OpenDvr(void)
{
  CloseDvr();
  fd_dvr = open(tsdevice, O_RDONLY | O_NONBLOCK );
  if (fd_dvr >= 0)
     tsBuffer = new cTSBuffer(fd_dvr, KILOBYTE(256), CardIndex() + 1);
  return fd_dvr >= 0;
}


void cDigiboxDevice::CloseDvr(void)
{
  if (fd_dvr >= 0)
  {
    close(fd_dvr);
    fd_dvr = -1;
    delete tsBuffer;
    tsBuffer = NULL;
  }
}

bool cDigiboxDevice::GetTSPacket(uchar *&Data)
{
  if (tsBuffer)

  {
    int r = tsBuffer->Read();
    if (r >= 0)
        {
      Data = tsBuffer->Get();

//-----------this part is new in 1.3.x

      if (Data) {
           // insert the actual PIDs:
           int Pid = (((uint16_t)Data[1] & PID_MASK_HI) << 8) | Data[2];
           if (Pid == DUMMYAPID)
              Pid = apid;
           else if (Pid == DUMMYVPID)
              Pid = vpid;
           Data[1] = ((Pid >> 8) & 0xFF) | (Data[1] & ~PID_MASK_HI);
           Data[2] = Pid & 0xFF;
           } 

//---------------------------

      return true;
    }
    else if (FATALERRNO)
        {
      LOG_ERROR;
      return false;
    }
    return true;
  }
  return false;
}

bool cDigiboxDevice::ProvidesSource(int Source) const
{
  return source == Source;
}


bool cDigiboxDevice::ProvidesTransponder(const cChannel *Channel) const
{
  return false; // can't provide any actual transponder
}


bool cDigiboxDevice::ProvidesChannel(const cChannel *Channel, int Priority, bool 
*NeedsDetachReceivers) const
{
  bool result = false;
  bool hasPriority = Priority < 0 || Priority > this->Priority();
  bool needsDetachReceivers = true;



//  cMpexChannel *MpexChannel = MpexChannels.GetMpexChannel(Channel);
//  if (MpexChannel) {


  if (ProvidesSource(Channel->Source())) {
    if (Receiving(true)) {
//        if (digiboxChannelNumber == MpexChannel->digiboxChannelNumber) {
        if (digiboxChannelNumber == Channel->Frequency()) {

        needsDetachReceivers = false;
        result = true;
      }
      else
      result = hasPriority;
    }
    else
      result = hasPriority;
  }
  if (NeedsDetachReceivers)
    *NeedsDetachReceivers = needsDetachReceivers;
  return result;
}


bool cDigiboxDevice::SetChannelDevice(const cChannel *Channel, bool LiveView)
{
    if ( !Receiving(true)) { // if we are receiving the channel is already set!
//      cMpexChannel *MpexChannel = MpexChannels.GetMpexChannel(Channel);
//      if (MpexChannel) {
//          digiboxChannelNumber = MpexChannel->digiboxChannelNumber;
            digiboxChannelNumber = Channel->Sid();
            vpid = Channel->Vpid();     // Video PID (MPEX default = 256)
            apid = Channel->Apid1();    // Audio PID (MPEX default = 259)
            tid = Channel->Tid();       // TID, used to switch input (0=composite 
video, 1=svhs, 2=tuner)
            sid = Channel->Sid();       // SID, sended by LIRC
            esyslog("Set Channel TID %d SID %d  VPID %d  APID %d", tid, sid, vpid, 
apid);
            //XXX only when recording??? -> faster channel switching!
            //LircSend("SKY"); // makes sure the Digibox is "on"
            //XXX lircprint(fd_lirc, "BACKUP");
            //XXX lircprint(fd_lirc, "BACKUP");
            //XXX lircprint(fd_lirc, "BACKUP");

            //LircSend(digiboxChannelNumber);
            //struct v4l2_capability vcap;
            //struct v4l2_input input;
            //struct v4l2_queryctrl queryctrl;

            struct v4l2_control control;
            fd = open(videodevice, O_RDWR);
            if (ioctl(fd, VIDIOC_S_INPUT, &tid) == -1 ) {
                const char *c = "Error: digiboxChannelNumber %s\n";
                char buf[100];
                sprintf(buf, c, digiboxChannelNumber);
                dsyslog(buf);
                }

//          struct v4l2_audio audio;
//          memset (&audio, 0, sizeof (audio)); /* clear audio.mode, audio.reserved */
//          audio.index = 0;
//          if (ioctl(fd, VIDIOC_S_AUDIO, &audio) == -1 ) {
//              perror ("VIDIOC_S AUDIO");
//              }

            // --- setting brightness ---
            control.id = V4L2_CID_BRIGHTNESS;
            control.value = Brightness;
            if (ioctl (fd, VIDIOC_S_CTRL, &control) == -1) {
                perror ("VIDIOC_S_CTRL");
                }
            // --- setting contrast ---
            control.id = V4L2_CID_CONTRAST;
            control.value = Contrast;
            if (ioctl (fd, VIDIOC_S_CTRL, &control) == -1) {
                perror ("VIDIOC_S_CTRL");
                }
            control.id = V4L2_CID_HUE;
            control.value = Colour;
            if (ioctl (fd, VIDIOC_S_CTRL, &control) == -1) {
                perror ("VIDIOC_S_CTRL");
                }
            // --- volume setting ---          funzt nicht  :-(
//          control.id = V4L2_CID_AUDIO_VOLUME;
//          control.value = Volume;
//          if (ioctl (fd, VIDIOC_S_CTRL, &control) == -1) {
//              perror ("VIDIOC_S_CTRL");
//              }
//          control.id = V4L2_CID_AUDIO_LOUDNESS;
//          control.value = true;
//          if (ioctl (fd, VIDIOC_S_CTRL, &control) == -1) {
//              perror ("VIDIOC_S_CTRL");
//              }
//          control.id = V4L2_CID_AUDIO_MUTE;
//          control.value = false;
//          if (ioctl (fd, VIDIOC_S_CTRL, &control) == -1) {
//              perror ("VIDIOC_S_CTRL");
//              }
            close(fd); 
//       }
    }
return true;
}

void cDigiboxDevice::SetVideoDevice(const char *VideoDevice)
{
  videodevice = strdup(VideoDevice);
}

const char *cDigiboxDevice::VideoDevice(void)
{
  return videodevice;
}

void cDigiboxDevice::SetTSDevice(const char *TSDevice)
{
  tsdevice = strdup(TSDevice);
}

const char *cDigiboxDevice::TSDevice(void)
{
  return tsdevice;
}



// --- cPluginMpex ------------------------------------------------------------


class cPluginMpex : public cPlugin
{
  private:
    // Add any member variables or functions you may need here.
    const char *videodevice;
    const char *tsdevice;
  public:
    cPluginMpex(void);
    virtual ~cPluginMpex();
    virtual const char *Version(void) { return VERSION; }
    virtual const char *Description(void) { return DESCRIPTION; }
    virtual const char *CommandLineHelp(void);
    virtual bool ProcessArgs(int argc, char *argv[]);
    virtual bool Initialize(void);
    virtual bool Start(void);
    virtual void Housekeeping(void);
    virtual const char *MainMenuEntry(void) { return MAINMENUENTRY; }
    virtual cOsdObject *MainMenuAction(void);
    virtual cMenuSetupPage *SetupMenu(void);
    virtual bool SetupParse(const char *Name, const char *Value);
};


cPluginMpex::cPluginMpex(void)
{
  // Initialize any member variables here.
  // DON'T DO ANYTHING ELSE THAT MAY HAVE SIDE EFFECTS, REQUIRE GLOBAL
  // VDR OBJECTS TO EXIST OR PRODUCE ANY OUTPUT!
  videodevice = "/dev/video0";
  tsdevice = "/dev/video1";
}


cPluginMpex::~cPluginMpex()
{
  // Clean up after yourself!
}


const char *cPluginMpex::CommandLineHelp(void)
{
  // Return a string that describes all known command line options.
  return "  -v [dev],   --video=[dev]  Video-Device  (default: /dev/video0\n"
         "  -t [dev],   --ts=[dev]     TS-Device     (default: /dev/video1\n";
}


bool cPluginMpex::ProcessArgs(int argc, char *argv[])
{
  // Implement command line argument processing here if applicable.
  static struct option long_options[] =
  {
    { "video",  required_argument, NULL, 'v'},
    { "ts",     required_argument, NULL, 't'},
    { NULL}
  };
  int c, option_index = 0;
  while((c = getopt_long(argc,argv,"v:t:",long_options,&option_index))!=-1)
  {
    switch(c)
        {
      case 'v':
        videodevice = optarg;
                break;
      case 't':
        tsdevice = optarg;
            break;
      default:
            return false;
    }
  }
  return true;
}


bool cPluginMpex::Initialize(void)
{
  // Initialize any background activities the plugin shall perform.
    new cDigiboxDevice;
    return true;

/*
  const char *ConfigDir = ConfigDirectory(Name());
  if (ConfigDir) {
     if (MpexChannels.Load(AddDirectory(ConfigDir, "channels.conf.mpex"), true)) {
        new cDigiboxDevice;
        return true;
 
        }
        }
  else
     esyslog("ERROR: can't get config directory");
  return false;
*/
}


bool cPluginMpex::Start(void)
{
  // Start any background activities the plugin shall perform.
  cDigiboxDevice::SetVideoDevice(videodevice);
  cDigiboxDevice::SetTSDevice(tsdevice);
  //RegisterI18n(Phrases);
  return true;
}


void cPluginMpex::Housekeeping(void)
{
  // Perform any cleanup or other regular tasks.
}


cOsdObject *cPluginMpex::MainMenuAction(void)
{
  // Perform the action when selected from the main VDR menu.
  return NULL;
}


class cMenuSetupMpex : public cMenuSetupPage
{
  private:
    int newVolume;
    int newLoudness;
    int newBrightness;
    int newContrast;
    int newColour;
  protected:
    virtual void Store(void);
  public:
    cMenuSetupMpex(void);
};

cMenuSetupPage *cPluginMpex::SetupMenu(void)
{
  // Return a setup menu in case the plugin supports one.
  return new cMenuSetupMpex;
}

cMenuSetupMpex::cMenuSetupMpex(void)
{
  // Return a setup menu in case the plugin supports one.
  newVolume = Volume;
  newLoudness = Loudness;
  newBrightness = Brightness;
  newContrast = Contrast;
  newColour = Colour;
  Add(new cMenuEditIntItem(tr("Volume"), &newVolume, 1, 65535));
  Add(new cMenuEditIntItem(tr("Loudness"), &newLoudness, 0, 1)); 
  Add(new cMenuEditIntItem(tr("Brightness"), &newBrightness, 1, 65535)); 
  Add(new cMenuEditIntItem(tr("Contrast"), &newContrast, 1, 65535));
  Add(new cMenuEditIntItem(tr("Colour"), &newColour, 1, 65535));
}

void cMenuSetupMpex::Store(void)
{
  SetupStore("Volume", Volume = newVolume);
  SetupStore("Loudness", Loudness = newLoudness);
  SetupStore("Brightness", Brightness = newBrightness);
  SetupStore("Contrast", Contrast = newContrast);
  SetupStore("Colour", Colour = newColour);
}

bool cPluginMpex::SetupParse(const char *Name, const char *Value)
{
  // Parse your own setup parameters and store their values.
  if      (!strcasecmp(Name, "Volume"))     Volume = atoi(Value);
  else if (!strcasecmp(Name, "Loudness"))   Loudness = atoi(Value);
  else if (!strcasecmp(Name, "Brightness")) Brightness = atoi(Value);
  else if (!strcasecmp(Name, "Contrast"))   Contrast = atoi(Value);
  else if (!strcasecmp(Name, "Colour"))     Colour = atoi(Value);
  else 
        return false;
  return true;
}

VDRPLUGINCREATOR(cPluginMpex); // Don't touch this!

Reply via email to