Skip to content

Change HDMI Source on TV (Device 0) #10

Closed

Description

@pimok

Thank you for your great work!

Is there an API function, using the current bindings, that lets me select the source to be displayed on the TV?
ActiveSource chooses "self", but I want to be able to tell the TV choose HDMI1, HDMI2 or HDMI3 using the API.

Thanks again.
pimok

Activity

  1. trainman419 commented on Feb 9, 2015

    @trainman419
    Owner

    libcec doesn't provide any bindings for changing the input on a specific device.

    I suspect this is because the CEC standard doesn't specify commands for changing inputs.

    For my receiver, there are vendor-specific remote keypresses that I can send to change inputs (Device.set_av_input). I suspect your TV has a similar set of keypresses, but they're probably vendor-specific. If you can find or figure out which keypresses to send, I can help provide a better API for sending them.

  2. pimok commented on Feb 9, 2015

    @pimok
    Author

    Thanks for your feednback.

    Unfortunately on my samsung, pressing the remote control (av input)SOURCE and then NUM3 brings an on-screen error message and only allows the arrows to select the source.

    There seems to be a CEC command sequence which tells the TV to select an input. I do not know if the TV reacts directly to this command or if one of its sources reacts to the CEC command and selects itself to be the source on the TV. This does actually work when I type in the sequence as a tx command using cec-client.

    The CEC command for "TV please select HDMI2 as av input" on the bus looks like;
    1f 82 20 00
    1 is the initiator (me ? eg RPi?)
    f is CECDEVICE_BROADCAST
    82 is CEC_OPCODE_ACTIVE_SOURCE
    20 00 is HDMI2

    This is output by the following libcec code:
    bool CCECCommandHandler::TransmitActiveSource(const cec_logical_address iInitiator, uint16_t iPhysicalAddress, bool bIsReply)
    {
    cec_command command;
    cec_command::Format(command, iInitiator, CECDEVICE_BROADCAST, CEC_OPCODE_ACTIVE_SOURCE);
    command.parameters.PushBack((uint8_t) ((iPhysicalAddress >> 8) & 0xFF));
    command.parameters.PushBack((uint8_t) (iPhysicalAddress & 0xFF));

    return Transmit(command, false, bIsReply);
    }

    Making a binding to this function is probably difficult as the network structure of the C++ classes is quite deep and maybe the initiator may become wrong.

    If you could implement a binding for a function that gives direct access to Transmit then this could be used to send CEC packets on the bus and bypassing the network structure. Something like a python call cec.transmit("1f822000")

    Possible implementation in your bindings code cec.cpp:

    static unsigned char from_hex(char c)
    {
    return (c>='0' && c<='9') ? (c-'0'):
    (c>='a' && c<='f') ? (c-'a'+10):
    (c>='A' && c<='F') ? (c-'A'+10): 0;
    }

    static unsigned char from_hex2(char hi, char lo)
    {
    return from_hex(hi)<<4+from_hex(lo);
    }

    static PyObject * transmit(PyObject * args) {
    const char * input = NULL;
    if( PyArg_ParseTuple(args, "s:transmit", &input) && input && strlen(input)>=4) {
    cec_command data;
    bool success;
    Py_BEGIN_ALLOW_THREADS
    data.initiator = from_hex(input[0]);
    data.destination = from_hex(input[1]);
    data.opcode = from_hex2(input[2], input[3]);
    data.opcode_set = 1;
    for (int i= 4; input[i] && input[i+1]; i+= 2)
    data.PushBack(from_hex2(input[i], input[i+1]));
    success = CEC_adapter->Transmit(data);
    Py_END_ALLOW_THREADS
    if( success ) {
    Py_RETURN_TRUE;
    } else {
    Py_RETURN_FALSE;
    }
    }
    else {
    return NULL;
    }
    }

    Thanks again
    pimok

  3. trainman419 commented on Feb 9, 2015

    @trainman419
    Owner

    If you have suggested code changes, please submit them as a pull request.

    That said, I recommend a few changes to this before submitting it:

    • Determine the sender address automatically.
    • Make this a method on the Device object rather than a raw call, so that the user doesn't have to worry about the destination device address.

    If libcec is already implementing this as part of their setActiveSource call, it may be better to implement the wrapper for that; particularly since it's already on the TODO list for the API.

  4. Snyder1977 commented on Mar 20, 2015

    @Snyder1977

    Hi all, I have the same problem as pimok. My Panasonic TV can be turned on but it chooses the wrong input. It will be set to the correct input, if I send the following command via shell: echo "tx 4f 82 23 00" | cec-client -s

    I´d like to be able to set the active source via python. It would be great to have a python wrapper for setting the active source!

  5. s-gopinath commented on Mar 15, 2017

    @s-gopinath

    Hi Voltagex,

    I tried the "as" command. But It always activate the HDMI1 source. But My the HDMI CEC adapter is connected to HDMI2. Can anyone tell me how to activate the HDMI port of which my device is connected?

  6. trainman419 commented on Nov 4, 2017

    @trainman419
    Owner

    set_active_source and get_active_source have now been implemented.

  7. albfan commented on May 3, 2024

    @albfan

    As this is based on libcec if Pulse-Eight/libcec#656 is correct, will set_active_source really work? or only for hdmi1?

    cec.transmit(destination, opcode, bytes([0x30,0x00]))

    just work, but

    cec.set_active_source(3)

    always redirect to hdmi1

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions