Ticket #3433: 3433-v2.patch

File 3433-v2.patch, 5.6 KB (added by danielk, 13 years ago)

Code reviewed + updated patch (still untested)

  • libs/libmythtv/osdtypeteletext.h

     
    1818class OSD;
    1919class OSDType;
    2020class OSDSurface;
     21class OSDTypeTeletext;
    2122class TV;
    2223
    2324class TTColor
     
    106107    int_to_page_t     pages;
    107108};
    108109
     110class OSDUpdateLocker
     111{
     112  public:
     113    OSDUpdateLocker(QMutex *lock, OSDTypeTeletext *parent);
     114    ~OSDUpdateLocker(void);
     115
     116  private:
     117    QMutex          *m_lock;
     118    OSDTypeTeletext *m_parent;
     119};
     120
    109121class OSDTypeTeletext : public OSDType, public TeletextViewer
    110122{
    111123    Q_OBJECT
     124
    112125    friend QColor color_tt2qt(int ttcolor);
     126    friend class OSDUpdateLocker;
     127
    113128  public:
    114129    OSDTypeTeletext(const QString &name, TTFFont *font,
    115130                    QRect displayrect, float wmult, float hmult, OSD *osd);
     
    209224    uint8_t      m_header[40];
    210225    mutable bool m_header_changed;
    211226    mutable bool m_page_changed;
     227    mutable bool m_osd_changed;
    212228
    213229    TeletextMagazine m_magazines[8];
    214230    unsigned char    m_bitswap[256];
  • libs/libmythtv/osdtypeteletext.cpp

     
    6868
    6969      m_transparent(false),             m_revealHidden(false),
    7070      m_displaying(false),              m_osd(osd),
    71       m_header_changed(false),          m_page_changed(false)
     71      m_header_changed(false),          m_page_changed(false),
     72      m_osd_changed(false)
    7273{
    7374    m_unbiasedrect  = bias(m_displayrect, wmult, hmult);
    7475
     
    8990 */
    9091void OSDTypeTeletext::Reset(void)
    9192{
    92     QMutexLocker locker(&m_lock);
     93    OSDUpdateLocker locker(&m_lock, this);
    9394
    9495    for (uint mag = 0; mag < 8; mag++)
    9596    {
     
    129130                                    const unsigned char* buf,
    130131                                    int vbimode, int lang, int flags)
    131132{
    132     QMutexLocker locker(&m_lock);
     133    OSDUpdateLocker locker(&m_lock, this);
    133134
    134135    int magazine = MAGAZINE(page);
    135136    if (magazine < 1 || magazine > 8)
     
    207208void OSDTypeTeletext::AddTeletextData(int magazine, int row,
    208209                                      const unsigned char* buf, int vbimode)
    209210{
    210     QMutexLocker locker(&m_lock);
     211    OSDUpdateLocker locker(&m_lock, this);
    211212
    212213    int b1, b2, b3, err;
    213214
     
    322323        return;
    323324
    324325    m_page_changed = true;
    325     m_osd->UpdateTeletext();
     326    m_osd_changed = true;
     327// note: We cannot call UpdateTeletext from here since it will try to get the
     328//       osdlock. The problem with this is that the OSD::Display might already
     329//       be active and have called our Draw function and hence is pending the
     330//       m_lock being freed. Since the OSD::Display uses the osdlock, our call
     331//       to the UpdateTeletext would result in a semaphore deadlock.
     332//    m_osd->UpdateTeletext();
    326333}
    327334
    328335/** \fn OSDTypeTeletext::HeaderUpdated(unsigned char*,int)
     
    479486 */
    480487void OSDTypeTeletext::KeyPress(uint key)
    481488{
    482     QMutexLocker locker(&m_lock);
     489    OSDUpdateLocker locker(&m_lock, this);
    483490
    484491    int newPage = m_curpage;
    485492    int newSubPage = m_cursubpage;
     
    665672 */
    666673void OSDTypeTeletext::SetPage(int page, int subpage)
    667674{
    668     QMutexLocker locker(&m_lock);
     675    OSDUpdateLocker locker(&m_lock, this);
    669676
    670677    if (page < 0x100 || page > 0x899)
    671678        return;
     
    11091116
    11101117void OSDTypeTeletext::Reinit(float wmult, float hmult)
    11111118{
    1112     QMutexLocker locker(&m_lock);
     1119    OSDUpdateLocker locker(&m_lock, this);
    11131120
    11141121    m_displayrect = bias(m_unbiasedrect, wmult, hmult);
    11151122    m_tt_colspace = m_displayrect.width()  / kTeletextColumns;
     
    12321239    }
    12331240}
    12341241
     1242/**
     1243 * \class OSDUpdateLocker
     1244 * \brief Helper class to the OSDTypeTeletext
     1245 *
     1246 * This class is used to lock the m_lock semaphore when
     1247 * there is a chance that the locked code will result in the
     1248 * OSD::UpdateTeletext() function being called. It's purpose
     1249 * is to lock the semaphore and once the locked code has
     1250 * finished to check for a request to call OSD::UpdateTeletext().
     1251 * If required, the m_lock is released and the required call made
     1252 *
     1253 * This is to overcome the possible semaphore deadlock as follows:
     1254 * \code
     1255 *  - Teletext data arrives -> locks m_lock
     1256 *  - While the teletext data is being processed the XMV request an
     1257 *    OSD update display
     1258 *  - The OSD update display will lock the osdlock
     1259 *  - The OSD update can results in the Teletext:Draw method being
     1260 *    called and hence the OSD update is now waiting on m_lock being
     1261 *    released to continue it's drawing process
     1262 *  - If the processing of the teletext data result in the function
     1263 *    OSD::UpdateTeletext being called, this function will try to
     1264 *    get the osdlock.
     1265 *  - This results in the classic semaphore deadlock and hence all
     1266 *    OSD update cease.
     1267 * \endcode
     1268 **************************************************************************/
     1269
     1270OSDUpdateLocker::OSDUpdateLocker(QMutex *lock, OSDTypeTeletext *parent) :
     1271    m_lock(lock), m_parent(parent)
     1272{
     1273    m_lock->lock();
     1274}
     1275
     1276OSDUpdateLocker::~OSDUpdateLocker(void)
     1277{
     1278    // see if the osd has to be requested a redraw
     1279    if (m_parent->m_osd_changed)
     1280    {
     1281        m_parent->m_osd_changed = false;
     1282        m_lock->unlock();
     1283        // now it is safe to do the OSD update
     1284        m_parent->m_osd->UpdateTeletext();
     1285    }
     1286    else
     1287    {
     1288        // normal exit. Will result in the m_lock being released.
     1289        m_lock->unlock();
     1290    }
     1291}
     1292