/* SPDX-License-Identifier: GPL-2.0-or-later */ /* * Copyright (C) 2019, Google Inc. * * geometry.cpp - Geometry classes tests */ #include <iostream> #include <libcamera/geometry.h> #include "test.h" using namespace std; using namespace libcamera; class GeometryTest : public Test { protected: template<typename T> bool compare(const T &lhs, const T &rhs, bool (*op)(const T &lhs, const T &rhs), const char *opName, bool expect) { bool result = op(lhs, rhs); if (result != expect) { cout << lhs.toString() << opName << " " << rhs.toString() << "test failed" << std::endl; return false; } return true; } int run() { /* * Point tests */ /* Equality */ if (!compare(Point(50, 100), Point(50, 100), &operator==, "==", true)) return TestFail; if (!compare(Point(-50, 100), Point(-50, 100), &operator==, "==", true)) return TestFail; if (!compare(Point(50, -100), Point(50, -100), &operator==, "==", true)) return TestFail; if (!compare(Point(-50, -100), Point(-50, -100), &operator==, "==", true)) return TestFail; /* Inequality */ if (!compare(Point(50, 100), Point(50, 100), &operator!=, "!=", false)) return TestFail; if (!compare(Point(-50, 100), Point(-50, 100), &operator!=, "!=", false)) return TestFail; if (!compare(Point(50, -100), Point(50, -100), &operator!=, "!=", false)) return TestFail; if (!compare(Point(-50, -100), Point(-50, -100), &operator!=, "!=", false)) return TestFail; if (!compare(Point(-50, 100), Point(50, 100), &operator!=, "!=", true)) return TestFail; if (!compare(Point(50, -100), Point(50, 100), &operator!=, "!=", true)) return TestFail; if (!compare(Point(-50, -100), Point(50, 100), &operator!=, "!=", true)) return TestFail; /* Negation */ if (Point(50, 100) != -Point(-50, -100) || Point(50, 100) == -Point(50, -100) || Point(50, 100) == -Point(-50, 100)) { cout << "Point negation test failed" << endl; return TestFail; } /* Default constructor */ if (Point() != Point(0, 0)) { cout << "Default constructor test failed" << endl; return TestFail; } /* * Size tests */ if (!Size().isNull() || !Size(0, 0).isNull()) { cout << "Null size incorrectly reported as not null" << endl; return TestFail; } if (Size(0, 100).isNull() || Size(100, 0).isNull() || Size(100, 100).isNull()) { cout << "Non-null size incorrectly reported as null" << endl; return TestFail; } /* Test alignDownTo(), alignUpTo(), boundTo() and expandTo() */ Size s(50, 50); s.alignDownTo(16, 16); if (s != Size(48, 48)) { cout << "Size::alignDownTo() test failed" << endl; return TestFail; } s.alignUpTo(32, 32); if (s != Size(64, 64)) { cout << "Size::alignUpTo() test failed" << endl; return TestFail; } s.boundTo({ 40, 40 }); if (s != Size(40, 40)) { cout << "Size::boundTo() test failed" << endl; return TestFail; } s.expandTo({ 50, 50 }); if (s != Size(50, 50)) { cout << "Size::expandTo() test failed" << endl; return TestFail; } s.alignDownTo(16, 16).alignUpTo(32, 32) .boundTo({ 40, 80 }).expandTo({ 16, 80 }); if (s != Size(40, 80)) { cout << "Size chained in-place modifiers test failed" << endl; return TestFail; } /* Test alignedDownTo(), alignedUpTo(), boundedTo() and expandedTo() */ if (Size(0, 0).alignedDownTo(16, 8) != Size(0, 0) || Size(1, 1).alignedDownTo(16, 8) != Size(0, 0) || Size(16, 8).alignedDownTo(16, 8) != Size(16, 8)) { cout << "Size::alignedDownTo() test failed" << endl; return TestFail; } if (Size(0, 0).alignedUpTo(16, 8) != Size(0, 0) || Size(1, 1).alignedUpTo(16, 8) != Size(16, 8) || Size(16, 8).alignedUpTo(16, 8) != Size(16, 8)) { cout << "Size::alignedUpTo() test failed" << endl; return TestFail; } if (Size(0, 0).boundedTo({ 100, 100 }) != Size(0, 0) || Size(200, 50).boundedTo({ 100, 100 }) != Size(100, 50) || Size(50, 200).boundedTo({ 100, 100 }) != Size(50, 100)) { cout << "Size::boundedTo() test failed" << endl; return TestFail; } if (Size(0, 0).expandedTo({ 100, 100 }) != Size(100, 100) || Size(200, 50).expandedTo({ 100, 100 }) != Size(200, 100) || Size(50, 200).expandedTo({ 100, 100 }) != Size(100, 200)) { cout << "Size::expandedTo() test failed" << endl; return TestFail; } /* Aspect ratio tests */ if (Size(0, 0).boundedToAspectRatio(Size(4, 3)) != Size(0, 0) || Size(1920, 1440).boundedToAspectRatio(Size(16, 9)) != Size(1920, 1080) || Size(1920, 1440).boundedToAspectRatio(Size(65536, 36864)) != Size(1920, 1080) || Size(1440, 1920).boundedToAspectRatio(Size(9, 16)) != Size(1080, 1920) || Size(1920, 1080).boundedToAspectRatio(Size(4, 3)) != Size(1440, 1080) || Size(1920, 1080).boundedToAspectRatio(Size(65536, 49152)) != Size(1440, 1080) || Size(1024, 1024).boundedToAspectRatio(Size(1, 1)) != Size(1024, 1024) || Size(1920, 1080).boundedToAspectRatio(Size(16, 9)) != Size(1920, 1080) || Size(200, 100).boundedToAspectRatio(Size(16, 9)) != Size(177, 100) || Size(300, 200).boundedToAspectRatio(Size(16, 9)) != Size(300, 168)) { cout << "Size::boundedToAspectRatio() test failed" << endl; return TestFail; } if (Size(0, 0).expandedToAspectRatio(Size(4, 3)) != Size(0, 0) || Size(1920, 1440).expandedToAspectRatio(Size(16, 9)) != Size(2560, 1440) || Size(1920, 1440).expandedToAspectRatio(Size(65536, 36864)) != Size(2560, 1440) || Size(1440, 1920).expandedToAspectRatio(Size(9, 16)) != Size(1440, 2560) || Size(1920, 1080).expandedToAspectRatio(Size(4, 3)) != Size(1920, 1440) || Size(1920, 1080).expandedToAspectRatio(Size(65536, 49152)) != Size(1920, 1440) || Size(1024, 1024).expandedToAspectRatio(Size(1, 1)) != Size(1024, 1024) || Size(1920, 1080).expandedToAspectRatio(Size(16, 9)) != Size(1920, 1080) || Size(200, 100).expandedToAspectRatio(Size(16, 9)) != Size(200, 112) || Size(300, 200).expandedToAspectRatio(Size(16, 9)) != Size(355, 200)) { cout << "Size::expandedToAspectRatio() test failed" << endl; return TestFail; } /* Size::centeredTo() tests */ if (Size(0, 0).centeredTo(Point(50, 100)) != Rectangle(50, 100, 0, 0) || Size(0, 0).centeredTo(Point(-50, -100)) != Rectangle(-50, -100, 0, 0) || Size(100, 200).centeredTo(Point(50, 100)) != Rectangle(0, 0, 100, 200) || Size(100, 200).centeredTo(Point(-50, -100)) != Rectangle(-100, -200, 100, 200) || Size(101, 201).centeredTo(Point(-50, -100)) != Rectangle(-100, -200, 101, 201) || Size(101, 201).centeredTo(Point(-51, -101)) != Rectangle(-101, -201, 101, 201)) { cout << "Size::centeredTo() test failed" << endl; return TestFail; } /* Scale a size by a float */ if (Size(1000, 2000) * 2.0 != Size(2000, 4000) || Size(300, 100) * 0.5 != Size(150, 50) || Size(1, 2) * 1.6 != Size(1, 3)) { cout << "Size::operator*() failed" << endl; return TestFail; } if (Size(1000, 2000) / 2.0 != Size(500, 1000) || Size(300, 100) / 0.5 != Size(600, 200) || Size(1000, 2000) / 3.0 != Size(333, 666)) { cout << "Size::operator*() failed" << endl; return TestFail; } s = Size(300, 100); s *= 0.3333; if (s != Size(99, 33)) { cout << "Size::operator*() test failed" << endl; return TestFail; } s = Size(300, 100); s /= 3; if (s != Size(100, 33)) { cout << "Size::operator*() test failed" << endl; return TestFail; } /* Test Size equality and inequality. */ if (!compare(Size(100, 100), Size(100, 100), &operator==, "==", true)) return TestFail; if (!compare(Size(100, 100), Size(100, 100), &operator!=, "!=", false)) return TestFail; if (!compare(Size(100, 100), Size(200, 100), &operator==, "==", false)) return TestFail; if (!compare(Size(100, 100), Size(200, 100), &operator!=, "!=", true)) return TestFail; if (!compare(Size(100, 100), Size(100, 200), &operator==, "==", false)) return TestFail; if (!compare(Size(100, 100), Size(100, 200), &operator!=, "!=", true)) return TestFail; /* Test Size ordering based on combined with and height. */ if (!compare(Size(100, 100), Size(200, 200), &operator<, "<", true)) return TestFail; if (!compare(Size(100, 100), Size(200, 200), &operator<=, "<=", true)) return TestFail; if (!compare(Size(100, 100), Size(200, 200), &operator>, ">", false)) return TestFail; if (!compare(Size(100, 100), Size(200, 200), &operator>=, ">=", false)) return TestFail; if (!compare(Size(200, 200), Size(100, 100), &operator<, "<", false)) return TestFail; if (!compare(Size(200, 200), Size(100, 100), &operator<=, "<=", false)) return TestFail; if (!compare(Size(200, 200), Size(100, 100), &operator>, ">", true)) return TestFail; if (!compare(Size(200, 200), Size(100, 100), &operator>=, ">=", true)) return TestFail; /* Test Size ordering based on area (with overlapping sizes). */ if (!compare(Size(200, 100), Size(100, 400), &operator<, "<", true)) return TestFail; if (!compare(Size(200, 100), Size(100, 400), &operator<=, "<=", true)) return TestFail; if (!compare(Size(200, 100), Size(100, 400), &operator>, ">", false)) return TestFail; if (!compare(Size(200, 100), Size(100, 400), &operator>=, ">=", false)) return TestFail; if (!compare(Size(100, 400), Size(200, 100), &operator<, "<", false)) return TestFail; if (!compare(Size(100, 400), Size(200, 100), &operator<=, "<=", false)) return TestFail; if (!compare(Size(100, 400), Size(200, 100), &operator>, ">", true)) return TestFail; if (!compare(Size(100, 400), Size(200, 100), &operator>=, ">=", true)) return TestFail; /* Test Size ordering based on width (with identical areas). */ if (!compare(Size(100, 200), Size(200, 100), &operator<, "<", true)) return TestFail; if (!compare(Size(100, 200), Size(200, 100), &operator<=, "<=", true)) return TestFail; if (!compare(Size(100, 200), Size(200, 100), &operator>, ">", false)) return TestFail; if (!compare(Size(100, 200), Size(200, 100), &operator>=, ">=", false)) return TestFail; if (!compare(Size(200, 100), Size(100, 200), &operator<, "<", false)) return TestFail; if (!compare(Size(200, 100), Size(100, 200), &operator<=, "<=", false)) return TestFail; if (!compare(Size(200, 100), Size(100, 200), &operator>, ">", true)) return TestFail; if (!compare(Size(200, 100), Size(100, 200), &operator>=, ">=", true)) return TestFail; /* * Rectangle tests */ /* Test Rectangle::isNull(). */ if (!Rectangle(0, 0, 0, 0).isNull() || !Rectangle(1, 1, 0, 0).isNull()) { cout << "Null rectangle incorrectly reported as not null" << endl; return TestFail; } if (Rectangle(0, 0, 0, 1).isNull() || Rectangle(0, 0, 1, 0).isNull() || Rectangle(0, 0, 1, 1).isNull()) { cout << "Non-null rectangle incorrectly reported as null" << endl; return TestFail; } /* Rectangle::size(), Rectangle::topLeft() and Rectangle::center() tests */ if (Rectangle(-1, -2, 3, 4).size() != Size(3, 4) || Rectangle(0, 0, 100000, 200000).size() != Size(100000, 200000)) { cout << "Rectangle::size() test failed" << endl; return TestFail; } if (Rectangle(1, 2, 3, 4).topLeft() != Point(1, 2) || Rectangle(-1, -2, 3, 4).topLeft() != Point(-1, -2)) { cout << "Rectangle::topLeft() test failed" << endl; return TestFail; } if (Rectangle(0, 0, 300, 400).center() != Point(150, 200) || Rectangle(-1000, -2000, 300, 400).center() != Point(-850, -1800) || Rectangle(10, 20, 301, 401).center() != Point(160, 220) || Rectangle(11, 21, 301, 401).center() != Point(161, 221) || Rectangle(-1011, -2021, 301, 401).center() != Point(-861, -1821)) { cout << "Rectangle::center() test failed" << endl; return TestFail; } /* Rectangle::boundedTo() (intersection function) */ if (Rectangle(0, 0, 1000, 2000).boundedTo(Rectangle(0, 0, 1000, 2000)) != Rectangle(0, 0, 1000, 2000) || Rectangle(-500, -1000, 1000, 2000).boundedTo(Rectangle(0, 0, 1000, 2000)) != Rectangle(0, 0, 500, 1000) || Rectangle(500, 1000, 1000, 2000).boundedTo(Rectangle(0, 0, 1000, 2000)) != Rectangle(500, 1000, 500, 1000) || Rectangle(300, 400, 50, 100).boundedTo(Rectangle(0, 0, 1000, 2000)) != Rectangle(300, 400, 50, 100) || Rectangle(0, 0, 1000, 2000).boundedTo(Rectangle(300, 400, 50, 100)) != Rectangle(300, 400, 50, 100) || Rectangle(0, 0, 100, 100).boundedTo(Rectangle(50, 100, 100, 100)) != Rectangle(50, 100, 50, 0) || Rectangle(0, 0, 100, 100).boundedTo(Rectangle(100, 50, 100, 100)) != Rectangle(100, 50, 0, 50) || Rectangle(-10, -20, 10, 20).boundedTo(Rectangle(10, 20, 100, 100)) != Rectangle(10, 20, 0, 0)) { cout << "Rectangle::boundedTo() test failed" << endl; return TestFail; } /* Rectangle::enclosedIn() tests */ if (Rectangle(10, 20, 300, 400).enclosedIn(Rectangle(-10, -20, 1300, 1400)) != Rectangle(10, 20, 300, 400) || Rectangle(-100, -200, 3000, 4000).enclosedIn(Rectangle(-10, -20, 1300, 1400)) != Rectangle(-10, -20, 1300, 1400) || Rectangle(-100, -200, 300, 400).enclosedIn(Rectangle(-10, -20, 1300, 1400)) != Rectangle(-10, -20, 300, 400) || Rectangle(5100, 6200, 300, 400).enclosedIn(Rectangle(-10, -20, 1300, 1400)) != Rectangle(990, 980, 300, 400) || Rectangle(100, -300, 150, 200).enclosedIn(Rectangle(50, 0, 200, 300)) != Rectangle(100, 0, 150, 200) || Rectangle(100, -300, 150, 1200).enclosedIn(Rectangle(50, 0, 200, 300)) != Rectangle(100, 0, 150, 300) || Rectangle(-300, 100, 200, 150).enclosedIn(Rectangle(0, 50, 300, 200)) != Rectangle(0, 100, 200, 150) || Rectangle(-300, 100, 1200, 150).enclosedIn(Rectangle(0, 50, 300, 200)) != Rectangle(0, 100, 300, 150)) { cout << "Rectangle::enclosedIn() test failed" << endl; return TestFail; } /* Rectange::scaledBy() tests */ if (Rectangle(10, 20, 300, 400).scaledBy(Size(0, 0), Size(1, 1)) != Rectangle(0, 0, 0, 0) || Rectangle(10, -20, 300, 400).scaledBy(Size(32768, 65536), Size(32768, 32768)) != Rectangle(10, -40, 300, 800) || Rectangle(-30000, 10000, 20000, 20000).scaledBy(Size(7, 7), Size(7, 7)) != Rectangle(-30000, 10000, 20000, 20000) || Rectangle(-20, -30, 320, 240).scaledBy(Size(1280, 960), Size(640, 480)) != Rectangle(-40, -60, 640, 480) || Rectangle(1, 1, 2026, 1510).scaledBy(Size(4056, 3024), Size(2028, 1512)) != Rectangle(2, 2, 4052, 3020)) { cout << "Rectangle::scaledBy() test failed" << endl; return TestFail; } /* Rectangle::translatedBy() tests */ if (Rectangle(10, -20, 300, 400).translatedBy(Point(-30, 40)) != Rectangle(-20, 20, 300, 400) || Rectangle(-10, 20, 400, 300).translatedBy(Point(50, -60)) != Rectangle(40, -40, 400, 300)) { cout << "Rectangle::translatedBy() test failed" << endl; return TestFail; } /* Rectangle::scaleBy() tests */ Rectangle r(-20, -30, 320, 240); r.scaleBy(Size(1280, 960), Size(640, 480)); if (r != Rectangle(-40, -60, 640, 480)) { cout << "Rectangle::scaleBy() test failed" << endl; return TestFail; } r = Rectangle(1, 1, 2026, 1510); r.scaleBy(Size(4056, 3024), Size(2028, 1512)); if (r != Rectangle(2, 2, 4052, 3020)) { cout << "Rectangle::scaleBy() test failed" << endl; return TestFail; } /* Rectangle::translateBy() tests */ r = Rectangle(10, -20, 300, 400); r.translateBy(Point(-30, 40)); if (r != Rectangle(-20, 20, 300, 400)) { cout << "Rectangle::translateBy() test failed" << endl; return TestFail; } r = Rectangle(-10, 20, 400, 300); r.translateBy(Point(50, -60)); if (r != Rectangle(40, -40, 400, 300)) { cout << "Rectangle::translateBy() test failed" << endl; return TestFail; } return TestPass; } }; TEST_REGISTER(GeometryTest) ref='#n391'>391</a> <a id='n392' href='#n392'>392</a> <a id='n393' href='#n393'>393</a> <a id='n394' href='#n394'>394</a> <a id='n395' href='#n395'>395</a> <a id='n396' href='#n396'>396</a> <a id='n397' href='#n397'>397</a> <a id='n398' href='#n398'>398</a> <a id='n399' href='#n399'>399</a> <a id='n400' href='#n400'>400</a> <a id='n401' href='#n401'>401</a> <a id='n402' href='#n402'>402</a> <a id='n403' href='#n403'>403</a> <a id='n404' href='#n404'>404</a> <a id='n405' href='#n405'>405</a> <a id='n406' href='#n406'>406</a> <a id='n407' href='#n407'>407</a> <a id='n408' href='#n408'>408</a> <a id='n409' href='#n409'>409</a> <a id='n410' href='#n410'>410</a> <a id='n411' href='#n411'>411</a> <a id='n412' href='#n412'>412</a> <a id='n413' href='#n413'>413</a> <a id='n414' href='#n414'>414</a> <a id='n415' href='#n415'>415</a> <a id='n416' href='#n416'>416</a> <a id='n417' href='#n417'>417</a> <a id='n418' href='#n418'>418</a> <a id='n419' href='#n419'>419</a> <a id='n420' href='#n420'>420</a> <a id='n421' href='#n421'>421</a> <a id='n422' href='#n422'>422</a> <a id='n423' href='#n423'>423</a> <a id='n424' href='#n424'>424</a> <a id='n425' href='#n425'>425</a> <a id='n426' href='#n426'>426</a> <a id='n427' href='#n427'>427</a> <a id='n428' href='#n428'>428</a> <a id='n429' href='#n429'>429</a> <a id='n430' href='#n430'>430</a> <a id='n431' href='#n431'>431</a> <a id='n432' href='#n432'>432</a> <a id='n433' href='#n433'>433</a> <a id='n434' href='#n434'>434</a> <a id='n435' href='#n435'>435</a> <a id='n436' href='#n436'>436</a> <a id='n437' href='#n437'>437</a> <a id='n438' href='#n438'>438</a> <a id='n439' href='#n439'>439</a> <a id='n440' href='#n440'>440</a> <a id='n441' href='#n441'>441</a> <a id='n442' href='#n442'>442</a> <a id='n443' href='#n443'>443</a> <a id='n444' href='#n444'>444</a> <a id='n445' href='#n445'>445</a> <a id='n446' href='#n446'>446</a> <a id='n447' href='#n447'>447</a> <a id='n448' href='#n448'>448</a> <a id='n449' href='#n449'>449</a> <a id='n450' href='#n450'>450</a> <a id='n451' href='#n451'>451</a> <a id='n452' href='#n452'>452</a> <a id='n453' href='#n453'>453</a> <a id='n454' href='#n454'>454</a> <a id='n455' href='#n455'>455</a> <a id='n456' href='#n456'>456</a> <a id='n457' href='#n457'>457</a> <a id='n458' href='#n458'>458</a> <a id='n459' href='#n459'>459</a> <a id='n460' href='#n460'>460</a> <a id='n461' href='#n461'>461</a> <a id='n462' href='#n462'>462</a> <a id='n463' href='#n463'>463</a> <a id='n464' href='#n464'>464</a> <a id='n465' href='#n465'>465</a> <a id='n466' href='#n466'>466</a> <a id='n467' href='#n467'>467</a> <a id='n468' href='#n468'>468</a> <a id='n469' href='#n469'>469</a> <a id='n470' href='#n470'>470</a> <a id='n471' href='#n471'>471</a> <a id='n472' href='#n472'>472</a> <a id='n473' href='#n473'>473</a> <a id='n474' href='#n474'>474</a> <a id='n475' href='#n475'>475</a> <a id='n476' href='#n476'>476</a> <a id='n477' href='#n477'>477</a> <a id='n478' href='#n478'>478</a> <a id='n479' href='#n479'>479</a> <a id='n480' href='#n480'>480</a> <a id='n481' href='#n481'>481</a> <a id='n482' href='#n482'>482</a> <a id='n483' href='#n483'>483</a> <a id='n484' href='#n484'>484</a> <a id='n485' href='#n485'>485</a> <a id='n486' href='#n486'>486</a> <a id='n487' href='#n487'>487</a> <a id='n488' href='#n488'>488</a> <a id='n489' href='#n489'>489</a> <a id='n490' href='#n490'>490</a> <a id='n491' href='#n491'>491</a> <a id='n492' href='#n492'>492</a> <a id='n493' href='#n493'>493</a> <a id='n494' href='#n494'>494</a> <a id='n495' href='#n495'>495</a> <a id='n496' href='#n496'>496</a> <a id='n497' href='#n497'>497</a> <a id='n498' href='#n498'>498</a> <a id='n499' href='#n499'>499</a> <a id='n500' href='#n500'>500</a> <a id='n501' href='#n501'>501</a> <a id='n502' href='#n502'>502</a> <a id='n503' href='#n503'>503</a> <a id='n504' href='#n504'>504</a> <a id='n505' href='#n505'>505</a> <a id='n506' href='#n506'>506</a> <a id='n507' href='#n507'>507</a> <a id='n508' href='#n508'>508</a> <a id='n509' href='#n509'>509</a> <a id='n510' href='#n510'>510</a> <a id='n511' href='#n511'>511</a> <a id='n512' href='#n512'>512</a> <a id='n513' href='#n513'>513</a> <a id='n514' href='#n514'>514</a> <a id='n515' href='#n515'>515</a> <a id='n516' href='#n516'>516</a> <a id='n517' href='#n517'>517</a> <a id='n518' href='#n518'>518</a> <a id='n519' href='#n519'>519</a> <a id='n520' href='#n520'>520</a> <a id='n521' href='#n521'>521</a> <a id='n522' href='#n522'>522</a> <a id='n523' href='#n523'>523</a> <a id='n524' href='#n524'>524</a> <a id='n525' href='#n525'>525</a> <a id='n526' href='#n526'>526</a> <a id='n527' href='#n527'>527</a> <a id='n528' href='#n528'>528</a> <a id='n529' href='#n529'>529</a> <a id='n530' href='#n530'>530</a> <a id='n531' href='#n531'>531</a> <a id='n532' href='#n532'>532</a> <a id='n533' href='#n533'>533</a> <a id='n534' href='#n534'>534</a> <a id='n535' href='#n535'>535</a> <a id='n536' href='#n536'>536</a> <a id='n537' href='#n537'>537</a> <a id='n538' href='#n538'>538</a> <a id='n539' href='#n539'>539</a> <a id='n540' href='#n540'>540</a> <a id='n541' href='#n541'>541</a> <a id='n542' href='#n542'>542</a> <a id='n543' href='#n543'>543</a> <a id='n544' href='#n544'>544</a> <a id='n545' href='#n545'>545</a> <a id='n546' href='#n546'>546</a> <a id='n547' href='#n547'>547</a> <a id='n548' href='#n548'>548</a> <a id='n549' href='#n549'>549</a> <a id='n550' href='#n550'>550</a> <a id='n551' href='#n551'>551</a> <a id='n552' href='#n552'>552</a> <a id='n553' href='#n553'>553</a> <a id='n554' href='#n554'>554</a> <a id='n555' href='#n555'>555</a> <a id='n556' href='#n556'>556</a> <a id='n557' href='#n557'>557</a> <a id='n558' href='#n558'>558</a> <a id='n559' href='#n559'>559</a> <a id='n560' href='#n560'>560</a> <a id='n561' href='#n561'>561</a> <a id='n562' href='#n562'>562</a> <a id='n563' href='#n563'>563</a> <a id='n564' href='#n564'>564</a> <a id='n565' href='#n565'>565</a> <a id='n566' href='#n566'>566</a> <a id='n567' href='#n567'>567</a> <a id='n568' href='#n568'>568</a> <a id='n569' href='#n569'>569</a> <a id='n570' href='#n570'>570</a> <a id='n571' href='#n571'>571</a> <a id='n572' href='#n572'>572</a> <a id='n573' href='#n573'>573</a> <a id='n574' href='#n574'>574</a> <a id='n575' href='#n575'>575</a> <a id='n576' href='#n576'>576</a> <a id='n577' href='#n577'>577</a> <a id='n578' href='#n578'>578</a> <a id='n579' href='#n579'>579</a> <a id='n580' href='#n580'>580</a> <a id='n581' href='#n581'>581</a> <a id='n582' href='#n582'>582</a> <a id='n583' href='#n583'>583</a> <a id='n584' href='#n584'>584</a> <a id='n585' href='#n585'>585</a> <a id='n586' href='#n586'>586</a> <a id='n587' href='#n587'>587</a> <a id='n588' href='#n588'>588</a> <a id='n589' href='#n589'>589</a> <a id='n590' href='#n590'>590</a> <a id='n591' href='#n591'>591</a> <a id='n592' href='#n592'>592</a> <a id='n593' href='#n593'>593</a> <a id='n594' href='#n594'>594</a> <a id='n595' href='#n595'>595</a> <a id='n596' href='#n596'>596</a> <a id='n597' href='#n597'>597</a> <a id='n598' href='#n598'>598</a> <a id='n599' href='#n599'>599</a> <a id='n600' href='#n600'>600</a> <a id='n601' href='#n601'>601</a> <a id='n602' href='#n602'>602</a> <a id='n603' href='#n603'>603</a> <a id='n604' href='#n604'>604</a> <a id='n605' href='#n605'>605</a> <a id='n606' href='#n606'>606</a> <a id='n607' href='#n607'>607</a> <a id='n608' href='#n608'>608</a> <a id='n609' href='#n609'>609</a> <a id='n610' href='#n610'>610</a> <a id='n611' href='#n611'>611</a> <a id='n612' href='#n612'>612</a> <a id='n613' href='#n613'>613</a> <a id='n614' href='#n614'>614</a> <a id='n615' href='#n615'>615</a> <a id='n616' href='#n616'>616</a> <a id='n617' href='#n617'>617</a> <a id='n618' href='#n618'>618</a> <a id='n619' href='#n619'>619</a> <a id='n620' href='#n620'>620</a> <a id='n621' href='#n621'>621</a> <a id='n622' href='#n622'>622</a> <a id='n623' href='#n623'>623</a> <a id='n624' href='#n624'>624</a> <a id='n625' href='#n625'>625</a> <a id='n626' href='#n626'>626</a> <a id='n627' href='#n627'>627</a> <a id='n628' href='#n628'>628</a> <a id='n629' href='#n629'>629</a> <a id='n630' href='#n630'>630</a> <a id='n631' href='#n631'>631</a> <a id='n632' href='#n632'>632</a> <a id='n633' href='#n633'>633</a> <a id='n634' href='#n634'>634</a> <a id='n635' href='#n635'>635</a> <a id='n636' href='#n636'>636</a> <a id='n637' href='#n637'>637</a> <a id='n638' href='#n638'>638</a> <a id='n639' href='#n639'>639</a> <a id='n640' href='#n640'>640</a> <a id='n641' href='#n641'>641</a> <a id='n642' href='#n642'>642</a> <a id='n643' href='#n643'>643</a> <a id='n644' href='#n644'>644</a> <a id='n645' href='#n645'>645</a> <a id='n646' href='#n646'>646</a> <a id='n647' href='#n647'>647</a> <a id='n648' href='#n648'>648</a> <a id='n649' href='#n649'>649</a> <a id='n650' href='#n650'>650</a> <a id='n651' href='#n651'>651</a> <a id='n652' href='#n652'>652</a> <a id='n653' href='#n653'>653</a> <a id='n654' href='#n654'>654</a> <a id='n655' href='#n655'>655</a> <a id='n656' href='#n656'>656</a> <a id='n657' href='#n657'>657</a> <a id='n658' href='#n658'>658</a> <a id='n659' href='#n659'>659</a> <a id='n660' href='#n660'>660</a> <a id='n661' href='#n661'>661</a> <a id='n662' href='#n662'>662</a> <a id='n663' href='#n663'>663</a> <a id='n664' href='#n664'>664</a> <a id='n665' href='#n665'>665</a> <a id='n666' href='#n666'>666</a> <a id='n667' href='#n667'>667</a> <a id='n668' href='#n668'>668</a> <a id='n669' href='#n669'>669</a> <a id='n670' href='#n670'>670</a> <a id='n671' href='#n671'>671</a> <a id='n672' href='#n672'>672</a> <a id='n673' href='#n673'>673</a> <a id='n674' href='#n674'>674</a> <a id='n675' href='#n675'>675</a> <a id='n676' href='#n676'>676</a> <a id='n677' href='#n677'>677</a> <a id='n678' href='#n678'>678</a> <a id='n679' href='#n679'>679</a> <a id='n680' href='#n680'>680</a> <a id='n681' href='#n681'>681</a> <a id='n682' href='#n682'>682</a> <a id='n683' href='#n683'>683</a> <a id='n684' href='#n684'>684</a> <a id='n685' href='#n685'>685</a> <a id='n686' href='#n686'>686</a> <a id='n687' href='#n687'>687</a> <a id='n688' href='#n688'>688</a> <a id='n689' href='#n689'>689</a> <a id='n690' href='#n690'>690</a> <a id='n691' href='#n691'>691</a> <a id='n692' href='#n692'>692</a> <a id='n693' href='#n693'>693</a> <a id='n694' href='#n694'>694</a> <a id='n695' href='#n695'>695</a> <a id='n696' href='#n696'>696</a> <a id='n697' href='#n697'>697</a> <a id='n698' href='#n698'>698</a> <a id='n699' href='#n699'>699</a> <a id='n700' href='#n700'>700</a> <a id='n701' href='#n701'>701</a> <a id='n702' href='#n702'>702</a> <a id='n703' href='#n703'>703</a> <a id='n704' href='#n704'>704</a> <a id='n705' href='#n705'>705</a> <a id='n706' href='#n706'>706</a> <a id='n707' href='#n707'>707</a> <a id='n708' href='#n708'>708</a> <a id='n709' href='#n709'>709</a> <a id='n710' href='#n710'>710</a> <a id='n711' href='#n711'>711</a> <a id='n712' href='#n712'>712</a> <a id='n713' href='#n713'>713</a> <a id='n714' href='#n714'>714</a> <a id='n715' href='#n715'>715</a> <a id='n716' href='#n716'>716</a> <a id='n717' href='#n717'>717</a> <a id='n718' href='#n718'>718</a> <a id='n719' href='#n719'>719</a> <a id='n720' href='#n720'>720</a> <a id='n721' href='#n721'>721</a> <a id='n722' href='#n722'>722</a> <a id='n723' href='#n723'>723</a> <a id='n724' href='#n724'>724</a> <a id='n725' href='#n725'>725</a> <a id='n726' href='#n726'>726</a> <a id='n727' href='#n727'>727</a> <a id='n728' href='#n728'>728</a> <a id='n729' href='#n729'>729</a> <a id='n730' href='#n730'>730</a> <a id='n731' href='#n731'>731</a> <a id='n732' href='#n732'>732</a> <a id='n733' href='#n733'>733</a> <a id='n734' href='#n734'>734</a> <a id='n735' href='#n735'>735</a> <a id='n736' href='#n736'>736</a> <a id='n737' href='#n737'>737</a> <a id='n738' href='#n738'>738</a> <a id='n739' href='#n739'>739</a> <a id='n740' href='#n740'>740</a> <a id='n741' href='#n741'>741</a> <a id='n742' href='#n742'>742</a> <a id='n743' href='#n743'>743</a> <a id='n744' href='#n744'>744</a> <a id='n745' href='#n745'>745</a> <a id='n746' href='#n746'>746</a> <a id='n747' href='#n747'>747</a> <a id='n748' href='#n748'>748</a> <a id='n749' href='#n749'>749</a> <a id='n750' href='#n750'>750</a> <a id='n751' href='#n751'>751</a> <a id='n752' href='#n752'>752</a> <a id='n753' href='#n753'>753</a> <a id='n754' href='#n754'>754</a> <a id='n755' href='#n755'>755</a> <a id='n756' href='#n756'>756</a> <a id='n757' href='#n757'>757</a> <a id='n758' href='#n758'>758</a> <a id='n759' href='#n759'>759</a> <a id='n760' href='#n760'>760</a> <a id='n761' href='#n761'>761</a> <a id='n762' href='#n762'>762</a> <a id='n763' href='#n763'>763</a> <a id='n764' href='#n764'>764</a> <a id='n765' href='#n765'>765</a> <a id='n766' href='#n766'>766</a> <a id='n767' href='#n767'>767</a> <a id='n768' href='#n768'>768</a> <a id='n769' href='#n769'>769</a> <a id='n770' href='#n770'>770</a> <a id='n771' href='#n771'>771</a> <a id='n772' href='#n772'>772</a> <a id='n773' href='#n773'>773</a> <a id='n774' href='#n774'>774</a> <a id='n775' href='#n775'>775</a> <a id='n776' href='#n776'>776</a> <a id='n777' href='#n777'>777</a> <a id='n778' href='#n778'>778</a> <a id='n779' href='#n779'>779</a> <a id='n780' href='#n780'>780</a> <a id='n781' href='#n781'>781</a> <a id='n782' href='#n782'>782</a> <a id='n783' href='#n783'>783</a> <a id='n784' href='#n784'>784</a> <a id='n785' href='#n785'>785</a> <a id='n786' href='#n786'>786</a> <a id='n787' href='#n787'>787</a> <a id='n788' href='#n788'>788</a> <a id='n789' href='#n789'>789</a> <a id='n790' href='#n790'>790</a> </pre></td> <td class='lines'><pre><code><span class="hl com">/* SPDX-License-Identifier: GPL-2.0-or-later */</span> <span class="hl com">/*</span> <span class="hl com"> * Copyright (C) 2019, Google Inc.</span> <span class="hl com"> *</span> <span class="hl com"> * main_window.cpp - qcam - Main application window</span> <span class="hl com"> */</span> <span class="hl ppc">#include</span> <span class="hl pps">"main_window.h"</span><span class="hl ppc"></span> <span class="hl ppc">#include <iomanip></span> <span class="hl ppc">#include <string></span> <span class="hl ppc">#include <sys/mman.h></span> <span class="hl ppc">#include <QComboBox></span> <span class="hl ppc">#include <QCoreApplication></span> <span class="hl ppc">#include <QFileDialog></span> <span class="hl ppc">#include <QImage></span> <span class="hl ppc">#include <QImageWriter></span> <span class="hl ppc">#include <QInputDialog></span> <span class="hl ppc">#include <QMutexLocker></span> <span class="hl ppc">#include <QStandardPaths></span> <span class="hl ppc">#include <QTimer></span> <span class="hl ppc">#include <QToolBar></span> <span class="hl ppc">#include <QToolButton></span> <span class="hl ppc">#include <QtDebug></span> <span class="hl ppc">#include <libcamera/camera_manager.h></span> <span class="hl ppc">#include <libcamera/version.h></span> <span class="hl ppc">#include</span> <span class="hl pps">"dng_writer.h"</span><span class="hl ppc"></span> <span class="hl ppc">#ifndef QT_NO_OPENGL</span> <span class="hl ppc">#include</span> <span class="hl pps">"viewfinder_gl.h"</span><span class="hl ppc"></span> <span class="hl ppc">#endif</span> <span class="hl ppc">#include</span> <span class="hl pps">"viewfinder_qt.h"</span><span class="hl ppc"></span> <span class="hl kwa">using namespace</span> libcamera<span class="hl opt">;</span> <span class="hl ppc">#if QT_VERSION < QT_VERSION_CHECK(5, 14, 0)</span> <span class="hl com">/*</span> <span class="hl com"> * Qt::fixed was introduced in v5.14, and ::fixed deprecated in v5.15. Allow</span> <span class="hl com"> * usage of Qt::fixed unconditionally.</span> <span class="hl com"> */</span> <span class="hl kwa">namespace</span> Qt <span class="hl opt">{</span> <span class="hl kwc">constexpr auto</span> fixed <span class="hl opt">= ::</span>fixed<span class="hl opt">;</span> <span class="hl opt">}</span> <span class="hl com">/* namespace Qt */</span> <span class="hl ppc">#endif</span> <span class="hl com">/**</span> <span class="hl com"> * \brief Custom QEvent to signal capture completion</span> <span class="hl com"> */</span> <span class="hl kwc">class</span> CaptureEvent <span class="hl opt">:</span> <span class="hl kwc">public</span> QEvent <span class="hl opt">{</span> <span class="hl kwc">public</span><span class="hl opt">:</span> <span class="hl kwd">CaptureEvent</span><span class="hl opt">()</span> <span class="hl opt">:</span> <span class="hl kwd">QEvent</span><span class="hl opt">(</span><span class="hl kwd">type</span><span class="hl opt">())</span> <span class="hl opt">{</span> <span class="hl opt">}</span> <span class="hl kwb">static</span> Type <span class="hl kwd">type</span><span class="hl opt">()</span> <span class="hl opt">{</span> <span class="hl kwb">static int</span> type <span class="hl opt">=</span> <span class="hl kwc">QEvent</span><span class="hl opt">::</span><span class="hl kwd">registerEventType</span><span class="hl opt">();</span> <span class="hl kwa">return static_cast</span><span class="hl opt"><</span>Type<span class="hl opt">>(</span>type<span class="hl opt">);</span> <span class="hl opt">}</span> <span class="hl opt">};</span> <span class="hl com">/**</span> <span class="hl com"> * \brief Custom QEvent to signal hotplug or unplug</span> <span class="hl com"> */</span> <span class="hl kwc">class</span> HotplugEvent <span class="hl opt">:</span> <span class="hl kwc">public</span> QEvent <span class="hl opt">{</span> <span class="hl kwc">public</span><span class="hl opt">:</span> <span class="hl kwb">enum</span> PlugEvent <span class="hl opt">{</span> HotPlug<span class="hl opt">,</span> HotUnplug <span class="hl opt">};</span> <span class="hl kwd">HotplugEvent</span><span class="hl opt">(</span><span class="hl kwc">std</span><span class="hl opt">::</span>shared_ptr<span class="hl opt"><</span>Camera<span class="hl opt">></span> camera<span class="hl opt">,</span> PlugEvent event<span class="hl opt">)</span> <span class="hl opt">:</span> <span class="hl kwd">QEvent</span><span class="hl opt">(</span><span class="hl kwd">type</span><span class="hl opt">()),</span> <span class="hl kwd">camera_</span><span class="hl opt">(</span><span class="hl kwc">std</span><span class="hl opt">::</span><span class="hl kwd">move</span><span class="hl opt">(</span>camera<span class="hl opt">)),</span> <span class="hl kwd">plugEvent_</span><span class="hl opt">(</span>event<span class="hl opt">)</span> <span class="hl opt">{</span> <span class="hl opt">}</span> <span class="hl kwb">static</span> Type <span class="hl kwd">type</span><span class="hl opt">()</span> <span class="hl opt">{</span> <span class="hl kwb">static int</span> type <span class="hl opt">=</span> <span class="hl kwc">QEvent</span><span class="hl opt">::</span><span class="hl kwd">registerEventType</span><span class="hl opt">();</span> <span class="hl kwa">return static_cast</span><span class="hl opt"><</span>Type<span class="hl opt">>(</span>type<span class="hl opt">);</span> <span class="hl opt">}</span> PlugEvent <span class="hl kwd">hotplugEvent</span><span class="hl opt">()</span> <span class="hl kwb">const</span> <span class="hl opt">{</span> <span class="hl kwa">return</span> plugEvent_<span class="hl opt">; }</span> Camera <span class="hl opt">*</span><span class="hl kwd">camera</span><span class="hl opt">()</span> <span class="hl kwb">const</span> <span class="hl opt">{</span> <span class="hl kwa">return</span> camera_<span class="hl opt">.</span><span class="hl kwd">get</span><span class="hl opt">(); }</span> <span class="hl kwc">private</span><span class="hl opt">:</span> <span class="hl kwc">std</span><span class="hl opt">::</span>shared_ptr<span class="hl opt"><</span>Camera<span class="hl opt">></span> camera_<span class="hl opt">;</span> PlugEvent plugEvent_<span class="hl opt">;</span> <span class="hl opt">};</span> <span class="hl kwc">MainWindow</span><span class="hl opt">::</span><span class="hl kwd">MainWindow</span><span class="hl opt">(</span>CameraManager <span class="hl opt">*</span>cm<span class="hl opt">,</span> <span class="hl kwb">const</span> <span class="hl kwc">OptionsParser</span><span class="hl opt">::</span>Options <span class="hl opt">&</span>options<span class="hl opt">)</span> <span class="hl opt">:</span> <span class="hl kwd">saveRaw_</span><span class="hl opt">(</span><span class="hl kwc">nullptr</span><span class="hl opt">),</span> <span class="hl kwd">options_</span><span class="hl opt">(</span>options<span class="hl opt">),</span> <span class="hl kwd">cm_</span><span class="hl opt">(</span>cm<span class="hl opt">),</span> <span class="hl kwd">allocator_</span><span class="hl opt">(</span><span class="hl kwc">nullptr</span><span class="hl opt">),</span> <span class="hl kwd">isCapturing_</span><span class="hl opt">(</span><span class="hl kwa">false</span><span class="hl opt">),</span> <span class="hl kwd">captureRaw_</span><span class="hl opt">(</span><span class="hl kwa">false</span><span class="hl opt">)</span> <span class="hl opt">{</span> <span class="hl kwb">int</span> ret<span class="hl opt">;</span> <span class="hl com">/*</span> <span class="hl com"> * Initialize the UI: Create the toolbar, set the window title and</span> <span class="hl com"> * create the viewfinder widget.</span> <span class="hl com"> */</span> <span class="hl kwd">createToolbars</span><span class="hl opt">();</span> title_ <span class="hl opt">=</span> <span class="hl str">"QCam "</span> <span class="hl opt">+</span> <span class="hl kwc">QString</span><span class="hl opt">::</span><span class="hl kwd">fromStdString</span><span class="hl opt">(</span><span class="hl kwc">CameraManager</span><span class="hl opt">::</span><span class="hl kwd">version</span><span class="hl opt">());</span> <span class="hl kwd">setWindowTitle</span><span class="hl opt">(</span>title_<span class="hl opt">);</span> <span class="hl kwd">connect</span><span class="hl opt">(&</span>titleTimer_<span class="hl opt">,</span> <span class="hl kwd">SIGNAL</span><span class="hl opt">(</span><span class="hl kwd">timeout</span><span class="hl opt">()),</span> <span class="hl kwa">this</span><span class="hl opt">,</span> <span class="hl kwd">SLOT</span><span class="hl opt">(</span><span class="hl kwd">updateTitle</span><span class="hl opt">()));</span> <span class="hl com">/* Renderer type Qt or GLES, select Qt by default. */</span> <span class="hl kwc">std</span><span class="hl opt">::</span>string renderType <span class="hl opt">=</span> <span class="hl str">"qt"</span><span class="hl opt">;</span> <span class="hl kwa">if</span> <span class="hl opt">(</span>options_<span class="hl opt">.</span><span class="hl kwd">isSet</span><span class="hl opt">(</span>OptRenderer<span class="hl opt">))</span> renderType <span class="hl opt">=</span> options_<span class="hl opt">[</span>OptRenderer<span class="hl opt">].</span><span class="hl kwd">toString</span><span class="hl opt">();</span> <span class="hl kwa">if</span> <span class="hl opt">(</span>renderType <span class="hl opt">==</span> <span class="hl str">"qt"</span><span class="hl opt">) {</span> ViewFinderQt <span class="hl opt">*</span>viewfinder <span class="hl opt">=</span> <span class="hl kwa">new</span> <span class="hl kwd">ViewFinderQt</span><span class="hl opt">(</span><span class="hl kwa">this</span><span class="hl opt">);</span> <span class="hl kwd">connect</span><span class="hl opt">(</span>viewfinder<span class="hl opt">, &</span><span class="hl kwc">ViewFinderQt</span><span class="hl opt">::</span>renderComplete<span class="hl opt">,</span> <span class="hl kwa">this</span><span class="hl opt">, &</span><span class="hl kwc">MainWindow</span><span class="hl opt">::</span>queueRequest<span class="hl opt">);</span> viewfinder_ <span class="hl opt">=</span> viewfinder<span class="hl opt">;</span> <span class="hl kwd">setCentralWidget</span><span class="hl opt">(</span>viewfinder<span class="hl opt">);</span> <span class="hl ppc">#ifndef QT_NO_OPENGL</span> <span class="hl opt">}</span> <span class="hl kwa">else if</span> <span class="hl opt">(</span>renderType <span class="hl opt">==</span> <span class="hl str">"gles"</span><span class="hl opt">) {</span> ViewFinderGL <span class="hl opt">*</span>viewfinder <span class="hl opt">=</span> <span class="hl kwa">new</span> <span class="hl kwd">ViewFinderGL</span><span class="hl opt">(</span><span class="hl kwa">this</span><span class="hl opt">);</span> <span class="hl kwd">connect</span><span class="hl opt">(</span>viewfinder<span class="hl opt">, &</span><span class="hl kwc">ViewFinderGL</span><span class="hl opt">::</span>renderComplete<span class="hl opt">,</span> <span class="hl kwa">this</span><span class="hl opt">, &</span><span class="hl kwc">MainWindow</span><span class="hl opt">::</span>queueRequest<span class="hl opt">);</span> viewfinder_ <span class="hl opt">=</span> viewfinder<span class="hl opt">;</span> <span class="hl kwd">setCentralWidget</span><span class="hl opt">(</span>viewfinder<span class="hl opt">);</span> <span class="hl ppc">#endif</span> <span class="hl opt">}</span> <span class="hl kwa">else</span> <span class="hl opt">{</span> <span class="hl kwd">qWarning</span><span class="hl opt">() <<</span> <span class="hl str">"Invalid render type"</span> <span class="hl opt"><<</span> <span class="hl kwc">QString</span><span class="hl opt">::</span><span class="hl kwd">fromStdString</span><span class="hl opt">(</span>renderType<span class="hl opt">);</span> <span class="hl kwd">quit</span><span class="hl opt">();</span> <span class="hl kwa">return</span><span class="hl opt">;</span> <span class="hl opt">}</span> <span class="hl kwd">adjustSize</span><span class="hl opt">();</span> <span class="hl com">/* Hotplug/unplug support */</span> cm_<span class="hl opt">-></span>cameraAdded<span class="hl opt">.</span><span class="hl kwd">connect</span><span class="hl opt">(</span><span class="hl kwa">this</span><span class="hl opt">, &</span><span class="hl kwc">MainWindow</span><span class="hl opt">::</span>addCamera<span class="hl opt">);</span> cm_<span class="hl opt">-></span>cameraRemoved<span class="hl opt">.</span><span class="hl kwd">connect</span><span class="hl opt">(</span><span class="hl kwa">this</span><span class="hl opt">, &</span><span class="hl kwc">MainWindow</span><span class="hl opt">::</span>removeCamera<span class="hl opt">);</span> <span class="hl com">/* Open the camera and start capture. */</span> ret <span class="hl opt">=</span> <span class="hl kwd">openCamera</span><span class="hl opt">();</span> <span class="hl kwa">if</span> <span class="hl opt">(</span>ret <span class="hl opt"><</span> <span class="hl num">0</span><span class="hl opt">) {</span> <span class="hl kwd">quit</span><span class="hl opt">();</span> <span class="hl kwa">return</span><span class="hl opt">;</span> <span class="hl opt">}</span> startStopAction_<span class="hl opt">-></span><span class="hl kwd">setChecked</span><span class="hl opt">(</span><span class="hl kwa">true</span><span class="hl opt">);</span> <span class="hl opt">}</span> <span class="hl kwc">MainWindow</span><span class="hl opt">::~</span><span class="hl kwd">MainWindow</span><span class="hl opt">()</span> <span class="hl opt">{</span> <span class="hl kwa">if</span> <span class="hl opt">(</span>camera_<span class="hl opt">) {</span> <span class="hl kwd">stopCapture</span><span class="hl opt">();</span> camera_<span class="hl opt">-></span><span class="hl kwd">release</span><span class="hl opt">();</span> camera_<span class="hl opt">.</span><span class="hl kwd">reset</span><span class="hl opt">();</span> <span class="hl opt">}</span> <span class="hl opt">}</span> <span class="hl kwb">bool</span> <span class="hl kwc">MainWindow</span><span class="hl opt">::</span><span class="hl kwd">event</span><span class="hl opt">(</span>QEvent <span class="hl opt">*</span>e<span class="hl opt">)</span> <span class="hl opt">{</span> <span class="hl kwa">if</span> <span class="hl opt">(</span>e<span class="hl opt">-></span><span class="hl kwd">type</span><span class="hl opt">() ==</span> <span class="hl kwc">CaptureEvent</span><span class="hl opt">::</span><span class="hl kwd">type</span><span class="hl opt">()) {</span> <span class="hl kwd">processCapture</span><span class="hl opt">();</span> <span class="hl kwa">return true</span><span class="hl opt">;</span> <span class="hl opt">}</span> <span class="hl kwa">else if</span> <span class="hl opt">(</span>e<span class="hl opt">-></span><span class="hl kwd">type</span><span class="hl opt">() ==</span> <span class="hl kwc">HotplugEvent</span><span class="hl opt">::</span><span class="hl kwd">type</span><span class="hl opt">()) {</span> <span class="hl kwd">processHotplug</span><span class="hl opt">(</span><span class="hl kwa">static_cast</span><span class="hl opt"><</span>HotplugEvent <span class="hl opt">*>(</span>e<span class="hl opt">));</span> <span class="hl kwa">return true</span><span class="hl opt">;</span> <span class="hl opt">}</span> <span class="hl kwa">return</span> <span class="hl kwc">QMainWindow</span><span class="hl opt">::</span><span class="hl kwd">event</span><span class="hl opt">(</span>e<span class="hl opt">);</span> <span class="hl opt">}</span> <span class="hl kwb">int</span> <span class="hl kwc">MainWindow</span><span class="hl opt">::</span><span class="hl kwd">createToolbars</span><span class="hl opt">()</span> <span class="hl opt">{</span> QAction <span class="hl opt">*</span>action<span class="hl opt">;</span> toolbar_ <span class="hl opt">=</span> <span class="hl kwd">addToolBar</span><span class="hl opt">(</span><span class="hl str">"Main"</span><span class="hl opt">);</span> <span class="hl com">/* Disable right click context menu. */</span> toolbar_<span class="hl opt">-></span><span class="hl kwd">setContextMenuPolicy</span><span class="hl opt">(</span><span class="hl kwc">Qt</span><span class="hl opt">::</span>PreventContextMenu<span class="hl opt">);</span> <span class="hl com">/* Quit action. */</span> action <span class="hl opt">=</span> toolbar_<span class="hl opt">-></span><span class="hl kwd">addAction</span><span class="hl opt">(</span><span class="hl kwc">QIcon</span><span class="hl opt">::</span><span class="hl kwd">fromTheme</span><span class="hl opt">(</span><span class="hl str">"application-exit"</span><span class="hl opt">,</span> <span class="hl kwd">QIcon</span><span class="hl opt">(</span><span class="hl str">":x-circle.svg"</span><span class="hl opt">)),</span> <span class="hl str">"Quit"</span><span class="hl opt">);</span> action<span class="hl opt">-></span><span class="hl kwd">setShortcut</span><span class="hl opt">(</span><span class="hl kwc">Qt</span><span class="hl opt">::</span>CTRL <span class="hl opt">|</span> <span class="hl kwc">Qt</span><span class="hl opt">::</span>Key_Q<span class="hl opt">);</span> <span class="hl kwd">connect</span><span class="hl opt">(</span>action<span class="hl opt">, &</span><span class="hl kwc">QAction</span><span class="hl opt">::</span>triggered<span class="hl opt">,</span> <span class="hl kwa">this</span><span class="hl opt">, &</span><span class="hl kwc">MainWindow</span><span class="hl opt">::</span>quit<span class="hl opt">);</span> <span class="hl com">/* Camera selector. */</span> cameraCombo_ <span class="hl opt">=</span> <span class="hl kwa">new</span> <span class="hl kwd">QComboBox</span><span class="hl opt">();</span> <span class="hl kwd">connect</span><span class="hl opt">(</span>cameraCombo_<span class="hl opt">,</span> QOverload<span class="hl opt"><</span><span class="hl kwb">int</span><span class="hl opt">>::</span><span class="hl kwd">of</span><span class="hl opt">(&</span><span class="hl kwc">QComboBox</span><span class="hl opt">::</span>activated<span class="hl opt">),</span> <span class="hl kwa">this</span><span class="hl opt">, &</span><span class="hl kwc">MainWindow</span><span class="hl opt">::</span>switchCamera<span class="hl opt">);</span> <span class="hl kwa">for</span> <span class="hl opt">(</span><span class="hl kwb">const</span> <span class="hl kwc">std</span><span class="hl opt">::</span>shared_ptr<span class="hl opt"><</span>Camera<span class="hl opt">> &</span>cam <span class="hl opt">:</span> cm_<span class="hl opt">-></span><span class="hl kwd">cameras</span><span class="hl opt">())</span> cameraCombo_<span class="hl opt">-></span><span class="hl kwd">addItem</span><span class="hl opt">(</span><span class="hl kwc">QString</span><span class="hl opt">::</span><span class="hl kwd">fromStdString</span><span class="hl opt">(</span>cam<span class="hl opt">-></span><span class="hl kwd">id</span><span class="hl opt">()));</span> toolbar_<span class="hl opt">-></span><span class="hl kwd">addWidget</span><span class="hl opt">(</span>cameraCombo_<span class="hl opt">);</span> toolbar_<span class="hl opt">-></span><span class="hl kwd">addSeparator</span><span class="hl opt">();</span> <span class="hl com">/* Start/Stop action. */</span> iconPlay_ <span class="hl opt">=</span> <span class="hl kwc">QIcon</span><span class="hl opt">::</span><span class="hl kwd">fromTheme</span><span class="hl opt">(</span><span class="hl str">"media-playback-start"</span><span class="hl opt">,</span> <span class="hl kwd">QIcon</span><span class="hl opt">(</span><span class="hl str">":play-circle.svg"</span><span class="hl opt">));</span> iconStop_ <span class="hl opt">=</span> <span class="hl kwc">QIcon</span><span class="hl opt">::</span><span class="hl kwd">fromTheme</span><span class="hl opt">(</span><span class="hl str">"media-playback-stop"</span><span class="hl opt">,</span> <span class="hl kwd">QIcon</span><span class="hl opt">(</span><span class="hl str">":stop-circle.svg"</span><span class="hl opt">));</span> action <span class="hl opt">=</span> toolbar_<span class="hl opt">-></span><span class="hl kwd">addAction</span><span class="hl opt">(</span>iconPlay_<span class="hl opt">,</span> <span class="hl str">"Start Capture"</span><span class="hl opt">);</span> action<span class="hl opt">-></span><span class="hl kwd">setCheckable</span><span class="hl opt">(</span><span class="hl kwa">true</span><span class="hl opt">);</span> action<span class="hl opt">-></span><span class="hl kwd">setShortcut</span><span class="hl opt">(</span><span class="hl kwc">Qt</span><span class="hl opt">::</span>Key_Space<span class="hl opt">);</span> <span class="hl kwd">connect</span><span class="hl opt">(</span>action<span class="hl opt">, &</span><span class="hl kwc">QAction</span><span class="hl opt">::</span>toggled<span class="hl opt">,</span> <span class="hl kwa">this</span><span class="hl opt">, &</span><span class="hl kwc">MainWindow</span><span class="hl opt">::</span>toggleCapture<span class="hl opt">);</span> startStopAction_ <span class="hl opt">=</span> action<span class="hl opt">;</span> <span class="hl com">/* Save As... action. */</span> action <span class="hl opt">=</span> toolbar_<span class="hl opt">-></span><span class="hl kwd">addAction</span><span class="hl opt">(</span><span class="hl kwc">QIcon</span><span class="hl opt">::</span><span class="hl kwd">fromTheme</span><span class="hl opt">(</span><span class="hl str">"document-save-as"</span><span class="hl opt">,</span> <span class="hl kwd">QIcon</span><span class="hl opt">(</span><span class="hl str">":save.svg"</span><span class="hl opt">)),</span> <span class="hl str">"Save As..."</span><span class="hl opt">);</span> action<span class="hl opt">-></span><span class="hl kwd">setShortcut</span><span class="hl opt">(</span><span class="hl kwc">QKeySequence</span><span class="hl opt">::</span>SaveAs<span class="hl opt">);</span> <span class="hl kwd">connect</span><span class="hl opt">(</span>action<span class="hl opt">, &</span><span class="hl kwc">QAction</span><span class="hl opt">::</span>triggered<span class="hl opt">,</span> <span class="hl kwa">this</span><span class="hl opt">, &</span><span class="hl kwc">MainWindow</span><span class="hl opt">::</span>saveImageAs<span class="hl opt">);</span> <span class="hl ppc">#ifdef HAVE_DNG</span> <span class="hl com">/* Save Raw action. */</span> action <span class="hl opt">=</span> toolbar_<span class="hl opt">-></span><span class="hl kwd">addAction</span><span class="hl opt">(</span><span class="hl kwc">QIcon</span><span class="hl opt">::</span><span class="hl kwd">fromTheme</span><span class="hl opt">(</span><span class="hl str">"camera-photo"</span><span class="hl opt">,</span> <span class="hl kwd">QIcon</span><span class="hl opt">(</span><span class="hl str">":aperture.svg"</span><span class="hl opt">)),</span> <span class="hl str">"Save Raw"</span><span class="hl opt">);</span> action<span class="hl opt">-></span><span class="hl kwd">setEnabled</span><span class="hl opt">(</span><span class="hl kwa">false</span><span class="hl opt">);</span> <span class="hl kwd">connect</span><span class="hl opt">(</span>action<span class="hl opt">, &</span><span class="hl kwc">QAction</span><span class="hl opt">::</span>triggered<span class="hl opt">,</span> <span class="hl kwa">this</span><span class="hl opt">, &</span><span class="hl kwc">MainWindow</span><span class="hl opt">::</span>captureRaw<span class="hl opt">);</span> saveRaw_ <span class="hl opt">=</span> action<span class="hl opt">;</span> <span class="hl ppc">#endif</span> <span class="hl kwa">return</span> <span class="hl num">0</span><span class="hl opt">;</span> <span class="hl opt">}</span> <span class="hl kwb">void</span> <span class="hl kwc">MainWindow</span><span class="hl opt">::</span><span class="hl kwd">quit</span><span class="hl opt">()</span> <span class="hl opt">{</span> <span class="hl kwc">QTimer</span><span class="hl opt">::</span><span class="hl kwd">singleShot</span><span class="hl opt">(</span><span class="hl num">0</span><span class="hl opt">,</span> <span class="hl kwc">QCoreApplication</span><span class="hl opt">::</span><span class="hl kwd">instance</span><span class="hl opt">(),</span> <span class="hl opt">&</span><span class="hl kwc">QCoreApplication</span><span class="hl opt">::</span>quit<span class="hl opt">);</span> <span class="hl opt">}</span> <span class="hl kwb">void</span> <span class="hl kwc">MainWindow</span><span class="hl opt">::</span><span class="hl kwd">updateTitle</span><span class="hl opt">()</span> <span class="hl opt">{</span> <span class="hl com">/* Calculate the average frame rate over the last period. */</span> <span class="hl kwb">unsigned int</span> duration <span class="hl opt">=</span> frameRateInterval_<span class="hl opt">.</span><span class="hl kwd">elapsed</span><span class="hl opt">();</span> <span class="hl kwb">unsigned int</span> frames <span class="hl opt">=</span> framesCaptured_ <span class="hl opt">-</span> previousFrames_<span class="hl opt">;</span> <span class="hl kwb">double</span> fps <span class="hl opt">=</span> frames <span class="hl opt">*</span> <span class="hl num">1000.0</span> <span class="hl opt">/</span> duration<span class="hl opt">;</span> <span class="hl com">/* Restart counters. */</span> frameRateInterval_<span class="hl opt">.</span><span class="hl kwd">start</span><span class="hl opt">();</span> previousFrames_ <span class="hl opt">=</span> framesCaptured_<span class="hl opt">;</span> <span class="hl kwd">setWindowTitle</span><span class="hl opt">(</span>title_ <span class="hl opt">+</span> <span class="hl str">" : "</span> <span class="hl opt">+</span> <span class="hl kwc">QString</span><span class="hl opt">::</span><span class="hl kwd">number</span><span class="hl opt">(</span>fps<span class="hl opt">,</span> <span class="hl str">'f'</span><span class="hl opt">,</span> <span class="hl num">2</span><span class="hl opt">) +</span> <span class="hl str">" fps"</span><span class="hl opt">);</span> <span class="hl opt">}</span> <span class="hl com">/* -----------------------------------------------------------------------------</span> <span class="hl com"> * Camera Selection</span> <span class="hl com"> */</span> <span class="hl kwb">void</span> <span class="hl kwc">MainWindow</span><span class="hl opt">::</span><span class="hl kwd">switchCamera</span><span class="hl opt">(</span><span class="hl kwb">int</span> index<span class="hl opt">)</span> <span class="hl opt">{</span> <span class="hl com">/* Get and acquire the new camera. */</span> <span class="hl kwb">const</span> <span class="hl kwc">auto</span> <span class="hl opt">&</span>cameras <span class="hl opt">=</span> cm_<span class="hl opt">-></span><span class="hl kwd">cameras</span><span class="hl opt">();</span> <span class="hl kwa">if</span> <span class="hl opt">(</span><span class="hl kwa">static_cast</span><span class="hl opt"><</span><span class="hl kwb">unsigned int</span><span class="hl opt">>(</span>index<span class="hl opt">) >=</span> cameras<span class="hl opt">.</span><span class="hl kwd">size</span><span class="hl opt">())</span> <span class="hl kwa">return</span><span class="hl opt">;</span> <span class="hl kwb">const</span> <span class="hl kwc">std</span><span class="hl opt">::</span>shared_ptr<span class="hl opt"><</span>Camera<span class="hl opt">> &</span>cam <span class="hl opt">=</span> cameras<span class="hl opt">[</span>index<span class="hl opt">];</span> <span class="hl kwa">if</span> <span class="hl opt">(</span>cam<span class="hl opt">-></span><span class="hl kwd">acquire</span><span class="hl opt">()) {</span> <span class="hl kwd">qInfo</span><span class="hl opt">() <<</span> <span class="hl str">"Failed to acquire camera"</span> <span class="hl opt"><<</span> cam<span class="hl opt">-></span><span class="hl kwd">id</span><span class="hl opt">().</span><span class="hl kwd">c_str</span><span class="hl opt">();</span> <span class="hl kwa">return</span><span class="hl opt">;</span> <span class="hl opt">}</span> <span class="hl kwd">qInfo</span><span class="hl opt">() <<</span> <span class="hl str">"Switching to camera"</span> <span class="hl opt"><<</span> cam<span class="hl opt">-></span><span class="hl kwd">id</span><span class="hl opt">().</span><span class="hl kwd">c_str</span><span class="hl opt">();</span> <span class="hl com">/*</span> <span class="hl com"> * Stop the capture session, release the current camera, replace it with</span> <span class="hl com"> * the new camera and start a new capture session.</span> <span class="hl com"> */</span> startStopAction_<span class="hl opt">-></span><span class="hl kwd">setChecked</span><span class="hl opt">(</span><span class="hl kwa">false</span><span class="hl opt">);</span> camera_<span class="hl opt">-></span><span class="hl kwd">release</span><span class="hl opt">();</span> camera_ <span class="hl opt">=</span> cam<span class="hl opt">;</span> startStopAction_<span class="hl opt">-></span><span class="hl kwd">setChecked</span><span class="hl opt">(</span><span class="hl kwa">true</span><span class="hl opt">);</span> <span class="hl opt">}</span> <span class="hl kwc">std</span><span class="hl opt">::</span>string <span class="hl kwc">MainWindow</span><span class="hl opt">::</span><span class="hl kwd">chooseCamera</span><span class="hl opt">()</span> <span class="hl opt">{</span> QStringList cameras<span class="hl opt">;</span> <span class="hl kwb">bool</span> result<span class="hl opt">;</span> <span class="hl com">/* If only one camera is available, use it automatically. */</span> <span class="hl kwa">if</span> <span class="hl opt">(</span>cm_<span class="hl opt">-></span><span class="hl kwd">cameras</span><span class="hl opt">().</span><span class="hl kwd">size</span><span class="hl opt">() ==</span> <span class="hl num">1</span><span class="hl opt">)</span> <span class="hl kwa">return</span> cm_<span class="hl opt">-></span><span class="hl kwd">cameras</span><span class="hl opt">()[</span><span class="hl num">0</span><span class="hl opt">]-></span><span class="hl kwd">id</span><span class="hl opt">();</span> <span class="hl com">/* Present a dialog box to pick a camera. */</span> <span class="hl kwa">for</span> <span class="hl opt">(</span><span class="hl kwb">const</span> <span class="hl kwc">std</span><span class="hl opt">::</span>shared_ptr<span class="hl opt"><</span>Camera<span class="hl opt">> &</span>cam <span class="hl opt">:</span> cm_<span class="hl opt">-></span><span class="hl kwd">cameras</span><span class="hl opt">())</span> cameras<span class="hl opt">.</span><span class="hl kwd">append</span><span class="hl opt">(</span><span class="hl kwc">QString</span><span class="hl opt">::</span><span class="hl kwd">fromStdString</span><span class="hl opt">(</span>cam<span class="hl opt">-></span><span class="hl kwd">id</span><span class="hl opt">()));</span> QString id <span class="hl opt">=</span> <span class="hl kwc">QInputDialog</span><span class="hl opt">::</span><span class="hl kwd">getItem</span><span class="hl opt">(</span><span class="hl kwa">this</span><span class="hl opt">,</span> <span class="hl str">"Select Camera"</span><span class="hl opt">,</span> <span class="hl str">"Camera:"</span><span class="hl opt">,</span> cameras<span class="hl opt">,</span> <span class="hl num">0</span><span class="hl opt">,</span> <span class="hl kwa">false</span><span class="hl opt">, &</span>result<span class="hl opt">);</span> <span class="hl kwa">if</span> <span class="hl opt">(!</span>result<span class="hl opt">)</span> <span class="hl kwa">return</span> <span class="hl kwc">std</span><span class="hl opt">::</span><span class="hl kwd">string</span><span class="hl opt">();</span> <span class="hl kwa">return</span> id<span class="hl opt">.</span><span class="hl kwd">toStdString</span><span class="hl opt">();</span> <span class="hl opt">}</span> <span class="hl kwb">int</span> <span class="hl kwc">MainWindow</span><span class="hl opt">::</span><span class="hl kwd">openCamera</span><span class="hl opt">()</span> <span class="hl opt">{</span> <span class="hl kwc">std</span><span class="hl opt">::</span>string cameraName<span class="hl opt">;</span> <span class="hl com">/*</span> <span class="hl com"> * Use the camera specified on the command line, if any, or display the</span> <span class="hl com"> * camera selection dialog box otherwise.</span> <span class="hl com"> */</span> <span class="hl kwa">if</span> <span class="hl opt">(</span>options_<span class="hl opt">.</span><span class="hl kwd">isSet</span><span class="hl opt">(</span>OptCamera<span class="hl opt">))</span> cameraName <span class="hl opt">=</span> <span class="hl kwa">static_cast</span><span class="hl opt"><</span><span class="hl kwc">std</span><span class="hl opt">::</span>string<span class="hl opt">>(</span>options_<span class="hl opt">[</span>OptCamera<span class="hl opt">]);</span> <span class="hl kwa">else</span> cameraName <span class="hl opt">=</span> <span class="hl kwd">chooseCamera</span><span class="hl opt">();</span> <span class="hl kwa">if</span> <span class="hl opt">(</span>cameraName <span class="hl opt">==</span> <span class="hl str">""</span><span class="hl opt">)</span> <span class="hl kwa">return</span> <span class="hl opt">-</span>EINVAL<span class="hl opt">;</span> <span class="hl com">/* Get and acquire the camera. */</span> camera_ <span class="hl opt">=</span> cm_<span class="hl opt">-></span><span class="hl kwd">get</span><span class="hl opt">(</span>cameraName<span class="hl opt">);</span> <span class="hl kwa">if</span> <span class="hl opt">(!</span>camera_<span class="hl opt">) {</span> <span class="hl kwd">qInfo</span><span class="hl opt">() <<</span> <span class="hl str">"Camera"</span> <span class="hl opt"><<</span> cameraName<span class="hl opt">.</span><span class="hl kwd">c_str</span><span class="hl opt">() <<</span> <span class="hl str">"not found"</span><span class="hl opt">;</span> <span class="hl kwa">return</span> <span class="hl opt">-</span>ENODEV<span class="hl opt">;</span> <span class="hl opt">}</span> <span class="hl kwa">if</span> <span class="hl opt">(</span>camera_<span class="hl opt">-></span><span class="hl kwd">acquire</span><span class="hl opt">()) {</span> <span class="hl kwd">qInfo</span><span class="hl opt">() <<</span> <span class="hl str">"Failed to acquire camera"</span><span class="hl opt">;</span> camera_<span class="hl opt">.</span><span class="hl kwd">reset</span><span class="hl opt">();</span> <span class="hl kwa">return</span> <span class="hl opt">-</span>EBUSY<span class="hl opt">;</span> <span class="hl opt">}</span> <span class="hl com">/* Set the combo-box entry with the currently selected Camera. */</span> cameraCombo_<span class="hl opt">-></span><span class="hl kwd">setCurrentText</span><span class="hl opt">(</span><span class="hl kwc">QString</span><span class="hl opt">::</span><span class="hl kwd">fromStdString</span><span class="hl opt">(</span>cameraName<span class="hl opt">));</span> <span class="hl kwa">return</span> <span class="hl num">0</span><span class="hl opt">;</span> <span class="hl opt">}</span> <span class="hl com">/* -----------------------------------------------------------------------------</span> <span class="hl com"> * Capture Start & Stop</span> <span class="hl com"> */</span> <span class="hl kwb">void</span> <span class="hl kwc">MainWindow</span><span class="hl opt">::</span><span class="hl kwd">toggleCapture</span><span class="hl opt">(</span><span class="hl kwb">bool</span> start<span class="hl opt">)</span> <span class="hl opt">{</span> <span class="hl kwa">if</span> <span class="hl opt">(</span>start<span class="hl opt">) {</span> <span class="hl kwd">startCapture</span><span class="hl opt">();</span> startStopAction_<span class="hl opt">-></span><span class="hl kwd">setIcon</span><span class="hl opt">(</span>iconStop_<span class="hl opt">);</span> startStopAction_<span class="hl opt">-></span><span class="hl kwd">setText</span><span class="hl opt">(</span><span class="hl str">"Stop Capture"</span><span class="hl opt">);</span> <span class="hl opt">}</span> <span class="hl kwa">else</span> <span class="hl opt">{</span> <span class="hl kwd">stopCapture</span><span class="hl opt">();</span> startStopAction_<span class="hl opt">-></span><span class="hl kwd">setIcon</span><span class="hl opt">(</span>iconPlay_<span class="hl opt">);</span> startStopAction_<span class="hl opt">-></span><span class="hl kwd">setText</span><span class="hl opt">(</span><span class="hl str">"Start Capture"</span><span class="hl opt">);</span> <span class="hl opt">}</span> <span class="hl opt">}</span> <span class="hl com">/**</span> <span class="hl com"> * \brief Start capture with the current camera</span> <span class="hl com"> *</span> <span class="hl com"> * This function shall not be called directly, use toggleCapture() instead.</span> <span class="hl com"> */</span> <span class="hl kwb">int</span> <span class="hl kwc">MainWindow</span><span class="hl opt">::</span><span class="hl kwd">startCapture</span><span class="hl opt">()</span> <span class="hl opt">{</span> StreamRoles roles <span class="hl opt">=</span> <span class="hl kwc">StreamKeyValueParser</span><span class="hl opt">::</span><span class="hl kwd">roles</span><span class="hl opt">(</span>options_<span class="hl opt">[</span>OptStream<span class="hl opt">]);</span> <span class="hl kwb">int</span> ret<span class="hl opt">;</span> <span class="hl com">/* Verify roles are supported. */</span> <span class="hl kwa">switch</span> <span class="hl opt">(</span>roles<span class="hl opt">.</span><span class="hl kwd">size</span><span class="hl opt">()) {</span> <span class="hl kwa">case</span> <span class="hl num">1</span><span class="hl opt">:</span> <span class="hl kwa">if</span> <span class="hl opt">(</span>roles<span class="hl opt">[</span><span class="hl num">0</span><span class="hl opt">] !=</span> <span class="hl kwc">StreamRole</span><span class="hl opt">::</span>Viewfinder<span class="hl opt">) {</span> <span class="hl kwd">qWarning</span><span class="hl opt">() <<</span> <span class="hl str">"Only viewfinder supported for single stream"</span><span class="hl opt">;</span> <span class="hl kwa">return</span> <span class="hl opt">-</span>EINVAL<span class="hl opt">;</span> <span class="hl opt">}</span> <span class="hl kwa">break</span><span class="hl opt">;</span> <span class="hl kwa">case</span> <span class="hl num">2</span><span class="hl opt">:</span> <span class="hl kwa">if</span> <span class="hl opt">(</span>roles<span class="hl opt">[</span><span class="hl num">0</span><span class="hl opt">] !=</span> <span class="hl kwc">StreamRole</span><span class="hl opt">::</span>Viewfinder <span class="hl opt">||