mirror of
				https://github.com/hyperion-project/hyperion.ng.git
				synced 2025-03-01 10:33:28 +00:00 
			
		
		
		
	Merge pull request #458 from Paulchen-Panther/master
Replace XGetImage with XShmGetImage Former-commit-id: a40813e1c19b09b2d8f1cd5f6837bf7b2651e7a8
This commit is contained in:
		
							
								
								
									
										12
									
								
								effects/police-lights-single.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										12
									
								
								effects/police-lights-single.json
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,12 @@ | |||||||
|  | { | ||||||
|  | 	"name" : "Police Lights Single", | ||||||
|  | 	"script" : "police.py", | ||||||
|  | 	"args" : | ||||||
|  | 	{ | ||||||
|  | 		"rotation-time" : 1.5, | ||||||
|  | 		"color_one" : [ 255, 0, 0 ], | ||||||
|  | 		"color_two" : [ 0, 0, 255 ], | ||||||
|  | 		"colors_count" : 10, | ||||||
|  | 		"reverse" : false | ||||||
|  | 	} | ||||||
|  | } | ||||||
							
								
								
									
										11
									
								
								effects/police-lights-solid.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										11
									
								
								effects/police-lights-solid.json
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,11 @@ | |||||||
|  | { | ||||||
|  | 	"name" : "Police Lights Solid", | ||||||
|  | 	"script" : "police.py", | ||||||
|  | 	"args" : | ||||||
|  | 	{ | ||||||
|  | 		"rotation-time" : 1.0, | ||||||
|  | 		"color_one" : [ 255, 0, 0 ], | ||||||
|  | 		"color_two" : [ 0, 0, 255 ], | ||||||
|  | 		"reverse" : false | ||||||
|  | 	} | ||||||
|  | } | ||||||
							
								
								
									
										46
									
								
								effects/police.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										46
									
								
								effects/police.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,46 @@ | |||||||
|  | import hyperion | ||||||
|  | import time | ||||||
|  | import colorsys | ||||||
|  |  | ||||||
|  | # Get the parameters | ||||||
|  | rotationTime = float(hyperion.args.get('rotation-time', 2.0)) | ||||||
|  | colorOne = hyperion.args.get('color_one', (255,0,0)) | ||||||
|  | colorTwo = hyperion.args.get('color_two', (0,0,255)) | ||||||
|  | colorsCount = hyperion.args.get('colors_count', hyperion.ledCount/2) | ||||||
|  | reverse = bool(hyperion.args.get('reverse', False)) | ||||||
|  |  | ||||||
|  | # Check parameters | ||||||
|  | rotationTime = max(0.1, rotationTime) | ||||||
|  | colorsCount = min(hyperion.ledCount/2, colorsCount) | ||||||
|  |  | ||||||
|  | # Initialize the led data | ||||||
|  | hsv1 = colorsys.rgb_to_hsv(colorOne[0]/255.0, colorOne[1]/255.0, colorOne[2]/255.0) | ||||||
|  | hsv2 = colorsys.rgb_to_hsv(colorTwo[0]/255.0, colorTwo[1]/255.0, colorTwo[2]/255.0) | ||||||
|  | colorBlack = (0,0,0) | ||||||
|  | ledData = bytearray() | ||||||
|  | for i in range(hyperion.ledCount): | ||||||
|  | 	if i <= colorsCount: | ||||||
|  | 		rgb = colorsys.hsv_to_rgb(hsv1[0], hsv1[1], hsv1[2]) | ||||||
|  | 	elif (i >= hyperion.ledCount/2-1) & (i < (hyperion.ledCount/2) + colorsCount): | ||||||
|  | 		rgb = colorsys.hsv_to_rgb(hsv2[0], hsv2[1], hsv2[2]) | ||||||
|  | 	else: | ||||||
|  | 		rgb = colorBlack | ||||||
|  | 	ledData += bytearray((int(255*rgb[0]), int(255*rgb[1]), int(255*rgb[2]))) | ||||||
|  |  | ||||||
|  | # Calculate the sleep time and rotation increment | ||||||
|  | increment = 3 | ||||||
|  | sleepTime = rotationTime / hyperion.ledCount | ||||||
|  | while sleepTime < 0.05: | ||||||
|  | 	increment *= 2 | ||||||
|  | 	sleepTime *= 2 | ||||||
|  | increment %= hyperion.ledCount | ||||||
|  |  | ||||||
|  | # Switch direction if needed | ||||||
|  | if reverse: | ||||||
|  | 	increment = -increment | ||||||
|  | 	 | ||||||
|  | # Start the write data loop | ||||||
|  | while not hyperion.abort(): | ||||||
|  | 	hyperion.setColor(ledData) | ||||||
|  | 	ledData = ledData[-increment:] + ledData[:-increment] | ||||||
|  | 	time.sleep(sleepTime) | ||||||
| @@ -7,6 +7,11 @@ | |||||||
| // X11 includes | // X11 includes | ||||||
| #include <X11/Xlib.h> | #include <X11/Xlib.h> | ||||||
|  |  | ||||||
|  | #include <X11/extensions/Xrender.h> | ||||||
|  | #include <X11/extensions/XShm.h> | ||||||
|  | #include <sys/ipc.h> | ||||||
|  | #include <sys/shm.h> | ||||||
|  |  | ||||||
| class X11Grabber | class X11Grabber | ||||||
| { | { | ||||||
| public: | public: | ||||||
| @@ -16,6 +21,8 @@ public: | |||||||
| 	virtual ~X11Grabber(); | 	virtual ~X11Grabber(); | ||||||
|  |  | ||||||
| 	int open(); | 	int open(); | ||||||
|  | 	 | ||||||
|  | 	bool Setup(); | ||||||
|  |  | ||||||
| 	Image<ColorRgb> & grab(); | 	Image<ColorRgb> & grab(); | ||||||
|  |  | ||||||
| @@ -26,14 +33,24 @@ private: | |||||||
|     int _cropRight; |     int _cropRight; | ||||||
|     int _cropTop; |     int _cropTop; | ||||||
|     int _cropBottom; |     int _cropBottom; | ||||||
|  |      | ||||||
|  |     XImage* _xImage; | ||||||
|  |     XShmSegmentInfo _shminfo; | ||||||
|  |  | ||||||
| 	/// Reference to the X11 display (nullptr if not opened) | 	/// Reference to the X11 display (nullptr if not opened) | ||||||
| 	Display * _x11Display; | 	Display* _x11Display; | ||||||
|  | 	Window _window; | ||||||
|  | 	XWindowAttributes _windowAttr; | ||||||
|  |  | ||||||
| 	unsigned _screenWidth; | 	unsigned _screenWidth; | ||||||
| 	unsigned _screenHeight; | 	unsigned _screenHeight; | ||||||
|  | 	unsigned _croppedWidth; | ||||||
|  | 	unsigned _croppedHeight; | ||||||
|  |  | ||||||
| 	Image<ColorRgb> _image; | 	Image<ColorRgb> _image; | ||||||
|  | 	 | ||||||
|  | 	void freeResources(); | ||||||
|  | 	void setupResources(); | ||||||
|  | 	 | ||||||
| 	int updateScreenDimensions(); | 	int updateScreenDimensions(); | ||||||
| }; | }; | ||||||
|   | |||||||
| @@ -17,82 +17,116 @@ X11Grabber::X11Grabber(int cropLeft, int cropRight, int cropTop, int cropBottom, | |||||||
|     _x11Display(nullptr), |     _x11Display(nullptr), | ||||||
|     _screenWidth(0), |     _screenWidth(0), | ||||||
|     _screenHeight(0), |     _screenHeight(0), | ||||||
|  |     _croppedWidth(0), | ||||||
|  |     _croppedHeight(0), | ||||||
|     _image(0,0) |     _image(0,0) | ||||||
| { | { | ||||||
|     _imageResampler.setHorizontalPixelDecimation(horizontalPixelDecimation); |     _imageResampler.setHorizontalPixelDecimation(horizontalPixelDecimation); | ||||||
|     _imageResampler.setVerticalPixelDecimation(verticalPixelDecimation); |     _imageResampler.setVerticalPixelDecimation(verticalPixelDecimation); | ||||||
|     _imageResampler.setCropping(0, 0, 0, 0); // cropping is performed by XGetImage |     _imageResampler.setCropping(0, 0, 0, 0); // cropping is performed by XShmGetImage | ||||||
| } | } | ||||||
|  |  | ||||||
| X11Grabber::~X11Grabber() | X11Grabber::~X11Grabber() | ||||||
| { | { | ||||||
|     if (_x11Display != nullptr) |     if (_x11Display != nullptr) | ||||||
|     { |     { | ||||||
|  | 	freeResources(); | ||||||
|         XCloseDisplay(_x11Display); |         XCloseDisplay(_x11Display); | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  |  | ||||||
| int X11Grabber::open() | void X11Grabber::freeResources() | ||||||
| { | { | ||||||
|     const char * display_name = nullptr; |     // Cleanup allocated resources of the X11 grab | ||||||
|     _x11Display = XOpenDisplay(display_name); |     XShmDetach(_x11Display, &_shminfo); | ||||||
|  |     XDestroyImage(_xImage); | ||||||
|  |     shmdt(_shminfo.shmaddr); | ||||||
|  |     shmctl(_shminfo.shmid, IPC_RMID, 0); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | void X11Grabber::setupResources() | ||||||
|  | { | ||||||
|  |     _xImage = XShmCreateImage(_x11Display, _windowAttr.visual, | ||||||
|  |                 _windowAttr.depth, ZPixmap, NULL, &_shminfo, | ||||||
|  |                 _croppedWidth, _croppedHeight); | ||||||
|  |      | ||||||
|  |     _shminfo.shmid = shmget(IPC_PRIVATE, _xImage->bytes_per_line * _xImage->height, IPC_CREAT|0777); | ||||||
|  |     _shminfo.shmaddr = _xImage->data = (char*)shmat(_shminfo.shmid,0,0); | ||||||
|  |     _shminfo.readOnly = False; | ||||||
|  |      | ||||||
|  |     XShmAttach(_x11Display, &_shminfo); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | bool X11Grabber::Setup() | ||||||
|  | { | ||||||
|  |     _x11Display = XOpenDisplay(NULL); | ||||||
|     if (_x11Display == nullptr) |     if (_x11Display == nullptr) | ||||||
|     { |     { | ||||||
|         std::cerr << "Failed to open the default X11-display" << std::endl; |       std::cerr << "Unable to open display"; | ||||||
|         return -1; |       if (getenv("DISPLAY")) | ||||||
|     } | 	std::cerr <<  " " << std::string(getenv("DISPLAY")) << std::endl; | ||||||
|  |       else | ||||||
|  | 	std::cerr << ". DISPLAY environment variable not set" << std::endl; | ||||||
|  |       return false; | ||||||
|  |      } | ||||||
|  |       | ||||||
|  |     _window = DefaultRootWindow(_x11Display); | ||||||
|  |  | ||||||
|     return 0; |     return true; | ||||||
| } |  } | ||||||
|  |  | ||||||
| Image<ColorRgb> & X11Grabber::grab() | Image<ColorRgb> & X11Grabber::grab() | ||||||
| { | { | ||||||
|     if (_x11Display == nullptr) |  | ||||||
|     { |  | ||||||
|         open(); |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     updateScreenDimensions(); |     updateScreenDimensions(); | ||||||
|  |      | ||||||
|     const unsigned croppedWidth  = _screenWidth - _cropLeft - _cropRight; |     XShmGetImage(_x11Display, _window, _xImage, _cropLeft, _cropTop, 0x00FFFFFF); | ||||||
|     const unsigned croppedHeight = _screenHeight - _cropTop - _cropBottom; |     if (_xImage == nullptr) | ||||||
|  |  | ||||||
|     // Capture the current screen |  | ||||||
|     XImage * xImage = XGetImage(_x11Display, DefaultRootWindow(_x11Display), _cropLeft, _cropTop, croppedWidth, croppedHeight, AllPlanes, ZPixmap); |  | ||||||
|     if (xImage == nullptr) |  | ||||||
|     { |     { | ||||||
|         std::cerr << "Grab failed" << std::endl; |         std::cerr << "Grab failed" << std::endl; | ||||||
|         return _image; |         return _image; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     _imageResampler.processImage(reinterpret_cast<const uint8_t *>(xImage->data), xImage->width, xImage->height, xImage->bytes_per_line, PIXELFORMAT_BGR32, _image); |     _imageResampler.processImage(reinterpret_cast<const uint8_t *>(_xImage->data), _xImage->width, _xImage->height, _xImage->bytes_per_line, PIXELFORMAT_BGR32, _image); | ||||||
|  |  | ||||||
|     // Cleanup allocated resources of the X11 grab |  | ||||||
|     XDestroyImage(xImage); |  | ||||||
|  |  | ||||||
|     return _image; |     return _image; | ||||||
| } | } | ||||||
|  |  | ||||||
| int X11Grabber::updateScreenDimensions() | int X11Grabber::updateScreenDimensions() | ||||||
| { | { | ||||||
|     XWindowAttributes window_attributes_return; |     const Status status = XGetWindowAttributes(_x11Display, _window, &_windowAttr); | ||||||
|     const Status status = XGetWindowAttributes(_x11Display, DefaultRootWindow(_x11Display), &window_attributes_return); |  | ||||||
|     if (status == 0) |     if (status == 0) | ||||||
|     { |     { | ||||||
|         std::cerr << "Failed to obtain window attributes" << std::endl; |         std::cerr << "Failed to obtain window attributes" << std::endl; | ||||||
|         return -1; |         return -1; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     if (_screenWidth == unsigned(window_attributes_return.width) && _screenHeight == unsigned(window_attributes_return.height)) |     if (_screenWidth == unsigned(_windowAttr.width) && _screenHeight == unsigned(_windowAttr.height)) | ||||||
|     { |     { | ||||||
|         // No update required |         // No update required | ||||||
|         return 0; |         return 0; | ||||||
|     } |     } | ||||||
|  |      | ||||||
|     std::cout << "Update of screen resolution: [" << _screenWidth << "x" << _screenHeight <<"] => "; |     std::cout << "Update of screen resolution: [" << _screenWidth << "x" << _screenHeight <<"] => "; | ||||||
|     _screenWidth  = window_attributes_return.width; |  | ||||||
|     _screenHeight = window_attributes_return.height; |     if (_screenWidth || _screenHeight) | ||||||
|  |       freeResources(); | ||||||
|  |      | ||||||
|  |     _screenWidth  = _windowAttr.width; | ||||||
|  |     _screenHeight = _windowAttr.height; | ||||||
|  |      | ||||||
|     std::cout << "[" << _screenWidth << "x" << _screenHeight <<"]" << std::endl; |     std::cout << "[" << _screenWidth << "x" << _screenHeight <<"]" << std::endl; | ||||||
|  |      | ||||||
|  |     if (_screenWidth > unsigned(_cropLeft + _cropRight)) | ||||||
|  |       _croppedWidth  = _screenWidth - _cropLeft - _cropRight; | ||||||
|  |     else | ||||||
|  |       _croppedWidth  = _screenWidth; | ||||||
|  |      | ||||||
|  |     if (_screenHeight > unsigned(_cropTop + _cropBottom)) | ||||||
|  |       _croppedHeight = _screenHeight - _cropTop - _cropBottom; | ||||||
|  |     else | ||||||
|  |       _croppedHeight = _screenHeight; | ||||||
|  |      | ||||||
|  |     setupResources(); | ||||||
|  |  | ||||||
|     return 0; |     return 0; | ||||||
| } | } | ||||||
|   | |||||||
| @@ -29,6 +29,11 @@ void X11Wrapper::stop() | |||||||
|     _timer.stop(); |     _timer.stop(); | ||||||
| } | } | ||||||
|  |  | ||||||
|  | bool X11Wrapper::displayInit() | ||||||
|  | { | ||||||
|  |     return _grabber.Setup(); | ||||||
|  | } | ||||||
|  |  | ||||||
| void X11Wrapper::capture() | void X11Wrapper::capture() | ||||||
| { | { | ||||||
|     const Image<ColorRgb> & screenshot = _grabber.grab(); |     const Image<ColorRgb> & screenshot = _grabber.grab(); | ||||||
|   | |||||||
| @@ -19,6 +19,8 @@ public: | |||||||
|     void start(); |     void start(); | ||||||
|  |  | ||||||
|     void stop(); |     void stop(); | ||||||
|  |      | ||||||
|  |     bool displayInit(); | ||||||
|  |  | ||||||
| signals: | signals: | ||||||
|     void sig_screenshot(const Image<ColorRgb> & screenshot); |     void sig_screenshot(const Image<ColorRgb> & screenshot); | ||||||
|   | |||||||
| @@ -77,6 +77,9 @@ int main(int argc, char ** argv) | |||||||
|                     argCropBottom.getValue(), |                     argCropBottom.getValue(), | ||||||
|                     argSizeDecimation.getValue(), // horizontal decimation |                     argSizeDecimation.getValue(), // horizontal decimation | ||||||
|                     argSizeDecimation.getValue()); // vertical decimation |                     argSizeDecimation.getValue()); // vertical decimation | ||||||
|  | 	 | ||||||
|  | 	if (!x11Wrapper.displayInit()) | ||||||
|  | 	  return -1; | ||||||
|  |  | ||||||
|         if (argScreenshot.isSet()) |         if (argScreenshot.isSet()) | ||||||
|         { |         { | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user